quotacheck.c
来自「<B>Digital的Unix操作系统VAX 4.2源码</B>」· C语言 代码 · 共 399 行
C
399 行
#ifndef lintstatic char sccsid[] = "@(#)quotacheck.c 4.2 2/12/91";#endif/* * Fix up / report on disc quotas & usage *//************************************************************************ * * * Copyright (c) 1984 by * * Digital Equipment Corporation, Maynard, MA * * All rights reserved. * * * * This software is furnished under a license and may be used and * * copied only in accordance with the terms of such license and * * with the inclusion of the above copyright notice. This * * software or any other copies thereof may not be provided or * * otherwise made available to any other person. No title to and * * ownership of the software is hereby transferred. * * * * This software is derived from software received from the * * University of California, Berkeley, and from Bell * * Laboratories. Use, duplication, or disclosure is subject to * * restrictions under license agreements with University of * * California and with AT&T. * * * * The information in this software is subject to change without * * notice and should not be construed as a commitment by Digital * * Equipment Corporation. * * * * Digital assumes no responsibility for the use or reliability * * of its software on equipment which is not supplied by Digital. * * * ************************************************************************//************************************************************************ * * Modification History * * dws -- 11-Feb-91 * Cleaned up code to read from character instead of block device. * Fixed bu in handling of inode table. * * Paul Shaughnessy, 14-Jul-87 * 002- Added logic to zero out quota file entry for a user that * no longer has any files. * * Stephen Reilly, 28-Nov-84 * 001- A the switch -f that will force quotacheck to create a quotas * file. * * 4.4 (Berkeley, Melbourne) 6/22/83 ***********************************************************************/#include <stdio.h>#include <ctype.h>#include <signal.h>#include <sys/param.h>#include <sys/inode.h>#include <sys/fs.h>#include <sys/quota.h>#include <sys/stat.h>#include <fstab.h>#include <pwd.h>union { struct fs sblk; char dummy[MAXBSIZE];} un;#define sblock un.sblkstruct dinode itab[MAXIPG];struct dinode *dp;long blocks;dev_t dev;#define LOGINNAMESIZE 8struct fileusage { struct fileusage *fu_next; struct dqusage fu_usage; u_short fu_uid; char fu_name[LOGINNAMESIZE + 1];};#define FUHASH 997struct fileusage *fuhead[FUHASH];struct fileusage *lookup();struct fileusage *adduid();int highuid;int fi;ino_t ino;long done;struct passwd *getpwent();struct dinode *ginode();char *malloc(), *makerawname();int vflag; /* verbose */int aflag; /* all file systems */int fflag; /* 001 force us to create the quotas file */char *qfname = "quotas";char quotafile[MAXPATHLEN + 1];struct dqblk zerodqbuf;main(argc, argv) int argc; char **argv;{ register struct fstab *fs; register struct fileusage *fup; register struct passwd *pw; int i, errs = 0;again: argc--, argv++; if (argc > 0 && strcmp(*argv, "-v") == 0) { vflag++; goto again; } if (argc > 0 && strcmp(*argv, "-a") == 0) { aflag++; goto again; } if (argc > 0 && strcmp(*argv, "-f") == 0) { /* 001 */ fflag++; /* 001 */ goto again; /* 001 */ } if (argc <= 0 && !aflag) { fprintf(stderr, "Usage:\n\t%s\n\t%s\n", "quotacheck [-v] -a", "quotacheck [-v] filesys ..."); exit(1); } if (vflag) { setpwent(); while ((pw = getpwent()) != 0) { fup = lookup(pw->pw_uid); if (fup == 0) fup = adduid(pw->pw_uid); strncpy(fup->fu_name, pw->pw_name, sizeof(fup->fu_name)); } endpwent(); } setfsent(); while ((fs = getfsent()) != NULL) { if (aflag && (fs->fs_type == 0 || strcmp(fs->fs_type, "rq") != 0)) continue; if (!aflag && !(oneof(fs->fs_file, argv, argc) || oneof(fs->fs_spec, argv, argc))) continue; (void) sprintf(quotafile, "%s/%s", fs->fs_file, qfname); errs += chkquota(fs->fs_spec, quotafile); } endfsent(); for (i = 0; i < argc; i++) if ((done & (1 << i)) == 0) fprintf(stderr, "%s not found in /etc/fstab\n", argv[i]); exit(errs);}chkquota(fsdev, qffile) char *fsdev; char *qffile;{ register struct fileusage *fup; struct fileusage zerofupbuf; /* Empty fileusage entry */ dev_t quotadev; FILE *qf; u_short uid; int cg, i; char *rawdisk; struct stat statb; struct dqblk dqbuf; if (stat(fsdev, &statb) < 0) { perror(fsdev); return (1); } if ((statb.st_mode & GFMT) == S_IFCHR) { rawdisk = fsdev; } else if ((statb.st_mode & GFMT) == S_IFBLK) { rawdisk = makerawname(fsdev); } else { fprintf(stderr, "Bad device type %s\n", fsdev); return (1); } if (vflag) fprintf(stdout, "*** Check quotas for %s\n", rawdisk); fi = open(rawdisk, 0); if (fi < 0) { perror(rawdisk); return (1); } qf = fopen(qffile, "r+"); if (qf == NULL) { /* * If the force flag is set then * try creating the file */ if (fflag) /* 001 */ qf = fopen(qffile, "w+"); /* 001 */ if (qf == NULL ) { /* 001 */ perror(qffile); /* 001 */ return (1); /* 001 */ } } if (fstat(fileno(qf), &statb) < 0) { perror(qffile); return (1); } quotadev = statb.st_dev; if (stat(fsdev, &statb) < 0) { perror(fsdev); return (1); } if (quotadev != statb.st_rdev) { fprintf(stderr, "%s dev (0x%x) mismatch %s dev (0x%x)\n", qffile, quotadev, fsdev, statb.st_rdev); return (1); } quota(Q_SYNC, 0, quotadev, 0); sync(); bread(SBLOCK, (char *)&sblock, SBSIZE); ino = 0; for (cg = 0; cg < sblock.fs_ncg; cg++) { dp = NULL; for (i = 0; i < sblock.fs_ipg; i++) acct(ginode()); } for (uid = 0; uid <= highuid; uid++) { fseek(qf, uid * sizeof(struct dqblk), 0); i = fread(&dqbuf, sizeof(struct dqblk), 1, qf); if (i == 0) dqbuf = zerodqbuf; fup = lookup(uid); if (fup == (struct fileusage *)0) { /* * 002 - If no inodes were found for user, then * zero out quota file entry for user if * stale data exists */ if ((dqbuf.dqb_curinodes) || (dqbuf.dqb_curblocks)) { fup = &zerofupbuf; fup->fu_usage.du_curinodes = 0; fup->fu_usage.du_curblocks = 0; } else continue; } if (dqbuf.dqb_curinodes == fup->fu_usage.du_curinodes && dqbuf.dqb_curblocks == fup->fu_usage.du_curblocks) { fup->fu_usage.du_curinodes = 0; fup->fu_usage.du_curblocks = 0; continue; } if (vflag) { if (fup->fu_name[0] != '\0') printf("%-10s fixed:", fup->fu_name); else printf("#%-9d fixed:", uid); fprintf(stdout, " inodes (old %d, new %d)", dqbuf.dqb_curinodes, fup->fu_usage.du_curinodes); fprintf(stdout, " blocks (old %d, new %d)\n", dqbuf.dqb_curblocks, fup->fu_usage.du_curblocks); } dqbuf.dqb_curinodes = fup->fu_usage.du_curinodes; dqbuf.dqb_curblocks = fup->fu_usage.du_curblocks; fseek(qf, uid * sizeof(struct dqblk), 0); fwrite(&dqbuf, sizeof(struct dqblk), 1, qf); quota(Q_SETDUSE, uid, quotadev, &fup->fu_usage); fup->fu_usage.du_curinodes = 0; fup->fu_usage.du_curblocks = 0; } return (0);}acct(ip) register struct dinode *ip;{ register n; register struct fileusage *fup; if (ip == NULL) return; if (ip->di_mode == 0) return; fup = lookup(ip->di_uid); if (fup == 0) fup = adduid(ip->di_uid); fup->fu_usage.du_curinodes++; if ((ip->di_mode & IFMT) == IFCHR || (ip->di_mode & IFMT) == IFBLK) return; fup->fu_usage.du_curblocks += ip->di_blocks;}oneof(target, list, n) char *target, *list[]; register int n;{ register int i; for (i = 0; i < n; i++) if (strcmp(target, list[i]) == 0) { done |= 1 << i; return (1); } return (0);}struct dinode *ginode(){ register unsigned long iblk; if (dp == NULL || ++dp >= &itab[MAXIPG]) { iblk = itod(&sblock, ino); bread(fsbtodb(&sblock, iblk), (char *)itab, sblock.fs_ipg * sizeof (struct dinode)); dp = &itab[ino % INOPB(&sblock)]; } if (ino++ < ROOTINO) return(NULL); return(dp);}bread(bno, buf, cnt) long unsigned bno; char *buf; int cnt;{ int i; lseek(fi, (long)dbtob(bno), 0); if ((i = read(fi, buf, cnt)) != cnt) { printf("read error %u\n", bno); if (i == -1) perror("read"); exit(1); }}struct fileusage *lookup(uid) u_short uid;{ register struct fileusage *fup; for (fup = fuhead[uid % FUHASH]; fup != 0; fup = fup->fu_next) if (fup->fu_uid == uid) return (fup); return ((struct fileusage *)0);}struct fileusage *adduid(uid) u_short uid;{ struct fileusage *fup, **fhp; fup = lookup(uid); if (fup != 0) return (fup); fup = (struct fileusage *)calloc(1, sizeof(struct fileusage)); if (fup == 0) { fprintf(stderr, "out of memory for fileusage structures\n"); exit(1); } fhp = &fuhead[uid % FUHASH]; fup->fu_next = *fhp; *fhp = fup; fup->fu_uid = uid; if (uid > highuid) highuid = uid; return (fup);}char *makerawname(cp) char *cp;{ static char rawbuf[MAXPATHLEN]; char *dp, *rindex(); if ((dp = rindex(cp, '/')) == NULL) return (NULL); *dp = '\0'; (void) strcpy(rawbuf, cp); *dp = '/'; (void) strcat(rawbuf, "/r"); (void) strcat(rawbuf, dp+1); return (rawbuf);}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?