diff --git a/usr.sbin/edquota/edquota.8 b/usr.sbin/edquota/edquota.8 index 274a4fece87a..ec8cb4f89644 100644 --- a/usr.sbin/edquota/edquota.8 +++ b/usr.sbin/edquota/edquota.8 @@ -33,9 +33,9 @@ .\" SUCH DAMAGE. .\" .\" from: @(#)edquota.8 8.2 (Berkeley) 4/27/95 -.\" $NetBSD: edquota.8,v 1.8 2002/01/19 03:11:34 wiz Exp $ +.\" $NetBSD: edquota.8,v 1.9 2002/12/04 21:01:13 bouyer Exp $ .\" -.Dd April 27, 1995 +.Dd December 4, 2002 .Dt EDQUOTA 8 .Os .Sh NAME @@ -44,18 +44,34 @@ .Sh SYNOPSIS .Nm .Op Fl u +.Op Fl f Ar filesystem .Op Fl p Ar proto-username .Ar username ... .Nm "" .Fl g +.Op Fl f Ar filesystem .Op Fl p Ar proto-groupname .Ar groupname ... .Nm "" -.Fl t .Op Fl u +.Op Fl f Ar filesystem +.Op Fl h Ar block#/inode# +.Op Fl s Ar block#/inode# +.Ar username ... .Nm "" -.Fl t .Fl g +.Op Fl f Ar filesystem +.Op Fl h Ar block#/inode# +.Op Fl s Ar block#/inode# +.Ar groupname ... +.Nm "" +.Op Fl u +.Op Fl f Ar filesystem +.Fl t +.Nm "" +.Fl g +.Op Fl f Ar filesystem +.Fl t .Sh DESCRIPTION .Nm is a quota editor. @@ -63,11 +79,17 @@ By default, or if the .Fl u flag is specified, one or more users may be specified on the command line. -For each user a temporary file is created -with an ASCII representation of the current -disk quotas for that user. +Unless +.Fl h +or +.Fl s +are used, a temporary file is created for each user with an ASCII +representation of the current disk quotas for that user. The list of filesystems with user quotas is determined from .Pa /etc/fstab . +By default, quota for all quota-enabled filesystems are edited; the +.Fl f +option can be used to restrict it to a single filesystem. An editor is invoked on the ASCII file. The editor invoked is .Xr vi 1 @@ -98,8 +120,15 @@ flag is specified, .Nm will duplicate the quotas of the prototypical user specified for each user specified. -This is the normal mechanism used to -initialize quotas for groups of users. +This is the normal mechanism used to initialize quotas for groups of users. +.Pp +The +.Fl h +and +.Fl s +flags can be used to change quota limits (soft and hard, respectively) +without user interaction, for usage in e.g. batch scripts. +The arguments are the new block and inode number limit, separated by a slash. .Pp If the .Fl g @@ -109,8 +138,7 @@ is invoked to edit the quotas of one or more groups specified on the command line. The .Fl p -flag can be specified in conjunction with -the +flag can be specified in conjunction with the .Fl g flag to specify a prototypical group to be duplicated among the listed set of groups. diff --git a/usr.sbin/edquota/edquota.c b/usr.sbin/edquota/edquota.c index 93b958c672e6..62f81b4ea98b 100644 --- a/usr.sbin/edquota/edquota.c +++ b/usr.sbin/edquota/edquota.c @@ -44,7 +44,7 @@ __COPYRIGHT("@(#) Copyright (c) 1980, 1990, 1993\n\ #if 0 static char sccsid[] = "from: @(#)edquota.c 8.3 (Berkeley) 4/27/95"; #else -__RCSID("$NetBSD: edquota.c,v 1.21 2000/04/14 06:26:53 simonb Exp $"); +__RCSID("$NetBSD: edquota.c,v 1.22 2002/12/04 21:01:13 bouyer Exp $"); #endif #endif /* not lint */ @@ -88,7 +88,7 @@ int main __P((int, char **)); void usage __P((void)); int getentry __P((char *, int)); struct quotause * - getprivs __P((long, int)); + getprivs __P((long, int, char *)); void putprivs __P((long, int, struct quotause *)); int editit __P((char *)); int writeprivs __P((struct quotause *, int, char *, int)); @@ -110,6 +110,8 @@ main(argc, argv) long id, protoid; int quotatype, tmpfd; char *protoname; + char *soft = NULL, *hard = NULL; + char *fs = NULL; int ch; int tflag = 0, pflag = 0; @@ -119,7 +121,7 @@ main(argc, argv) errx(1, "permission denied"); protoname = NULL; quotatype = USRQUOTA; - while ((ch = getopt(argc, argv, "ugtp:")) != -1) { + while ((ch = getopt(argc, argv, "ugtp:s:h:f:")) != -1) { switch(ch) { case 'p': protoname = optarg; @@ -134,6 +136,15 @@ main(argc, argv) case 't': tflag++; break; + case 's': + soft = optarg; + break; + case 'h': + hard = optarg; + break; + case 'f': + fs = optarg; + break; default: usage(); } @@ -141,9 +152,11 @@ main(argc, argv) argc -= optind; argv += optind; if (pflag) { + if (soft || hard) + usage(); if ((protoid = getentry(protoname, quotatype)) == -1) exit(1); - protoprivs = getprivs(protoid, quotatype); + protoprivs = getprivs(protoid, quotatype, fs); for (qup = protoprivs; qup; qup = qup->next) { qup->dqblk.dqb_btime = 0; qup->dqblk.dqb_itime = 0; @@ -155,10 +168,58 @@ main(argc, argv) } exit(0); } + if (soft || hard) { + struct quotause *qup; + u_int32_t softb, hardb, softi, hardi; + if (tflag) + usage(); + if (soft) { + if (sscanf(soft, "%d/%d", &softb, &softi) != 2) + usage(); + softb = btodb((u_quad_t)softb * 1024); + } + if (hard) { + if (sscanf(hard, "%d/%d", &hardb, &hardi) != 2) + usage(); + hardb = btodb((u_quad_t)hardb * 1024); + } + for ( ; argc > 0; argc--, argv++) { + if ((id = getentry(*argv, quotatype)) == -1) + continue; + curprivs = getprivs(id, quotatype, fs); + for (qup = curprivs; qup; qup = qup->next) { + if (soft) { + if (softb && + qup->dqblk.dqb_curblocks >= softb && + (qup->dqblk.dqb_bsoftlimit == 0 || + qup->dqblk.dqb_curblocks < + qup->dqblk.dqb_bsoftlimit)) + qup->dqblk.dqb_btime = 0; + if (softi && + qup->dqblk.dqb_curinodes >= softi && + (qup->dqblk.dqb_isoftlimit == 0 || + qup->dqblk.dqb_curinodes < + qup->dqblk.dqb_isoftlimit)) + qup->dqblk.dqb_itime = 0; + qup->dqblk.dqb_bsoftlimit = softb; + qup->dqblk.dqb_isoftlimit = softi; + } + if (hard) { + qup->dqblk.dqb_bhardlimit = hardb; + qup->dqblk.dqb_ihardlimit = hardi; + } + } + putprivs(id, quotatype, curprivs); + freeprivs(curprivs); + } + exit(0); + } tmpfd = mkstemp(tmpfil); fchown(tmpfd, getuid(), getgid()); if (tflag) { - protoprivs = getprivs(0, quotatype); + if (soft || hard) + usage(); + protoprivs = getprivs(0, quotatype, fs); if (writetimes(protoprivs, tmpfd, quotatype) == 0) exit(1); if (editit(tmpfil) && readtimes(protoprivs, tmpfd)) @@ -169,7 +230,7 @@ main(argc, argv) for ( ; argc > 0; argc--, argv++) { if ((id = getentry(*argv, quotatype)) == -1) continue; - curprivs = getprivs(id, quotatype); + curprivs = getprivs(id, quotatype, fs); if (writeprivs(curprivs, tmpfd, *argv, quotatype) == 0) continue; if (editit(tmpfil) && readprivs(curprivs, tmpfd)) @@ -184,10 +245,14 @@ main(argc, argv) void usage() { - fprintf(stderr, "%s%s%s%s", - "Usage: edquota [-u] [-p username] username ...\n", - "\tedquota -g [-p groupname] groupname ...\n", - "\tedquota [-u] -t\n", "\tedquota -g -t\n"); + fprintf(stderr, + "Usage: edquota [-u] [-p username] [-f filesystem] username ...\n" + "\tedquota -g [-p groupname] [-f filesystem] groupname ...\n" + "\tedquota [-u] [-f filesystem] [-s b#/i#] [-h b#/i#] username ...\n" + "\tedquota -g [-f filesystem] [-s b#/i#] [-h b#/i#] groupname ...\n" + "\tedquota [-u] [-f filesystem] -t\n" + "\tedquota -g [-f filesystem] -t\n" + ); exit(1); } @@ -229,9 +294,10 @@ getentry(name, quotatype) * Collect the requested quota information. */ struct quotause * -getprivs(id, quotatype) +getprivs(id, quotatype, filesys) long id; int quotatype; + char *filesys; { struct fstab *fs; struct quotause *qup, *quptail; @@ -247,6 +313,9 @@ getprivs(id, quotatype) while ((fs = getfsent()) != NULL) { if (strcmp(fs->fs_vfstype, "ffs")) continue; + if (filesys && strcmp(fs->fs_spec, filesys) != 0 && + strcmp(fs->fs_file, filesys) != 0) + continue; if (!hasquota(fs, quotatype, &qfpathname)) continue; qupsize = sizeof(*qup) + strlen(qfpathname);