121516Smckusick /* 241408Smckusick * Copyright (c) 1980, 1990 Regents of the University of California. 334362Sbostic * All rights reserved. 434362Sbostic * 541408Smckusick * This code is derived from software contributed to Berkeley by 641408Smckusick * Robert Elz at The University of Melbourne. 741408Smckusick * 842797Sbostic * %sccs.include.redist.c% 921516Smckusick */ 1021516Smckusick 1112707Smckusick #ifndef lint 1221516Smckusick char copyright[] = 1341408Smckusick "@(#) Copyright (c) 1980, 1990 Regents of the University of California.\n\ 1421516Smckusick All rights reserved.\n"; 1534362Sbostic #endif /* not lint */ 1612707Smckusick 1721516Smckusick #ifndef lint 18*51630Sbostic static char sccsid[] = "@(#)edquota.c 5.16 (Berkeley) 11/11/91"; 1934362Sbostic #endif /* not lint */ 2021516Smckusick 2112707Smckusick /* 2212707Smckusick * Disk quota editor. 2312707Smckusick */ 2436964Sbostic #include <sys/param.h> 2536964Sbostic #include <sys/stat.h> 2636964Sbostic #include <sys/file.h> 2741408Smckusick #include <sys/wait.h> 28*51630Sbostic #include <ufs/ufs/quota.h> 2912707Smckusick #include <errno.h> 3036964Sbostic #include <fstab.h> 3112707Smckusick #include <pwd.h> 3241408Smckusick #include <grp.h> 3312707Smckusick #include <ctype.h> 3436964Sbostic #include <stdio.h> 3541408Smckusick #include <string.h> 3637267Sbostic #include "pathnames.h" 3712707Smckusick 3845255Smckusick char *qfname = QUOTAFILENAME; 3945255Smckusick char *qfextension[] = INITQFNAMES; 4045255Smckusick char *quotagroup = QUOTAGROUP; 4141408Smckusick char tmpfil[] = _PATH_TMP; 4212707Smckusick 4341408Smckusick struct quotause { 4441408Smckusick struct quotause *next; 4541408Smckusick long flags; 4641408Smckusick struct dqblk dqblk; 4741408Smckusick char fsname[MAXPATHLEN + 1]; 4841444Smckusick char qfname[1]; /* actually longer */ 4941408Smckusick } *getprivs(); 5041408Smckusick #define FOUND 0x01 5112707Smckusick 5212707Smckusick main(argc, argv) 5341408Smckusick register char **argv; 5441408Smckusick int argc; 5512707Smckusick { 5641408Smckusick register struct quotause *qup, *protoprivs, *curprivs; 5741408Smckusick extern char *optarg; 5841408Smckusick extern int optind; 5941408Smckusick register long id, protoid; 6041408Smckusick register int quotatype, tmpfd; 6141408Smckusick char *protoname, ch; 6241408Smckusick int tflag = 0, pflag = 0; 6312707Smckusick 6441408Smckusick if (argc < 2) 6541408Smckusick usage(); 6612707Smckusick if (getuid()) { 6741408Smckusick fprintf(stderr, "edquota: permission denied\n"); 6812707Smckusick exit(1); 6912707Smckusick } 7041408Smckusick quotatype = USRQUOTA; 7141408Smckusick while ((ch = getopt(argc, argv, "ugtp:")) != EOF) { 7241408Smckusick switch(ch) { 7341408Smckusick case 'p': 7441408Smckusick protoname = optarg; 7541408Smckusick pflag++; 7641408Smckusick break; 7741408Smckusick case 'g': 7841408Smckusick quotatype = GRPQUOTA; 7941408Smckusick break; 8041408Smckusick case 'u': 8141408Smckusick quotatype = USRQUOTA; 8241408Smckusick break; 8341408Smckusick case 't': 8441408Smckusick tflag++; 8541408Smckusick break; 8641408Smckusick default: 8741408Smckusick usage(); 8841408Smckusick } 8941408Smckusick } 9041408Smckusick argc -= optind; 9141408Smckusick argv += optind; 9241408Smckusick if (pflag) { 9341408Smckusick if ((protoid = getentry(protoname, quotatype)) == -1) 9412803Smckusick exit(1); 9541408Smckusick protoprivs = getprivs(protoid, quotatype); 9641408Smckusick for (qup = protoprivs; qup; qup = qup->next) { 9741408Smckusick qup->dqblk.dqb_btime = 0; 9841408Smckusick qup->dqblk.dqb_itime = 0; 9912803Smckusick } 10012803Smckusick while (argc-- > 0) { 10141408Smckusick if ((id = getentry(*argv++, quotatype)) < 0) 10212803Smckusick continue; 10341408Smckusick putprivs(id, quotatype, protoprivs); 10412803Smckusick } 10512803Smckusick exit(0); 10612803Smckusick } 10741408Smckusick tmpfd = mkstemp(tmpfil); 10841408Smckusick fchown(tmpfd, getuid(), getgid()); 10941408Smckusick if (tflag) { 11041408Smckusick protoprivs = getprivs(0, quotatype); 11141408Smckusick if (writetimes(protoprivs, tmpfd, quotatype) == 0) 11241408Smckusick exit(1); 11341408Smckusick if (editit(tmpfil) && readtimes(protoprivs, tmpfd)) 11441408Smckusick putprivs(0, quotatype, protoprivs); 11541408Smckusick freeprivs(protoprivs); 11641408Smckusick exit(0); 11741408Smckusick } 11841408Smckusick for ( ; argc > 0; argc--, argv++) { 11941408Smckusick if ((id = getentry(*argv, quotatype)) == -1) 12012803Smckusick continue; 12141408Smckusick curprivs = getprivs(id, quotatype); 12241408Smckusick if (writeprivs(curprivs, tmpfd, *argv, quotatype) == 0) 12341408Smckusick continue; 12441408Smckusick if (editit(tmpfil) && readprivs(curprivs, tmpfd)) 12541408Smckusick putprivs(id, quotatype, curprivs); 12641408Smckusick freeprivs(curprivs); 12712803Smckusick } 12841408Smckusick close(tmpfd); 12912707Smckusick unlink(tmpfil); 13012707Smckusick exit(0); 13112707Smckusick } 13212707Smckusick 13341408Smckusick usage() 13441408Smckusick { 13541408Smckusick fprintf(stderr, "%s%s%s%s", 13641408Smckusick "Usage: edquota [-u] [-p username] username ...\n", 13741408Smckusick "\tedquota -g [-p groupname] groupname ...\n", 13841408Smckusick "\tedquota [-u] -t\n", "\tedquota -g -t\n"); 13941408Smckusick exit(1); 14041408Smckusick } 14141408Smckusick 14241408Smckusick /* 14341408Smckusick * This routine converts a name for a particular quota type to 14441408Smckusick * an identifier. This routine must agree with the kernel routine 14541408Smckusick * getinoquota as to the interpretation of quota types. 14641408Smckusick */ 14741408Smckusick getentry(name, quotatype) 14812803Smckusick char *name; 14941408Smckusick int quotatype; 15012707Smckusick { 15112803Smckusick struct passwd *pw; 15241408Smckusick struct group *gr; 15312707Smckusick 15412707Smckusick if (alldigits(name)) 15541408Smckusick return (atoi(name)); 15641408Smckusick switch(quotatype) { 15741408Smckusick case USRQUOTA: 15841408Smckusick if (pw = getpwnam(name)) 15941408Smckusick return (pw->pw_uid); 16012803Smckusick fprintf(stderr, "%s: no such user\n", name); 16141408Smckusick break; 16241408Smckusick case GRPQUOTA: 16341408Smckusick if (gr = getgrnam(name)) 16441408Smckusick return (gr->gr_gid); 16541408Smckusick fprintf(stderr, "%s: no such group\n", name); 16641408Smckusick break; 16741408Smckusick default: 16841408Smckusick fprintf(stderr, "%d: unknown quota type\n", quotatype); 16941408Smckusick break; 17012707Smckusick } 17141408Smckusick sleep(1); 17241408Smckusick return (-1); 17312707Smckusick } 17412707Smckusick 17541408Smckusick /* 17641408Smckusick * Collect the requested quota information. 17741408Smckusick */ 17841408Smckusick struct quotause * 17941408Smckusick getprivs(id, quotatype) 18041408Smckusick register long id; 18141408Smckusick int quotatype; 18212707Smckusick { 18341408Smckusick register struct fstab *fs; 18441408Smckusick register struct quotause *qup, *quptail; 18541408Smckusick struct quotause *quphead; 18641444Smckusick int qcmd, qupsize, fd; 18741444Smckusick char *qfpathname; 18841408Smckusick static int warned = 0; 18941408Smckusick extern int errno; 19041408Smckusick 19141408Smckusick setfsent(); 19241408Smckusick quphead = (struct quotause *)0; 19341408Smckusick qcmd = QCMD(Q_GETQUOTA, quotatype); 19441408Smckusick while (fs = getfsent()) { 19541444Smckusick if (strcmp(fs->fs_vfstype, "ufs")) 19641408Smckusick continue; 19741444Smckusick if (!hasquota(fs, quotatype, &qfpathname)) 19841408Smckusick continue; 19941444Smckusick qupsize = sizeof(*qup) + strlen(qfpathname); 20041444Smckusick if ((qup = (struct quotause *)malloc(qupsize)) == NULL) { 20141408Smckusick fprintf(stderr, "edquota: out of memory\n"); 20241408Smckusick exit(2); 20341408Smckusick } 20441444Smckusick if (quotactl(fs->fs_file, qcmd, id, &qup->dqblk) != 0) { 20541408Smckusick if (errno == EOPNOTSUPP && !warned) { 20641408Smckusick warned++; 20741408Smckusick fprintf(stderr, "Warning: %s\n", 20841408Smckusick "Quotas are not compiled into this kernel"); 20941408Smckusick sleep(3); 21041408Smckusick } 21141444Smckusick if ((fd = open(qfpathname, O_RDONLY)) < 0) { 21241444Smckusick fd = open(qfpathname, O_RDWR|O_CREAT, 0640); 21341444Smckusick if (fd < 0 && errno != ENOENT) { 21441444Smckusick perror(qfpathname); 21541444Smckusick free(qup); 21641444Smckusick continue; 21741444Smckusick } 21841444Smckusick fprintf(stderr, "Creating quota file %s\n", 21941444Smckusick qfpathname); 22041444Smckusick sleep(3); 22141444Smckusick (void) fchown(fd, getuid(), 22241444Smckusick getentry(quotagroup, GRPQUOTA)); 22341444Smckusick (void) fchmod(fd, 0640); 22441444Smckusick } 22541408Smckusick lseek(fd, (long)(id * sizeof(struct dqblk)), L_SET); 22641408Smckusick switch (read(fd, &qup->dqblk, sizeof(struct dqblk))) { 22741408Smckusick case 0: /* EOF */ 22841408Smckusick /* 22941408Smckusick * Convert implicit 0 quota (EOF) 23041408Smckusick * into an explicit one (zero'ed dqblk) 23141408Smckusick */ 23241408Smckusick bzero((caddr_t)&qup->dqblk, 23341408Smckusick sizeof(struct dqblk)); 23441408Smckusick break; 23541408Smckusick 23641408Smckusick case sizeof(struct dqblk): /* OK */ 23741408Smckusick break; 23841408Smckusick 23941408Smckusick default: /* ERROR */ 24041408Smckusick fprintf(stderr, "edquota: read error in "); 24141444Smckusick perror(qfpathname); 24241408Smckusick close(fd); 24341408Smckusick free(qup); 24441408Smckusick continue; 24541408Smckusick } 24641444Smckusick close(fd); 24741408Smckusick } 24841444Smckusick strcpy(qup->qfname, qfpathname); 24941408Smckusick strcpy(qup->fsname, fs->fs_file); 25041408Smckusick if (quphead == NULL) 25141408Smckusick quphead = qup; 25241408Smckusick else 25341408Smckusick quptail->next = qup; 25441408Smckusick quptail = qup; 25541408Smckusick qup->next = 0; 25641408Smckusick } 25741408Smckusick endfsent(); 25841408Smckusick return (quphead); 25941408Smckusick } 26041408Smckusick 26141408Smckusick /* 26241408Smckusick * Store the requested quota information. 26341408Smckusick */ 26441408Smckusick putprivs(id, quotatype, quplist) 26541408Smckusick long id; 26641408Smckusick int quotatype; 26741408Smckusick struct quotause *quplist; 26841408Smckusick { 26941408Smckusick register struct quotause *qup; 27041408Smckusick int qcmd, fd; 27141408Smckusick 27241408Smckusick qcmd = QCMD(Q_SETQUOTA, quotatype); 27341408Smckusick for (qup = quplist; qup; qup = qup->next) { 27441444Smckusick if (quotactl(qup->fsname, qcmd, id, &qup->dqblk) == 0) 27541408Smckusick continue; 27641444Smckusick if ((fd = open(qup->qfname, O_WRONLY)) < 0) { 27741444Smckusick perror(qup->qfname); 27841408Smckusick } else { 27941408Smckusick lseek(fd, (long)id * (long)sizeof (struct dqblk), 0); 28041408Smckusick if (write(fd, &qup->dqblk, sizeof (struct dqblk)) != 28141408Smckusick sizeof (struct dqblk)) { 28241408Smckusick fprintf(stderr, "edquota: "); 28341444Smckusick perror(qup->qfname); 28441408Smckusick } 28541408Smckusick close(fd); 28641408Smckusick } 28741408Smckusick } 28841408Smckusick } 28941408Smckusick 29041408Smckusick /* 29141408Smckusick * Take a list of priviledges and get it edited. 29241408Smckusick */ 29341408Smckusick editit(tmpfile) 29441408Smckusick char *tmpfile; 29541408Smckusick { 29633609Sbostic long omask; 29741408Smckusick int pid, stat; 29841408Smckusick extern char *getenv(); 29912707Smckusick 30033609Sbostic omask = sigblock(sigmask(SIGINT)|sigmask(SIGQUIT)|sigmask(SIGHUP)); 30112707Smckusick top: 30212707Smckusick if ((pid = fork()) < 0) { 30312707Smckusick extern errno; 30412707Smckusick 30512707Smckusick if (errno == EPROCLIM) { 30612707Smckusick fprintf(stderr, "You have too many processes\n"); 30712707Smckusick return(0); 30812707Smckusick } 30912707Smckusick if (errno == EAGAIN) { 31012707Smckusick sleep(1); 31112707Smckusick goto top; 31212707Smckusick } 31312707Smckusick perror("fork"); 31412707Smckusick return (0); 31512707Smckusick } 31612707Smckusick if (pid == 0) { 31712707Smckusick register char *ed; 31812707Smckusick 31913025Ssam sigsetmask(omask); 32012707Smckusick setgid(getgid()); 32112707Smckusick setuid(getuid()); 32212707Smckusick if ((ed = getenv("EDITOR")) == (char *)0) 32337976Sbostic ed = _PATH_VI; 32441408Smckusick execlp(ed, ed, tmpfile, 0); 32512707Smckusick perror(ed); 32612707Smckusick exit(1); 32712707Smckusick } 32841408Smckusick waitpid(pid, &stat, 0); 32913025Ssam sigsetmask(omask); 33041408Smckusick if (!WIFEXITED(stat) || WEXITSTATUS(stat) != 0) 33141408Smckusick return (0); 33241408Smckusick return (1); 33312707Smckusick } 33412707Smckusick 33541408Smckusick /* 33641408Smckusick * Convert a quotause list to an ASCII file. 33741408Smckusick */ 33841408Smckusick writeprivs(quplist, outfd, name, quotatype) 33941408Smckusick struct quotause *quplist; 34041408Smckusick int outfd; 34141408Smckusick char *name; 34241408Smckusick int quotatype; 34312707Smckusick { 34441408Smckusick register struct quotause *qup; 34512707Smckusick FILE *fd; 34612707Smckusick 34743266Smckusick ftruncate(outfd, 0); 34841408Smckusick lseek(outfd, 0, L_SET); 34941408Smckusick if ((fd = fdopen(dup(outfd), "w")) == NULL) { 35012707Smckusick fprintf(stderr, "edquota: "); 35112707Smckusick perror(tmpfil); 35212707Smckusick exit(1); 35312707Smckusick } 35441408Smckusick fprintf(fd, "Quotas for %s %s:\n", qfextension[quotatype], name); 35541408Smckusick for (qup = quplist; qup; qup = qup->next) { 35641408Smckusick fprintf(fd, "%s: %s %d, limits (soft = %d, hard = %d)\n", 35741408Smckusick qup->fsname, "blocks in use:", 35841408Smckusick dbtob(qup->dqblk.dqb_curblocks) / 1024, 35941408Smckusick dbtob(qup->dqblk.dqb_bsoftlimit) / 1024, 36041408Smckusick dbtob(qup->dqblk.dqb_bhardlimit) / 1024); 36141408Smckusick fprintf(fd, "%s %d, limits (soft = %d, hard = %d)\n", 36241408Smckusick "\tinodes in use:", qup->dqblk.dqb_curinodes, 36341408Smckusick qup->dqblk.dqb_isoftlimit, qup->dqblk.dqb_ihardlimit); 36412707Smckusick } 36512707Smckusick fclose(fd); 36641408Smckusick return (1); 36712707Smckusick } 36812707Smckusick 36941408Smckusick /* 37041408Smckusick * Merge changes to an ASCII file into a quotause list. 37141408Smckusick */ 37241408Smckusick readprivs(quplist, infd) 37341408Smckusick struct quotause *quplist; 37441408Smckusick int infd; 37512707Smckusick { 37641408Smckusick register struct quotause *qup; 37712707Smckusick FILE *fd; 37841408Smckusick int cnt; 37941408Smckusick register char *cp; 38041408Smckusick struct dqblk dqblk; 38141408Smckusick char *fsp, line1[BUFSIZ], line2[BUFSIZ]; 38212707Smckusick 38341408Smckusick lseek(infd, 0, L_SET); 38441408Smckusick fd = fdopen(dup(infd), "r"); 38512707Smckusick if (fd == NULL) { 38612707Smckusick fprintf(stderr, "Can't re-read temp file!!\n"); 38741408Smckusick return (0); 38812707Smckusick } 38941408Smckusick /* 39041408Smckusick * Discard title line, then read pairs of lines to process. 39141408Smckusick */ 39241408Smckusick (void) fgets(line1, sizeof (line1), fd); 39341408Smckusick while (fgets(line1, sizeof (line1), fd) != NULL && 39441408Smckusick fgets(line2, sizeof (line2), fd) != NULL) { 39541408Smckusick if ((fsp = strtok(line1, " \t:")) == NULL) { 39641408Smckusick fprintf(stderr, "%s: bad format\n", line1); 39741408Smckusick return (0); 39841408Smckusick } 39941408Smckusick if ((cp = strtok((char *)0, "\n")) == NULL) { 40041408Smckusick fprintf(stderr, "%s: %s: bad format\n", fsp, 40141408Smckusick &fsp[strlen(fsp) + 1]); 40241408Smckusick return (0); 40341408Smckusick } 40441408Smckusick cnt = sscanf(cp, 40541408Smckusick " blocks in use: %d, limits (soft = %d, hard = %d)", 40641408Smckusick &dqblk.dqb_curblocks, &dqblk.dqb_bsoftlimit, 40741408Smckusick &dqblk.dqb_bhardlimit); 40841408Smckusick if (cnt != 3) { 40941408Smckusick fprintf(stderr, "%s:%s: bad format\n", fsp, cp); 41041408Smckusick return (0); 41141408Smckusick } 41241408Smckusick dqblk.dqb_curblocks = btodb(dqblk.dqb_curblocks * 1024); 41341408Smckusick dqblk.dqb_bsoftlimit = btodb(dqblk.dqb_bsoftlimit * 1024); 41441408Smckusick dqblk.dqb_bhardlimit = btodb(dqblk.dqb_bhardlimit * 1024); 41541408Smckusick if ((cp = strtok(line2, "\n")) == NULL) { 41641408Smckusick fprintf(stderr, "%s: %s: bad format\n", fsp, line2); 41741408Smckusick return (0); 41841408Smckusick } 41941408Smckusick cnt = sscanf(cp, 42041408Smckusick "\tinodes in use: %d, limits (soft = %d, hard = %d)", 42141408Smckusick &dqblk.dqb_curinodes, &dqblk.dqb_isoftlimit, 42241408Smckusick &dqblk.dqb_ihardlimit); 42341408Smckusick if (cnt != 3) { 42441408Smckusick fprintf(stderr, "%s: %s: bad format\n", fsp, line2); 42541408Smckusick return (0); 42641408Smckusick } 42741408Smckusick for (qup = quplist; qup; qup = qup->next) { 42841408Smckusick if (strcmp(fsp, qup->fsname)) 42941408Smckusick continue; 43041408Smckusick /* 43141408Smckusick * Cause time limit to be reset when the quota 43241408Smckusick * is next used if previously had no soft limit 43341408Smckusick * or were under it, but now have a soft limit 43441408Smckusick * and are over it. 43541408Smckusick */ 43641408Smckusick if (dqblk.dqb_bsoftlimit && 43741408Smckusick qup->dqblk.dqb_curblocks >= dqblk.dqb_bsoftlimit && 43841408Smckusick (qup->dqblk.dqb_bsoftlimit == 0 || 43941408Smckusick qup->dqblk.dqb_curblocks < 44041408Smckusick qup->dqblk.dqb_bsoftlimit)) 44141408Smckusick qup->dqblk.dqb_btime = 0; 44241408Smckusick if (dqblk.dqb_isoftlimit && 44341408Smckusick qup->dqblk.dqb_curinodes >= dqblk.dqb_isoftlimit && 44441408Smckusick (qup->dqblk.dqb_isoftlimit == 0 || 44541408Smckusick qup->dqblk.dqb_curinodes < 44641408Smckusick qup->dqblk.dqb_isoftlimit)) 44741408Smckusick qup->dqblk.dqb_itime = 0; 44841408Smckusick qup->dqblk.dqb_bsoftlimit = dqblk.dqb_bsoftlimit; 44941408Smckusick qup->dqblk.dqb_bhardlimit = dqblk.dqb_bhardlimit; 45041408Smckusick qup->dqblk.dqb_isoftlimit = dqblk.dqb_isoftlimit; 45141408Smckusick qup->dqblk.dqb_ihardlimit = dqblk.dqb_ihardlimit; 45241408Smckusick qup->flags |= FOUND; 45341408Smckusick if (dqblk.dqb_curblocks == qup->dqblk.dqb_curblocks && 45441408Smckusick dqblk.dqb_curinodes == qup->dqblk.dqb_curinodes) 45541408Smckusick break; 45641408Smckusick fprintf(stderr, 45741408Smckusick "%s: cannot change current allocation\n", fsp); 45812707Smckusick break; 45941408Smckusick } 46041408Smckusick } 46141408Smckusick fclose(fd); 46241408Smckusick /* 46341408Smckusick * Disable quotas for any filesystems that have not been found. 46441408Smckusick */ 46541408Smckusick for (qup = quplist; qup; qup = qup->next) { 46641408Smckusick if (qup->flags & FOUND) { 46741408Smckusick qup->flags &= ~FOUND; 46812716Smckusick continue; 46912716Smckusick } 47041408Smckusick qup->dqblk.dqb_bsoftlimit = 0; 47141408Smckusick qup->dqblk.dqb_bhardlimit = 0; 47241408Smckusick qup->dqblk.dqb_isoftlimit = 0; 47341408Smckusick qup->dqblk.dqb_ihardlimit = 0; 47412707Smckusick } 47541408Smckusick return (1); 47641408Smckusick } 47741408Smckusick 47841408Smckusick /* 47941408Smckusick * Convert a quotause list to an ASCII file of grace times. 48041408Smckusick */ 48141408Smckusick writetimes(quplist, outfd, quotatype) 48241408Smckusick struct quotause *quplist; 48341408Smckusick int outfd; 48441408Smckusick int quotatype; 48541408Smckusick { 48641408Smckusick register struct quotause *qup; 48741408Smckusick char *cvtstoa(); 48841408Smckusick FILE *fd; 48941408Smckusick 49043266Smckusick ftruncate(outfd, 0); 49141408Smckusick lseek(outfd, 0, L_SET); 49241408Smckusick if ((fd = fdopen(dup(outfd), "w")) == NULL) { 49341408Smckusick fprintf(stderr, "edquota: "); 49441408Smckusick perror(tmpfil); 49541408Smckusick exit(1); 49641408Smckusick } 49741408Smckusick fprintf(fd, "Time units may be: days, hours, minutes, or seconds\n"); 49841408Smckusick fprintf(fd, "Grace period before enforcing soft limits for %ss:\n", 49941408Smckusick qfextension[quotatype]); 50041408Smckusick for (qup = quplist; qup; qup = qup->next) { 50141408Smckusick fprintf(fd, "%s: block grace period: %s, ", 50241408Smckusick qup->fsname, cvtstoa(qup->dqblk.dqb_btime)); 50341408Smckusick fprintf(fd, "file grace period: %s\n", 50441408Smckusick cvtstoa(qup->dqblk.dqb_itime)); 50541408Smckusick } 50612707Smckusick fclose(fd); 50741408Smckusick return (1); 50841408Smckusick } 50941408Smckusick 51041408Smckusick /* 51141408Smckusick * Merge changes of grace times in an ASCII file into a quotause list. 51241408Smckusick */ 51341408Smckusick readtimes(quplist, infd) 51441408Smckusick struct quotause *quplist; 51541408Smckusick int infd; 51641408Smckusick { 51741408Smckusick register struct quotause *qup; 51841408Smckusick FILE *fd; 51941408Smckusick int cnt; 52041408Smckusick register char *cp; 52141408Smckusick time_t itime, btime, iseconds, bseconds; 52241408Smckusick char *fsp, bunits[10], iunits[10], line1[BUFSIZ]; 52341408Smckusick 52441408Smckusick lseek(infd, 0, L_SET); 52541408Smckusick fd = fdopen(dup(infd), "r"); 52641408Smckusick if (fd == NULL) { 52741408Smckusick fprintf(stderr, "Can't re-read temp file!!\n"); 52841408Smckusick return (0); 52941408Smckusick } 53041408Smckusick /* 53141408Smckusick * Discard two title lines, then read lines to process. 53241408Smckusick */ 53341408Smckusick (void) fgets(line1, sizeof (line1), fd); 53441408Smckusick (void) fgets(line1, sizeof (line1), fd); 53541408Smckusick while (fgets(line1, sizeof (line1), fd) != NULL) { 53641408Smckusick if ((fsp = strtok(line1, " \t:")) == NULL) { 53741408Smckusick fprintf(stderr, "%s: bad format\n", line1); 53841408Smckusick return (0); 53941408Smckusick } 54041408Smckusick if ((cp = strtok((char *)0, "\n")) == NULL) { 54141408Smckusick fprintf(stderr, "%s: %s: bad format\n", fsp, 54241408Smckusick &fsp[strlen(fsp) + 1]); 54341408Smckusick return (0); 54441408Smckusick } 54541408Smckusick cnt = sscanf(cp, 54641408Smckusick " block grace period: %d %s file grace period: %d %s", 54741408Smckusick &btime, bunits, &itime, iunits); 54841408Smckusick if (cnt != 4) { 54941408Smckusick fprintf(stderr, "%s:%s: bad format\n", fsp, cp); 55041408Smckusick return (0); 55141408Smckusick } 55241408Smckusick if (cvtatos(btime, bunits, &bseconds) == 0) 55341408Smckusick return (0); 55441408Smckusick if (cvtatos(itime, iunits, &iseconds) == 0) 55541408Smckusick return (0); 55641408Smckusick for (qup = quplist; qup; qup = qup->next) { 55741408Smckusick if (strcmp(fsp, qup->fsname)) 55841408Smckusick continue; 55941408Smckusick qup->dqblk.dqb_btime = bseconds; 56041408Smckusick qup->dqblk.dqb_itime = iseconds; 56141408Smckusick qup->flags |= FOUND; 56212707Smckusick break; 56312707Smckusick } 56441408Smckusick } 56541408Smckusick fclose(fd); 56641408Smckusick /* 56741408Smckusick * reset default grace periods for any filesystems 56841408Smckusick * that have not been found. 56941408Smckusick */ 57041408Smckusick for (qup = quplist; qup; qup = qup->next) { 57141408Smckusick if (qup->flags & FOUND) { 57241408Smckusick qup->flags &= ~FOUND; 57312707Smckusick continue; 57412707Smckusick } 57541408Smckusick qup->dqblk.dqb_btime = 0; 57641408Smckusick qup->dqblk.dqb_itime = 0; 57712707Smckusick } 57841408Smckusick return (1); 57912707Smckusick } 58012707Smckusick 58141408Smckusick /* 58241408Smckusick * Convert seconds to ASCII times. 58341408Smckusick */ 58412707Smckusick char * 58541408Smckusick cvtstoa(time) 58641408Smckusick time_t time; 58712707Smckusick { 58841408Smckusick static char buf[20]; 58912707Smckusick 59041408Smckusick if (time % (24 * 60 * 60) == 0) { 59141408Smckusick time /= 24 * 60 * 60; 59241408Smckusick sprintf(buf, "%d day%s", time, time == 1 ? "" : "s"); 59341408Smckusick } else if (time % (60 * 60) == 0) { 59441408Smckusick time /= 60 * 60; 59541408Smckusick sprintf(buf, "%d hour%s", time, time == 1 ? "" : "s"); 59641408Smckusick } else if (time % 60 == 0) { 59741408Smckusick time /= 60; 59841408Smckusick sprintf(buf, "%d minute%s", time, time == 1 ? "" : "s"); 59941408Smckusick } else 60041408Smckusick sprintf(buf, "%d second%s", time, time == 1 ? "" : "s"); 60141408Smckusick return (buf); 60241408Smckusick } 60341408Smckusick 60441408Smckusick /* 60541408Smckusick * Convert ASCII input times to seconds. 60641408Smckusick */ 60741408Smckusick cvtatos(time, units, seconds) 60841408Smckusick time_t time; 60941408Smckusick char *units; 61041408Smckusick time_t *seconds; 61141408Smckusick { 61241408Smckusick 61341408Smckusick if (bcmp(units, "second", 6) == 0) 61441408Smckusick *seconds = time; 61541408Smckusick else if (bcmp(units, "minute", 6) == 0) 61641408Smckusick *seconds = time * 60; 61741408Smckusick else if (bcmp(units, "hour", 4) == 0) 61841408Smckusick *seconds = time * 60 * 60; 61941408Smckusick else if (bcmp(units, "day", 3) == 0) 62041408Smckusick *seconds = time * 24 * 60 * 60; 62141408Smckusick else { 62241408Smckusick printf("%s: bad units, specify %s\n", units, 62341408Smckusick "days, hours, minutes, or seconds"); 62441408Smckusick return (0); 62512707Smckusick } 62641408Smckusick return (1); 62712707Smckusick } 62812707Smckusick 62941408Smckusick /* 63041408Smckusick * Free a list of quotause structures. 63141408Smckusick */ 63241408Smckusick freeprivs(quplist) 63341408Smckusick struct quotause *quplist; 63441408Smckusick { 63541408Smckusick register struct quotause *qup, *nextqup; 63641408Smckusick 63741408Smckusick for (qup = quplist; qup; qup = nextqup) { 63841408Smckusick nextqup = qup->next; 63941408Smckusick free(qup); 64041408Smckusick } 64141408Smckusick } 64241408Smckusick 64341408Smckusick /* 64441408Smckusick * Check whether a string is completely composed of digits. 64541408Smckusick */ 64612707Smckusick alldigits(s) 64712707Smckusick register char *s; 64812707Smckusick { 64912707Smckusick register c; 65012707Smckusick 65112707Smckusick c = *s++; 65212707Smckusick do { 65312707Smckusick if (!isdigit(c)) 65412707Smckusick return (0); 65512707Smckusick } while (c = *s++); 65612707Smckusick return (1); 65712707Smckusick } 65812707Smckusick 65941408Smckusick /* 66041408Smckusick * Check to see if a particular quota is to be enabled. 66141408Smckusick */ 66241444Smckusick hasquota(fs, type, qfnamep) 66341444Smckusick register struct fstab *fs; 66441408Smckusick int type; 66541444Smckusick char **qfnamep; 66612707Smckusick { 66741408Smckusick register char *opt; 66841444Smckusick char *cp, *index(), *strtok(); 66941408Smckusick static char initname, usrname[100], grpname[100]; 67041444Smckusick static char buf[BUFSIZ]; 67112707Smckusick 67241408Smckusick if (!initname) { 67341408Smckusick sprintf(usrname, "%s%s", qfextension[USRQUOTA], qfname); 67441408Smckusick sprintf(grpname, "%s%s", qfextension[GRPQUOTA], qfname); 67541408Smckusick initname = 1; 67612707Smckusick } 67741444Smckusick strcpy(buf, fs->fs_mntops); 67841408Smckusick for (opt = strtok(buf, ","); opt; opt = strtok(NULL, ",")) { 67941444Smckusick if (cp = index(opt, '=')) 68041444Smckusick *cp++ = '\0'; 68141408Smckusick if (type == USRQUOTA && strcmp(opt, usrname) == 0) 68241444Smckusick break; 68341408Smckusick if (type == GRPQUOTA && strcmp(opt, grpname) == 0) 68441444Smckusick break; 68512707Smckusick } 68641444Smckusick if (!opt) 68741444Smckusick return (0); 68841444Smckusick if (cp) { 68941444Smckusick *qfnamep = cp; 69041444Smckusick return (1); 69141444Smckusick } 69241444Smckusick (void) sprintf(buf, "%s/%s.%s", fs->fs_file, qfname, qfextension[type]); 69341444Smckusick *qfnamep = buf; 69441444Smckusick return (1); 69512707Smckusick } 696