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*60135Sbostic static char sccsid[] = "@(#)edquota.c 5.17 (Berkeley) 05/19/93"; 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> 2851630Sbostic #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> 36*60135Sbostic #include <unistd.h> 3737267Sbostic #include "pathnames.h" 3812707Smckusick 3945255Smckusick char *qfname = QUOTAFILENAME; 4045255Smckusick char *qfextension[] = INITQFNAMES; 4145255Smckusick char *quotagroup = QUOTAGROUP; 4241408Smckusick char tmpfil[] = _PATH_TMP; 4312707Smckusick 4441408Smckusick struct quotause { 4541408Smckusick struct quotause *next; 4641408Smckusick long flags; 4741408Smckusick struct dqblk dqblk; 4841408Smckusick char fsname[MAXPATHLEN + 1]; 4941444Smckusick char qfname[1]; /* actually longer */ 5041408Smckusick } *getprivs(); 5141408Smckusick #define FOUND 0x01 5212707Smckusick 5312707Smckusick main(argc, argv) 5441408Smckusick register char **argv; 5541408Smckusick int argc; 5612707Smckusick { 5741408Smckusick register struct quotause *qup, *protoprivs, *curprivs; 5841408Smckusick extern char *optarg; 5941408Smckusick extern int optind; 6041408Smckusick register long id, protoid; 6141408Smckusick register int quotatype, tmpfd; 6241408Smckusick char *protoname, ch; 6341408Smckusick int tflag = 0, pflag = 0; 6412707Smckusick 6541408Smckusick if (argc < 2) 6641408Smckusick usage(); 6712707Smckusick if (getuid()) { 6841408Smckusick fprintf(stderr, "edquota: permission denied\n"); 6912707Smckusick exit(1); 7012707Smckusick } 7141408Smckusick quotatype = USRQUOTA; 7241408Smckusick while ((ch = getopt(argc, argv, "ugtp:")) != EOF) { 7341408Smckusick switch(ch) { 7441408Smckusick case 'p': 7541408Smckusick protoname = optarg; 7641408Smckusick pflag++; 7741408Smckusick break; 7841408Smckusick case 'g': 7941408Smckusick quotatype = GRPQUOTA; 8041408Smckusick break; 8141408Smckusick case 'u': 8241408Smckusick quotatype = USRQUOTA; 8341408Smckusick break; 8441408Smckusick case 't': 8541408Smckusick tflag++; 8641408Smckusick break; 8741408Smckusick default: 8841408Smckusick usage(); 8941408Smckusick } 9041408Smckusick } 9141408Smckusick argc -= optind; 9241408Smckusick argv += optind; 9341408Smckusick if (pflag) { 9441408Smckusick if ((protoid = getentry(protoname, quotatype)) == -1) 9512803Smckusick exit(1); 9641408Smckusick protoprivs = getprivs(protoid, quotatype); 9741408Smckusick for (qup = protoprivs; qup; qup = qup->next) { 9841408Smckusick qup->dqblk.dqb_btime = 0; 9941408Smckusick qup->dqblk.dqb_itime = 0; 10012803Smckusick } 10112803Smckusick while (argc-- > 0) { 10241408Smckusick if ((id = getentry(*argv++, quotatype)) < 0) 10312803Smckusick continue; 10441408Smckusick putprivs(id, quotatype, protoprivs); 10512803Smckusick } 10612803Smckusick exit(0); 10712803Smckusick } 10841408Smckusick tmpfd = mkstemp(tmpfil); 10941408Smckusick fchown(tmpfd, getuid(), getgid()); 11041408Smckusick if (tflag) { 11141408Smckusick protoprivs = getprivs(0, quotatype); 11241408Smckusick if (writetimes(protoprivs, tmpfd, quotatype) == 0) 11341408Smckusick exit(1); 11441408Smckusick if (editit(tmpfil) && readtimes(protoprivs, tmpfd)) 11541408Smckusick putprivs(0, quotatype, protoprivs); 11641408Smckusick freeprivs(protoprivs); 11741408Smckusick exit(0); 11841408Smckusick } 11941408Smckusick for ( ; argc > 0; argc--, argv++) { 12041408Smckusick if ((id = getentry(*argv, quotatype)) == -1) 12112803Smckusick continue; 12241408Smckusick curprivs = getprivs(id, quotatype); 12341408Smckusick if (writeprivs(curprivs, tmpfd, *argv, quotatype) == 0) 12441408Smckusick continue; 12541408Smckusick if (editit(tmpfil) && readprivs(curprivs, tmpfd)) 12641408Smckusick putprivs(id, quotatype, curprivs); 12741408Smckusick freeprivs(curprivs); 12812803Smckusick } 12941408Smckusick close(tmpfd); 13012707Smckusick unlink(tmpfil); 13112707Smckusick exit(0); 13212707Smckusick } 13312707Smckusick 13441408Smckusick usage() 13541408Smckusick { 13641408Smckusick fprintf(stderr, "%s%s%s%s", 13741408Smckusick "Usage: edquota [-u] [-p username] username ...\n", 13841408Smckusick "\tedquota -g [-p groupname] groupname ...\n", 13941408Smckusick "\tedquota [-u] -t\n", "\tedquota -g -t\n"); 14041408Smckusick exit(1); 14141408Smckusick } 14241408Smckusick 14341408Smckusick /* 14441408Smckusick * This routine converts a name for a particular quota type to 14541408Smckusick * an identifier. This routine must agree with the kernel routine 14641408Smckusick * getinoquota as to the interpretation of quota types. 14741408Smckusick */ 14841408Smckusick getentry(name, quotatype) 14912803Smckusick char *name; 15041408Smckusick int quotatype; 15112707Smckusick { 15212803Smckusick struct passwd *pw; 15341408Smckusick struct group *gr; 15412707Smckusick 15512707Smckusick if (alldigits(name)) 15641408Smckusick return (atoi(name)); 15741408Smckusick switch(quotatype) { 15841408Smckusick case USRQUOTA: 15941408Smckusick if (pw = getpwnam(name)) 16041408Smckusick return (pw->pw_uid); 16112803Smckusick fprintf(stderr, "%s: no such user\n", name); 16241408Smckusick break; 16341408Smckusick case GRPQUOTA: 16441408Smckusick if (gr = getgrnam(name)) 16541408Smckusick return (gr->gr_gid); 16641408Smckusick fprintf(stderr, "%s: no such group\n", name); 16741408Smckusick break; 16841408Smckusick default: 16941408Smckusick fprintf(stderr, "%d: unknown quota type\n", quotatype); 17041408Smckusick break; 17112707Smckusick } 17241408Smckusick sleep(1); 17341408Smckusick return (-1); 17412707Smckusick } 17512707Smckusick 17641408Smckusick /* 17741408Smckusick * Collect the requested quota information. 17841408Smckusick */ 17941408Smckusick struct quotause * 18041408Smckusick getprivs(id, quotatype) 18141408Smckusick register long id; 18241408Smckusick int quotatype; 18312707Smckusick { 18441408Smckusick register struct fstab *fs; 18541408Smckusick register struct quotause *qup, *quptail; 18641408Smckusick struct quotause *quphead; 18741444Smckusick int qcmd, qupsize, fd; 18841444Smckusick char *qfpathname; 18941408Smckusick static int warned = 0; 19041408Smckusick extern int errno; 19141408Smckusick 19241408Smckusick setfsent(); 19341408Smckusick quphead = (struct quotause *)0; 19441408Smckusick qcmd = QCMD(Q_GETQUOTA, quotatype); 19541408Smckusick while (fs = getfsent()) { 19641444Smckusick if (strcmp(fs->fs_vfstype, "ufs")) 19741408Smckusick continue; 19841444Smckusick if (!hasquota(fs, quotatype, &qfpathname)) 19941408Smckusick continue; 20041444Smckusick qupsize = sizeof(*qup) + strlen(qfpathname); 20141444Smckusick if ((qup = (struct quotause *)malloc(qupsize)) == NULL) { 20241408Smckusick fprintf(stderr, "edquota: out of memory\n"); 20341408Smckusick exit(2); 20441408Smckusick } 20541444Smckusick if (quotactl(fs->fs_file, qcmd, id, &qup->dqblk) != 0) { 20641408Smckusick if (errno == EOPNOTSUPP && !warned) { 20741408Smckusick warned++; 20841408Smckusick fprintf(stderr, "Warning: %s\n", 20941408Smckusick "Quotas are not compiled into this kernel"); 21041408Smckusick sleep(3); 21141408Smckusick } 21241444Smckusick if ((fd = open(qfpathname, O_RDONLY)) < 0) { 21341444Smckusick fd = open(qfpathname, O_RDWR|O_CREAT, 0640); 21441444Smckusick if (fd < 0 && errno != ENOENT) { 21541444Smckusick perror(qfpathname); 21641444Smckusick free(qup); 21741444Smckusick continue; 21841444Smckusick } 21941444Smckusick fprintf(stderr, "Creating quota file %s\n", 22041444Smckusick qfpathname); 22141444Smckusick sleep(3); 22241444Smckusick (void) fchown(fd, getuid(), 22341444Smckusick getentry(quotagroup, GRPQUOTA)); 22441444Smckusick (void) fchmod(fd, 0640); 22541444Smckusick } 22641408Smckusick lseek(fd, (long)(id * sizeof(struct dqblk)), L_SET); 22741408Smckusick switch (read(fd, &qup->dqblk, sizeof(struct dqblk))) { 22841408Smckusick case 0: /* EOF */ 22941408Smckusick /* 23041408Smckusick * Convert implicit 0 quota (EOF) 23141408Smckusick * into an explicit one (zero'ed dqblk) 23241408Smckusick */ 23341408Smckusick bzero((caddr_t)&qup->dqblk, 23441408Smckusick sizeof(struct dqblk)); 23541408Smckusick break; 23641408Smckusick 23741408Smckusick case sizeof(struct dqblk): /* OK */ 23841408Smckusick break; 23941408Smckusick 24041408Smckusick default: /* ERROR */ 24141408Smckusick fprintf(stderr, "edquota: read error in "); 24241444Smckusick perror(qfpathname); 24341408Smckusick close(fd); 24441408Smckusick free(qup); 24541408Smckusick continue; 24641408Smckusick } 24741444Smckusick close(fd); 24841408Smckusick } 24941444Smckusick strcpy(qup->qfname, qfpathname); 25041408Smckusick strcpy(qup->fsname, fs->fs_file); 25141408Smckusick if (quphead == NULL) 25241408Smckusick quphead = qup; 25341408Smckusick else 25441408Smckusick quptail->next = qup; 25541408Smckusick quptail = qup; 25641408Smckusick qup->next = 0; 25741408Smckusick } 25841408Smckusick endfsent(); 25941408Smckusick return (quphead); 26041408Smckusick } 26141408Smckusick 26241408Smckusick /* 26341408Smckusick * Store the requested quota information. 26441408Smckusick */ 26541408Smckusick putprivs(id, quotatype, quplist) 26641408Smckusick long id; 26741408Smckusick int quotatype; 26841408Smckusick struct quotause *quplist; 26941408Smckusick { 27041408Smckusick register struct quotause *qup; 27141408Smckusick int qcmd, fd; 27241408Smckusick 27341408Smckusick qcmd = QCMD(Q_SETQUOTA, quotatype); 27441408Smckusick for (qup = quplist; qup; qup = qup->next) { 27541444Smckusick if (quotactl(qup->fsname, qcmd, id, &qup->dqblk) == 0) 27641408Smckusick continue; 27741444Smckusick if ((fd = open(qup->qfname, O_WRONLY)) < 0) { 27841444Smckusick perror(qup->qfname); 27941408Smckusick } else { 28041408Smckusick lseek(fd, (long)id * (long)sizeof (struct dqblk), 0); 28141408Smckusick if (write(fd, &qup->dqblk, sizeof (struct dqblk)) != 28241408Smckusick sizeof (struct dqblk)) { 28341408Smckusick fprintf(stderr, "edquota: "); 28441444Smckusick perror(qup->qfname); 28541408Smckusick } 28641408Smckusick close(fd); 28741408Smckusick } 28841408Smckusick } 28941408Smckusick } 29041408Smckusick 29141408Smckusick /* 29241408Smckusick * Take a list of priviledges and get it edited. 29341408Smckusick */ 29441408Smckusick editit(tmpfile) 29541408Smckusick char *tmpfile; 29641408Smckusick { 29733609Sbostic long omask; 29841408Smckusick int pid, stat; 29941408Smckusick extern char *getenv(); 30012707Smckusick 30133609Sbostic omask = sigblock(sigmask(SIGINT)|sigmask(SIGQUIT)|sigmask(SIGHUP)); 30212707Smckusick top: 30312707Smckusick if ((pid = fork()) < 0) { 30412707Smckusick extern errno; 30512707Smckusick 30612707Smckusick if (errno == EPROCLIM) { 30712707Smckusick fprintf(stderr, "You have too many processes\n"); 30812707Smckusick return(0); 30912707Smckusick } 31012707Smckusick if (errno == EAGAIN) { 31112707Smckusick sleep(1); 31212707Smckusick goto top; 31312707Smckusick } 31412707Smckusick perror("fork"); 31512707Smckusick return (0); 31612707Smckusick } 31712707Smckusick if (pid == 0) { 31812707Smckusick register char *ed; 31912707Smckusick 32013025Ssam sigsetmask(omask); 32112707Smckusick setgid(getgid()); 32212707Smckusick setuid(getuid()); 32312707Smckusick if ((ed = getenv("EDITOR")) == (char *)0) 32437976Sbostic ed = _PATH_VI; 32541408Smckusick execlp(ed, ed, tmpfile, 0); 32612707Smckusick perror(ed); 32712707Smckusick exit(1); 32812707Smckusick } 32941408Smckusick waitpid(pid, &stat, 0); 33013025Ssam sigsetmask(omask); 33141408Smckusick if (!WIFEXITED(stat) || WEXITSTATUS(stat) != 0) 33241408Smckusick return (0); 33341408Smckusick return (1); 33412707Smckusick } 33512707Smckusick 33641408Smckusick /* 33741408Smckusick * Convert a quotause list to an ASCII file. 33841408Smckusick */ 33941408Smckusick writeprivs(quplist, outfd, name, quotatype) 34041408Smckusick struct quotause *quplist; 34141408Smckusick int outfd; 34241408Smckusick char *name; 34341408Smckusick int quotatype; 34412707Smckusick { 34541408Smckusick register struct quotause *qup; 34612707Smckusick FILE *fd; 34712707Smckusick 34843266Smckusick ftruncate(outfd, 0); 34941408Smckusick lseek(outfd, 0, L_SET); 35041408Smckusick if ((fd = fdopen(dup(outfd), "w")) == NULL) { 35112707Smckusick fprintf(stderr, "edquota: "); 35212707Smckusick perror(tmpfil); 35312707Smckusick exit(1); 35412707Smckusick } 35541408Smckusick fprintf(fd, "Quotas for %s %s:\n", qfextension[quotatype], name); 35641408Smckusick for (qup = quplist; qup; qup = qup->next) { 35741408Smckusick fprintf(fd, "%s: %s %d, limits (soft = %d, hard = %d)\n", 35841408Smckusick qup->fsname, "blocks in use:", 35941408Smckusick dbtob(qup->dqblk.dqb_curblocks) / 1024, 36041408Smckusick dbtob(qup->dqblk.dqb_bsoftlimit) / 1024, 36141408Smckusick dbtob(qup->dqblk.dqb_bhardlimit) / 1024); 36241408Smckusick fprintf(fd, "%s %d, limits (soft = %d, hard = %d)\n", 36341408Smckusick "\tinodes in use:", qup->dqblk.dqb_curinodes, 36441408Smckusick qup->dqblk.dqb_isoftlimit, qup->dqblk.dqb_ihardlimit); 36512707Smckusick } 36612707Smckusick fclose(fd); 36741408Smckusick return (1); 36812707Smckusick } 36912707Smckusick 37041408Smckusick /* 37141408Smckusick * Merge changes to an ASCII file into a quotause list. 37241408Smckusick */ 37341408Smckusick readprivs(quplist, infd) 37441408Smckusick struct quotause *quplist; 37541408Smckusick int infd; 37612707Smckusick { 37741408Smckusick register struct quotause *qup; 37812707Smckusick FILE *fd; 37941408Smckusick int cnt; 38041408Smckusick register char *cp; 38141408Smckusick struct dqblk dqblk; 38241408Smckusick char *fsp, line1[BUFSIZ], line2[BUFSIZ]; 38312707Smckusick 38441408Smckusick lseek(infd, 0, L_SET); 38541408Smckusick fd = fdopen(dup(infd), "r"); 38612707Smckusick if (fd == NULL) { 38712707Smckusick fprintf(stderr, "Can't re-read temp file!!\n"); 38841408Smckusick return (0); 38912707Smckusick } 39041408Smckusick /* 39141408Smckusick * Discard title line, then read pairs of lines to process. 39241408Smckusick */ 39341408Smckusick (void) fgets(line1, sizeof (line1), fd); 39441408Smckusick while (fgets(line1, sizeof (line1), fd) != NULL && 39541408Smckusick fgets(line2, sizeof (line2), fd) != NULL) { 39641408Smckusick if ((fsp = strtok(line1, " \t:")) == NULL) { 39741408Smckusick fprintf(stderr, "%s: bad format\n", line1); 39841408Smckusick return (0); 39941408Smckusick } 40041408Smckusick if ((cp = strtok((char *)0, "\n")) == NULL) { 40141408Smckusick fprintf(stderr, "%s: %s: bad format\n", fsp, 40241408Smckusick &fsp[strlen(fsp) + 1]); 40341408Smckusick return (0); 40441408Smckusick } 40541408Smckusick cnt = sscanf(cp, 40641408Smckusick " blocks in use: %d, limits (soft = %d, hard = %d)", 40741408Smckusick &dqblk.dqb_curblocks, &dqblk.dqb_bsoftlimit, 40841408Smckusick &dqblk.dqb_bhardlimit); 40941408Smckusick if (cnt != 3) { 41041408Smckusick fprintf(stderr, "%s:%s: bad format\n", fsp, cp); 41141408Smckusick return (0); 41241408Smckusick } 41341408Smckusick dqblk.dqb_curblocks = btodb(dqblk.dqb_curblocks * 1024); 41441408Smckusick dqblk.dqb_bsoftlimit = btodb(dqblk.dqb_bsoftlimit * 1024); 41541408Smckusick dqblk.dqb_bhardlimit = btodb(dqblk.dqb_bhardlimit * 1024); 41641408Smckusick if ((cp = strtok(line2, "\n")) == NULL) { 41741408Smckusick fprintf(stderr, "%s: %s: bad format\n", fsp, line2); 41841408Smckusick return (0); 41941408Smckusick } 42041408Smckusick cnt = sscanf(cp, 42141408Smckusick "\tinodes in use: %d, limits (soft = %d, hard = %d)", 42241408Smckusick &dqblk.dqb_curinodes, &dqblk.dqb_isoftlimit, 42341408Smckusick &dqblk.dqb_ihardlimit); 42441408Smckusick if (cnt != 3) { 42541408Smckusick fprintf(stderr, "%s: %s: bad format\n", fsp, line2); 42641408Smckusick return (0); 42741408Smckusick } 42841408Smckusick for (qup = quplist; qup; qup = qup->next) { 42941408Smckusick if (strcmp(fsp, qup->fsname)) 43041408Smckusick continue; 43141408Smckusick /* 43241408Smckusick * Cause time limit to be reset when the quota 43341408Smckusick * is next used if previously had no soft limit 43441408Smckusick * or were under it, but now have a soft limit 43541408Smckusick * and are over it. 43641408Smckusick */ 43741408Smckusick if (dqblk.dqb_bsoftlimit && 43841408Smckusick qup->dqblk.dqb_curblocks >= dqblk.dqb_bsoftlimit && 43941408Smckusick (qup->dqblk.dqb_bsoftlimit == 0 || 44041408Smckusick qup->dqblk.dqb_curblocks < 44141408Smckusick qup->dqblk.dqb_bsoftlimit)) 44241408Smckusick qup->dqblk.dqb_btime = 0; 44341408Smckusick if (dqblk.dqb_isoftlimit && 44441408Smckusick qup->dqblk.dqb_curinodes >= dqblk.dqb_isoftlimit && 44541408Smckusick (qup->dqblk.dqb_isoftlimit == 0 || 44641408Smckusick qup->dqblk.dqb_curinodes < 44741408Smckusick qup->dqblk.dqb_isoftlimit)) 44841408Smckusick qup->dqblk.dqb_itime = 0; 44941408Smckusick qup->dqblk.dqb_bsoftlimit = dqblk.dqb_bsoftlimit; 45041408Smckusick qup->dqblk.dqb_bhardlimit = dqblk.dqb_bhardlimit; 45141408Smckusick qup->dqblk.dqb_isoftlimit = dqblk.dqb_isoftlimit; 45241408Smckusick qup->dqblk.dqb_ihardlimit = dqblk.dqb_ihardlimit; 45341408Smckusick qup->flags |= FOUND; 45441408Smckusick if (dqblk.dqb_curblocks == qup->dqblk.dqb_curblocks && 45541408Smckusick dqblk.dqb_curinodes == qup->dqblk.dqb_curinodes) 45641408Smckusick break; 45741408Smckusick fprintf(stderr, 45841408Smckusick "%s: cannot change current allocation\n", fsp); 45912707Smckusick break; 46041408Smckusick } 46141408Smckusick } 46241408Smckusick fclose(fd); 46341408Smckusick /* 46441408Smckusick * Disable quotas for any filesystems that have not been found. 46541408Smckusick */ 46641408Smckusick for (qup = quplist; qup; qup = qup->next) { 46741408Smckusick if (qup->flags & FOUND) { 46841408Smckusick qup->flags &= ~FOUND; 46912716Smckusick continue; 47012716Smckusick } 47141408Smckusick qup->dqblk.dqb_bsoftlimit = 0; 47241408Smckusick qup->dqblk.dqb_bhardlimit = 0; 47341408Smckusick qup->dqblk.dqb_isoftlimit = 0; 47441408Smckusick qup->dqblk.dqb_ihardlimit = 0; 47512707Smckusick } 47641408Smckusick return (1); 47741408Smckusick } 47841408Smckusick 47941408Smckusick /* 48041408Smckusick * Convert a quotause list to an ASCII file of grace times. 48141408Smckusick */ 48241408Smckusick writetimes(quplist, outfd, quotatype) 48341408Smckusick struct quotause *quplist; 48441408Smckusick int outfd; 48541408Smckusick int quotatype; 48641408Smckusick { 48741408Smckusick register struct quotause *qup; 48841408Smckusick char *cvtstoa(); 48941408Smckusick FILE *fd; 49041408Smckusick 49143266Smckusick ftruncate(outfd, 0); 49241408Smckusick lseek(outfd, 0, L_SET); 49341408Smckusick if ((fd = fdopen(dup(outfd), "w")) == NULL) { 49441408Smckusick fprintf(stderr, "edquota: "); 49541408Smckusick perror(tmpfil); 49641408Smckusick exit(1); 49741408Smckusick } 49841408Smckusick fprintf(fd, "Time units may be: days, hours, minutes, or seconds\n"); 49941408Smckusick fprintf(fd, "Grace period before enforcing soft limits for %ss:\n", 50041408Smckusick qfextension[quotatype]); 50141408Smckusick for (qup = quplist; qup; qup = qup->next) { 50241408Smckusick fprintf(fd, "%s: block grace period: %s, ", 50341408Smckusick qup->fsname, cvtstoa(qup->dqblk.dqb_btime)); 50441408Smckusick fprintf(fd, "file grace period: %s\n", 50541408Smckusick cvtstoa(qup->dqblk.dqb_itime)); 50641408Smckusick } 50712707Smckusick fclose(fd); 50841408Smckusick return (1); 50941408Smckusick } 51041408Smckusick 51141408Smckusick /* 51241408Smckusick * Merge changes of grace times in an ASCII file into a quotause list. 51341408Smckusick */ 51441408Smckusick readtimes(quplist, infd) 51541408Smckusick struct quotause *quplist; 51641408Smckusick int infd; 51741408Smckusick { 51841408Smckusick register struct quotause *qup; 51941408Smckusick FILE *fd; 52041408Smckusick int cnt; 52141408Smckusick register char *cp; 52241408Smckusick time_t itime, btime, iseconds, bseconds; 52341408Smckusick char *fsp, bunits[10], iunits[10], line1[BUFSIZ]; 52441408Smckusick 52541408Smckusick lseek(infd, 0, L_SET); 52641408Smckusick fd = fdopen(dup(infd), "r"); 52741408Smckusick if (fd == NULL) { 52841408Smckusick fprintf(stderr, "Can't re-read temp file!!\n"); 52941408Smckusick return (0); 53041408Smckusick } 53141408Smckusick /* 53241408Smckusick * Discard two title lines, then read lines to process. 53341408Smckusick */ 53441408Smckusick (void) fgets(line1, sizeof (line1), fd); 53541408Smckusick (void) fgets(line1, sizeof (line1), fd); 53641408Smckusick while (fgets(line1, sizeof (line1), fd) != NULL) { 53741408Smckusick if ((fsp = strtok(line1, " \t:")) == NULL) { 53841408Smckusick fprintf(stderr, "%s: bad format\n", line1); 53941408Smckusick return (0); 54041408Smckusick } 54141408Smckusick if ((cp = strtok((char *)0, "\n")) == NULL) { 54241408Smckusick fprintf(stderr, "%s: %s: bad format\n", fsp, 54341408Smckusick &fsp[strlen(fsp) + 1]); 54441408Smckusick return (0); 54541408Smckusick } 54641408Smckusick cnt = sscanf(cp, 54741408Smckusick " block grace period: %d %s file grace period: %d %s", 54841408Smckusick &btime, bunits, &itime, iunits); 54941408Smckusick if (cnt != 4) { 55041408Smckusick fprintf(stderr, "%s:%s: bad format\n", fsp, cp); 55141408Smckusick return (0); 55241408Smckusick } 55341408Smckusick if (cvtatos(btime, bunits, &bseconds) == 0) 55441408Smckusick return (0); 55541408Smckusick if (cvtatos(itime, iunits, &iseconds) == 0) 55641408Smckusick return (0); 55741408Smckusick for (qup = quplist; qup; qup = qup->next) { 55841408Smckusick if (strcmp(fsp, qup->fsname)) 55941408Smckusick continue; 56041408Smckusick qup->dqblk.dqb_btime = bseconds; 56141408Smckusick qup->dqblk.dqb_itime = iseconds; 56241408Smckusick qup->flags |= FOUND; 56312707Smckusick break; 56412707Smckusick } 56541408Smckusick } 56641408Smckusick fclose(fd); 56741408Smckusick /* 56841408Smckusick * reset default grace periods for any filesystems 56941408Smckusick * that have not been found. 57041408Smckusick */ 57141408Smckusick for (qup = quplist; qup; qup = qup->next) { 57241408Smckusick if (qup->flags & FOUND) { 57341408Smckusick qup->flags &= ~FOUND; 57412707Smckusick continue; 57512707Smckusick } 57641408Smckusick qup->dqblk.dqb_btime = 0; 57741408Smckusick qup->dqblk.dqb_itime = 0; 57812707Smckusick } 57941408Smckusick return (1); 58012707Smckusick } 58112707Smckusick 58241408Smckusick /* 58341408Smckusick * Convert seconds to ASCII times. 58441408Smckusick */ 58512707Smckusick char * 58641408Smckusick cvtstoa(time) 58741408Smckusick time_t time; 58812707Smckusick { 58941408Smckusick static char buf[20]; 59012707Smckusick 59141408Smckusick if (time % (24 * 60 * 60) == 0) { 59241408Smckusick time /= 24 * 60 * 60; 59341408Smckusick sprintf(buf, "%d day%s", time, time == 1 ? "" : "s"); 59441408Smckusick } else if (time % (60 * 60) == 0) { 59541408Smckusick time /= 60 * 60; 59641408Smckusick sprintf(buf, "%d hour%s", time, time == 1 ? "" : "s"); 59741408Smckusick } else if (time % 60 == 0) { 59841408Smckusick time /= 60; 59941408Smckusick sprintf(buf, "%d minute%s", time, time == 1 ? "" : "s"); 60041408Smckusick } else 60141408Smckusick sprintf(buf, "%d second%s", time, time == 1 ? "" : "s"); 60241408Smckusick return (buf); 60341408Smckusick } 60441408Smckusick 60541408Smckusick /* 60641408Smckusick * Convert ASCII input times to seconds. 60741408Smckusick */ 60841408Smckusick cvtatos(time, units, seconds) 60941408Smckusick time_t time; 61041408Smckusick char *units; 61141408Smckusick time_t *seconds; 61241408Smckusick { 61341408Smckusick 61441408Smckusick if (bcmp(units, "second", 6) == 0) 61541408Smckusick *seconds = time; 61641408Smckusick else if (bcmp(units, "minute", 6) == 0) 61741408Smckusick *seconds = time * 60; 61841408Smckusick else if (bcmp(units, "hour", 4) == 0) 61941408Smckusick *seconds = time * 60 * 60; 62041408Smckusick else if (bcmp(units, "day", 3) == 0) 62141408Smckusick *seconds = time * 24 * 60 * 60; 62241408Smckusick else { 62341408Smckusick printf("%s: bad units, specify %s\n", units, 62441408Smckusick "days, hours, minutes, or seconds"); 62541408Smckusick return (0); 62612707Smckusick } 62741408Smckusick return (1); 62812707Smckusick } 62912707Smckusick 63041408Smckusick /* 63141408Smckusick * Free a list of quotause structures. 63241408Smckusick */ 63341408Smckusick freeprivs(quplist) 63441408Smckusick struct quotause *quplist; 63541408Smckusick { 63641408Smckusick register struct quotause *qup, *nextqup; 63741408Smckusick 63841408Smckusick for (qup = quplist; qup; qup = nextqup) { 63941408Smckusick nextqup = qup->next; 64041408Smckusick free(qup); 64141408Smckusick } 64241408Smckusick } 64341408Smckusick 64441408Smckusick /* 64541408Smckusick * Check whether a string is completely composed of digits. 64641408Smckusick */ 64712707Smckusick alldigits(s) 64812707Smckusick register char *s; 64912707Smckusick { 65012707Smckusick register c; 65112707Smckusick 65212707Smckusick c = *s++; 65312707Smckusick do { 65412707Smckusick if (!isdigit(c)) 65512707Smckusick return (0); 65612707Smckusick } while (c = *s++); 65712707Smckusick return (1); 65812707Smckusick } 65912707Smckusick 66041408Smckusick /* 66141408Smckusick * Check to see if a particular quota is to be enabled. 66241408Smckusick */ 66341444Smckusick hasquota(fs, type, qfnamep) 66441444Smckusick register struct fstab *fs; 66541408Smckusick int type; 66641444Smckusick char **qfnamep; 66712707Smckusick { 66841408Smckusick register char *opt; 66941444Smckusick char *cp, *index(), *strtok(); 67041408Smckusick static char initname, usrname[100], grpname[100]; 67141444Smckusick static char buf[BUFSIZ]; 67212707Smckusick 67341408Smckusick if (!initname) { 67441408Smckusick sprintf(usrname, "%s%s", qfextension[USRQUOTA], qfname); 67541408Smckusick sprintf(grpname, "%s%s", qfextension[GRPQUOTA], qfname); 67641408Smckusick initname = 1; 67712707Smckusick } 67841444Smckusick strcpy(buf, fs->fs_mntops); 67941408Smckusick for (opt = strtok(buf, ","); opt; opt = strtok(NULL, ",")) { 68041444Smckusick if (cp = index(opt, '=')) 68141444Smckusick *cp++ = '\0'; 68241408Smckusick if (type == USRQUOTA && strcmp(opt, usrname) == 0) 68341444Smckusick break; 68441408Smckusick if (type == GRPQUOTA && strcmp(opt, grpname) == 0) 68541444Smckusick break; 68612707Smckusick } 68741444Smckusick if (!opt) 68841444Smckusick return (0); 68941444Smckusick if (cp) { 69041444Smckusick *qfnamep = cp; 69141444Smckusick return (1); 69241444Smckusick } 69341444Smckusick (void) sprintf(buf, "%s/%s.%s", fs->fs_file, qfname, qfextension[type]); 69441444Smckusick *qfnamep = buf; 69541444Smckusick return (1); 69612707Smckusick } 697