version 1.14, 2000/02/01 03:23:36 |
version 1.15, 2000/10/18 22:15:29 |
|
|
#include <sys/stat.h> |
#include <sys/stat.h> |
#include <sys/mount.h> |
#include <sys/mount.h> |
#include <sys/socket.h> |
#include <sys/socket.h> |
|
|
#include <ufs/ufs/quota.h> |
#include <ufs/ufs/quota.h> |
|
#include <ctype.h> |
|
#include <err.h> |
|
#include <errno.h> |
|
#include <fstab.h> |
|
#include <grp.h> |
|
#include <netdb.h> |
|
#include <pwd.h> |
#include <stdio.h> |
#include <stdio.h> |
#include <stdlib.h> |
#include <stdlib.h> |
#include <fstab.h> |
|
#include <ctype.h> |
|
#include <string.h> |
#include <string.h> |
#include <pwd.h> |
#include <time.h> |
#include <grp.h> |
#include <unistd.h> |
#include <errno.h> |
|
|
|
#include <netdb.h> |
|
#include <rpc/rpc.h> |
#include <rpc/rpc.h> |
#include <rpc/pmap_prot.h> |
#include <rpc/pmap_prot.h> |
#include <rpcsvc/rquota.h> |
#include <rpcsvc/rquota.h> |
|
|
}; |
}; |
#define FOUND 0x01 |
#define FOUND 0x01 |
|
|
char *timeprt __P((time_t seconds)); |
int alldigits __P((char *)); |
struct quotause *getprivs __P((long id, int quotatype)); |
int callaurpc __P((char *, int, int, int, xdrproc_t, void *, |
|
xdrproc_t, void *)); |
|
int main __P((int, char **)); |
|
int getnfsquota __P((struct statfs *, struct fstab *, struct quotause *, |
|
long, int)); |
|
struct quotause *getprivs __P((long id, int quotatype)); |
|
int getufsquota __P((struct statfs *, struct fstab *, struct quotause *, |
|
long, int)); |
|
void heading __P((int, u_long, const char *, const char *)); |
|
void showgid __P((gid_t)); |
|
void showgrpname __P((const char *)); |
|
void showquotas __P((int, u_long, const char *)); |
|
void showuid __P((uid_t)); |
|
void showusrname __P((const char *)); |
|
char *timeprt __P((time_t seconds)); |
|
int ufshasquota __P((struct fstab *, int, char **)); |
|
void usage __P((void)); |
|
|
int qflag; |
int qflag; |
int vflag; |
int vflag; |
|
|
|
int |
main(argc, argv) |
main(argc, argv) |
|
int argc; |
char *argv[]; |
char *argv[]; |
{ |
{ |
int ngroups; |
int ngroups; |
|
|
if (gflag) { |
if (gflag) { |
mygid = getgid(); |
mygid = getgid(); |
ngroups = getgroups(NGROUPS, gidset); |
ngroups = getgroups(NGROUPS, gidset); |
if (ngroups < 0) { |
if (ngroups < 0) |
perror("quota: getgroups"); |
err(1, "getgroups"); |
exit(1); |
|
} |
|
showgid(mygid); |
showgid(mygid); |
for (i = 0; i < ngroups; i++) |
for (i = 0; i < ngroups; i++) |
if (gidset[i] != mygid) |
if (gidset[i] != mygid) |
|
|
} |
} |
exit(0); |
exit(0); |
} |
} |
|
/* NOTREACHED */ |
} |
} |
|
|
|
void |
usage() |
usage() |
{ |
{ |
|
|
fprintf(stderr, "%s\n%s\n%s\n", |
fprintf(stderr, "%s\n%s\n%s\n", |
"Usage: quota [-guqv]", |
"Usage: quota [-guqv]", |
"\tquota [-qv] -u username ...", |
"\tquota [-qv] -u username ...", |
"\tquota [-qv] -g groupname ..."); |
"\tquota [-qv] -g groupname ..."); |
exit(1); |
exit(1); |
} |
} |
|
|
/* |
/* |
* Print out quotas for a specified user identifier. |
* Print out quotas for a specified user identifier. |
*/ |
*/ |
|
void |
showuid(uid) |
showuid(uid) |
uid_t uid; |
uid_t uid; |
{ |
{ |
struct passwd *pwd = getpwuid(uid); |
struct passwd *pwd = getpwuid(uid); |
uid_t myuid; |
uid_t myuid; |
char *name; |
const char *name; |
|
|
if (pwd == NULL) |
if (pwd == NULL) |
name = "(no account)"; |
name = "(no account)"; |
|
|
name = pwd->pw_name; |
name = pwd->pw_name; |
myuid = getuid(); |
myuid = getuid(); |
if (uid != myuid && myuid != 0) { |
if (uid != myuid && myuid != 0) { |
printf("quota: %s (uid %u): permission denied\n", name, uid); |
warnx("%s (uid %u): permission denied", name, uid); |
return; |
return; |
} |
} |
showquotas(USRQUOTA, uid, name); |
showquotas(USRQUOTA, uid, name); |
|
|
/* |
/* |
* Print out quotas for a specifed user name. |
* Print out quotas for a specifed user name. |
*/ |
*/ |
|
void |
showusrname(name) |
showusrname(name) |
char *name; |
const char *name; |
{ |
{ |
struct passwd *pwd = getpwnam(name); |
struct passwd *pwd = getpwnam(name); |
uid_t myuid; |
uid_t myuid; |
|
|
if (pwd == NULL) { |
if (pwd == NULL) { |
fprintf(stderr, "quota: %s: unknown user\n", name); |
warnx("%s: unknown user", name); |
return; |
return; |
} |
} |
myuid = getuid(); |
myuid = getuid(); |
if (pwd->pw_uid != myuid && myuid != 0) { |
if (pwd->pw_uid != myuid && myuid != 0) { |
fprintf(stderr, "quota: %s (uid %u): permission denied\n", |
warnx("%s (uid %u): permission denied", pwd->pw_name, pwd->pw_uid); |
pwd->pw_name, pwd->pw_uid); |
|
return; |
return; |
} |
} |
showquotas(USRQUOTA, pwd->pw_uid, pwd->pw_name); |
showquotas(USRQUOTA, pwd->pw_uid, pwd->pw_name); |
|
|
/* |
/* |
* Print out quotas for a specified group identifier. |
* Print out quotas for a specified group identifier. |
*/ |
*/ |
|
void |
showgid(gid) |
showgid(gid) |
gid_t gid; |
gid_t gid; |
{ |
{ |
struct group *grp = getgrgid(gid); |
struct group *grp = getgrgid(gid); |
int ngroups; |
int ngroups; |
gid_t mygid, gidset[NGROUPS]; |
gid_t mygid, gidset[NGROUPS]; |
register int i; |
int i; |
char *name; |
const char *name; |
|
|
if (grp == NULL) |
if (grp == NULL) |
name = "(no entry)"; |
name = "(no entry)"; |
|
|
mygid = getgid(); |
mygid = getgid(); |
ngroups = getgroups(NGROUPS, gidset); |
ngroups = getgroups(NGROUPS, gidset); |
if (ngroups < 0) { |
if (ngroups < 0) { |
perror("quota: getgroups"); |
warn("getgroups"); |
return; |
return; |
} |
} |
if (gid != mygid) { |
if (gid != mygid) { |
|
|
if (gid == gidset[i]) |
if (gid == gidset[i]) |
break; |
break; |
if (i >= ngroups && getuid() != 0) { |
if (i >= ngroups && getuid() != 0) { |
fprintf(stderr, |
warnx("%s (gid %u): permission denied", name, gid); |
"quota: %s (gid %u): permission denied\n", |
|
name, gid); |
|
return; |
return; |
} |
} |
} |
} |
|
|
/* |
/* |
* Print out quotas for a specifed group name. |
* Print out quotas for a specifed group name. |
*/ |
*/ |
|
void |
showgrpname(name) |
showgrpname(name) |
char *name; |
const char *name; |
{ |
{ |
struct group *grp = getgrnam(name); |
struct group *grp = getgrnam(name); |
int ngroups; |
int ngroups; |
gid_t mygid, gidset[NGROUPS]; |
gid_t mygid, gidset[NGROUPS]; |
register int i; |
int i; |
|
|
if (grp == NULL) { |
if (grp == NULL) { |
fprintf(stderr, "quota: %s: unknown group\n", name); |
warnx("%s: unknown group", name); |
return; |
return; |
} |
} |
mygid = getgid(); |
mygid = getgid(); |
ngroups = getgroups(NGROUPS, gidset); |
ngroups = getgroups(NGROUPS, gidset); |
if (ngroups < 0) { |
if (ngroups < 0) { |
perror("quota: getgroups"); |
warn("getgroups"); |
return; |
return; |
} |
} |
if (grp->gr_gid != mygid) { |
if (grp->gr_gid != mygid) { |
|
|
if (grp->gr_gid == gidset[i]) |
if (grp->gr_gid == gidset[i]) |
break; |
break; |
if (i >= ngroups && getuid() != 0) { |
if (i >= ngroups && getuid() != 0) { |
fprintf(stderr, |
warnx("%s (gid %u): permission denied", |
"quota: %s (gid %d): permission denied\n", |
|
grp->gr_name, grp->gr_gid); |
grp->gr_name, grp->gr_gid); |
return; |
return; |
} |
} |
|
|
showquotas(GRPQUOTA, grp->gr_gid, grp->gr_name); |
showquotas(GRPQUOTA, grp->gr_gid, grp->gr_name); |
} |
} |
|
|
|
void |
showquotas(type, id, name) |
showquotas(type, id, name) |
int type; |
int type; |
u_long id; |
u_long id; |
char *name; |
const char *name; |
{ |
{ |
register struct quotause *qup; |
struct quotause *qup; |
struct quotause *quplist; |
struct quotause *quplist; |
char *msgi, *msgb, *nam; |
char *msgi, *msgb, *nam; |
uid_t myuid, fd, lines = 0; |
uid_t lines = 0; |
static int first; |
|
static time_t now; |
static time_t now; |
|
|
if (now == 0) |
if (now == 0) |
|
|
qup->dqblk.dqb_curinodes >= qup->dqblk.dqb_ihardlimit) |
qup->dqblk.dqb_curinodes >= qup->dqblk.dqb_ihardlimit) |
msgi = "File limit reached on"; |
msgi = "File limit reached on"; |
else if (qup->dqblk.dqb_isoftlimit && |
else if (qup->dqblk.dqb_isoftlimit && |
qup->dqblk.dqb_curinodes >= qup->dqblk.dqb_isoftlimit) |
qup->dqblk.dqb_curinodes >= qup->dqblk.dqb_isoftlimit) { |
if (qup->dqblk.dqb_itime > now) |
if (qup->dqblk.dqb_itime > now) |
msgi = "In file grace period on"; |
msgi = "In file grace period on"; |
else |
else |
msgi = "Over file quota on"; |
msgi = "Over file quota on"; |
|
} |
msgb = (char *)0; |
msgb = (char *)0; |
if (qup->dqblk.dqb_bhardlimit && |
if (qup->dqblk.dqb_bhardlimit && |
qup->dqblk.dqb_curblocks >= qup->dqblk.dqb_bhardlimit) |
qup->dqblk.dqb_curblocks >= qup->dqblk.dqb_bhardlimit) |
msgb = "Block limit reached on"; |
msgb = "Block limit reached on"; |
else if (qup->dqblk.dqb_bsoftlimit && |
else if (qup->dqblk.dqb_bsoftlimit && |
qup->dqblk.dqb_curblocks >= qup->dqblk.dqb_bsoftlimit) |
qup->dqblk.dqb_curblocks >= qup->dqblk.dqb_bsoftlimit) { |
if (qup->dqblk.dqb_btime > now) |
if (qup->dqblk.dqb_btime > now) |
msgb = "In block grace period on"; |
msgb = "In block grace period on"; |
else |
else |
msgb = "Over block quota on"; |
msgb = "Over block quota on"; |
|
} |
if (qflag) { |
if (qflag) { |
if ((msgi != (char *)0 || msgb != (char *)0) && |
if ((msgi != (char *)0 || msgb != (char *)0) && |
lines++ == 0) |
lines++ == 0) |
|
|
nam = ""; |
nam = ""; |
} |
} |
printf("%15s%8d%c%7d%8d%8s" |
printf("%15s%8d%c%7d%8d%8s" |
, nam |
, nam |
, dbtob(qup->dqblk.dqb_curblocks) / 1024 |
, (int)(dbtob((u_quad_t)qup->dqblk.dqb_curblocks) |
, (msgb == (char *)0) ? ' ' : '*' |
/ 1024) |
, dbtob(qup->dqblk.dqb_bsoftlimit) / 1024 |
, (msgb == (char *)0) ? ' ' : '*' |
, dbtob(qup->dqblk.dqb_bhardlimit) / 1024 |
, (int)(dbtob((u_quad_t)qup->dqblk.dqb_bsoftlimit) |
, (msgb == (char *)0) ? "" |
/ 1024) |
: timeprt(qup->dqblk.dqb_btime)); |
, (int)(dbtob((u_quad_t)qup->dqblk.dqb_bhardlimit) |
|
/ 1024) |
|
, (msgb == (char *)0) ? "" |
|
: timeprt(qup->dqblk.dqb_btime)); |
printf("%8d%c%7d%8d%8s\n" |
printf("%8d%c%7d%8d%8s\n" |
, qup->dqblk.dqb_curinodes |
, qup->dqblk.dqb_curinodes |
, (msgi == (char *)0) ? ' ' : '*' |
, (msgi == (char *)0) ? ' ' : '*' |
, qup->dqblk.dqb_isoftlimit |
, qup->dqblk.dqb_isoftlimit |
, qup->dqblk.dqb_ihardlimit |
, qup->dqblk.dqb_ihardlimit |
, (msgi == (char *)0) ? "" |
, (msgi == (char *)0) ? "" |
: timeprt(qup->dqblk.dqb_itime) |
: timeprt(qup->dqblk.dqb_itime) |
); |
); |
continue; |
continue; |
} |
} |
|
|
heading(type, id, name, "none"); |
heading(type, id, name, "none"); |
} |
} |
|
|
|
void |
heading(type, id, name, tag) |
heading(type, id, name, tag) |
int type; |
int type; |
u_long id; |
u_long id; |
char *name, *tag; |
const char *name, *tag; |
{ |
{ |
|
|
printf("Disk quotas for %s %s (%cid %d): %s\n", qfextension[type], |
printf("Disk quotas for %s %s (%cid %ld): %s\n", qfextension[type], |
name, *qfextension[type], id, tag); |
name, *qfextension[type], id, tag); |
if (!qflag && tag[0] == '\0') { |
if (!qflag && tag[0] == '\0') { |
printf("%15s%8s %7s%8s%8s%8s %7s%8s%8s\n" |
printf("%15s%8s %7s%8s%8s%8s %7s%8s%8s\n" |
, "Filesystem" |
, "Filesystem" |
, "blocks" |
, "blocks" |
, "quota" |
, "quota" |
, "limit" |
, "limit" |
, "grace" |
, "grace" |
, "files" |
, "files" |
, "quota" |
, "quota" |
, "limit" |
, "limit" |
, "grace" |
, "grace" |
); |
); |
} |
} |
} |
} |
|
|
minutes = (seconds + 30) / 60; |
minutes = (seconds + 30) / 60; |
hours = (minutes + 30) / 60; |
hours = (minutes + 30) / 60; |
if (hours >= 36) { |
if (hours >= 36) { |
snprintf(buf, sizeof buf, "%ddays", (hours + 12) / 24); |
(void)snprintf(buf, sizeof buf, "%ddays", |
|
(int)((hours + 12) / 24)); |
return (buf); |
return (buf); |
} |
} |
if (minutes >= 60) { |
if (minutes >= 60) { |
snprintf(buf, sizeof buf, "%2d:%d", minutes / 60, minutes % 60); |
(void)snprintf(buf, sizeof buf, "%2d:%d", |
|
(int)(minutes / 60), (int)(minutes % 60)); |
return (buf); |
return (buf); |
} |
} |
snprintf(buf, sizeof buf, "%2d", minutes); |
(void)snprintf(buf, sizeof buf, "%2d", (int)minutes); |
return (buf); |
return (buf); |
} |
} |
|
|
|
|
*/ |
*/ |
struct quotause * |
struct quotause * |
getprivs(id, quotatype) |
getprivs(id, quotatype) |
register long id; |
long id; |
int quotatype; |
int quotatype; |
{ |
{ |
register struct quotause *qup, *quptail; |
struct quotause *qup, *quptail; |
register struct fstab *fs; |
struct fstab *fs; |
struct quotause *quphead; |
struct quotause *quphead; |
struct statfs *fst; |
struct statfs *fst; |
int nfst, i; |
int nfst, i; |
|
|
qup = quphead = (struct quotause *)0; |
qup = quphead = NULL; |
|
|
nfst = getmntinfo(&fst, MNT_WAIT); |
nfst = getmntinfo(&fst, MNT_WAIT); |
if (nfst == 0) { |
if (nfst == 0) |
fprintf(stderr, "quota: no filesystems mounted!\n"); |
errx(2, "no filesystems mounted!"); |
exit(2); |
|
} |
|
setfsent(); |
setfsent(); |
for (i=0; i<nfst; i++) { |
for (i = 0; i < nfst; i++) { |
if (qup == NULL) { |
if (qup == NULL) { |
if ((qup = (struct quotause *)malloc(sizeof *qup)) == NULL) { |
if ((qup = (struct quotause *)malloc(sizeof *qup)) == NULL) |
fprintf(stderr, "quota: out of memory\n"); |
errx(2, "out of memory"); |
exit(2); |
|
} |
|
} |
} |
if (strncmp(fst[i].f_fstypename, "nfs", MFSNAMELEN) == 0) { |
if (strncmp(fst[i].f_fstypename, "nfs", MFSNAMELEN) == 0) { |
if (getnfsquota(&fst[i], NULL, qup, id, quotatype) == 0) |
if (getnfsquota(&fst[i], NULL, qup, id, quotatype) == 0) |
|
|
/* |
/* |
* Check to see if a particular quota is to be enabled. |
* Check to see if a particular quota is to be enabled. |
*/ |
*/ |
|
int |
ufshasquota(fs, type, qfnamep) |
ufshasquota(fs, type, qfnamep) |
register struct fstab *fs; |
struct fstab *fs; |
int type; |
int type; |
char **qfnamep; |
char **qfnamep; |
{ |
{ |
|
|
static char buf[BUFSIZ]; |
static char buf[BUFSIZ]; |
char *opt, *cp; |
char *opt, *cp; |
|
|
|
cp = NULL; |
if (!initname) { |
if (!initname) { |
snprintf(usrname, sizeof usrname, "%s%s", |
(void)snprintf(usrname, sizeof usrname, "%s%s", |
qfextension[USRQUOTA], qfname); |
qfextension[USRQUOTA], qfname); |
snprintf(grpname, sizeof grpname, "%s%s", |
(void)snprintf(grpname, sizeof grpname, "%s%s", |
qfextension[GRPQUOTA], qfname); |
qfextension[GRPQUOTA], qfname); |
initname = 1; |
initname = 1; |
} |
} |
strncpy(buf, fs->fs_mntops, sizeof buf); |
strncpy(buf, fs->fs_mntops, sizeof buf); |
|
buf[sizeof(buf) - 1] = '\0'; |
for (opt = strtok(buf, ","); opt; opt = strtok(NULL, ",")) { |
for (opt = strtok(buf, ","); opt; opt = strtok(NULL, ",")) { |
if (cp = strchr(opt, '=')) |
if ((cp = strchr(opt, '='))) |
*cp++ = '\0'; |
*cp++ = '\0'; |
if (type == USRQUOTA && strcmp(opt, usrname) == 0) |
if (type == USRQUOTA && strcmp(opt, usrname) == 0) |
break; |
break; |
|
|
*qfnamep = cp; |
*qfnamep = cp; |
return (1); |
return (1); |
} |
} |
(void) snprintf(buf, sizeof buf, "%s/%s.%s", |
(void)snprintf(buf, sizeof buf, "%s/%s.%s", |
fs->fs_file, qfname, qfextension[type]); |
fs->fs_file, qfname, qfextension[type]); |
*qfnamep = buf; |
*qfnamep = buf; |
return (1); |
return (1); |
|
|
|
|
if (quotactl(fs->fs_file, qcmd, id, &qup->dqblk) != 0) { |
if (quotactl(fs->fs_file, qcmd, id, &qup->dqblk) != 0) { |
if ((fd = open(qfpathname, O_RDONLY)) < 0) { |
if ((fd = open(qfpathname, O_RDONLY)) < 0) { |
perror(qfpathname); |
warn("%s", qfpathname); |
return (0); |
return (0); |
} |
} |
(void) lseek(fd, (off_t)(id * sizeof(struct dqblk)), SEEK_SET); |
(void)lseek(fd, (off_t)(id * sizeof(struct dqblk)), SEEK_SET); |
switch (read(fd, &qup->dqblk, sizeof(struct dqblk))) { |
switch (read(fd, &qup->dqblk, sizeof(struct dqblk))) { |
case 0: /* EOF */ |
case 0: /* EOF */ |
/* |
/* |
|
|
case sizeof(struct dqblk): /* OK */ |
case sizeof(struct dqblk): /* OK */ |
break; |
break; |
default: /* ERROR */ |
default: /* ERROR */ |
fprintf(stderr, "quota: read error"); |
warn("read error `%s'", qfpathname); |
perror(qfpathname); |
|
close(fd); |
close(fd); |
return (0); |
return (0); |
} |
} |
|
|
*/ |
*/ |
cp = strchr(fst->f_mntfromname, ':'); |
cp = strchr(fst->f_mntfromname, ':'); |
if (cp == NULL) { |
if (cp == NULL) { |
fprintf(stderr, "cannot find hostname for %s\n", |
warnx("cannot find hostname for %s", fst->f_mntfromname); |
fst->f_mntfromname); |
|
return (0); |
return (0); |
} |
} |
|
|
|
|
case Q_NOQUOTA: |
case Q_NOQUOTA: |
break; |
break; |
case Q_EPERM: |
case Q_EPERM: |
fprintf(stderr, "quota permission error, host: %s\n", |
warnx("permission error, host: %s", fst->f_mntfromname); |
fst->f_mntfromname); |
|
break; |
break; |
case Q_OK: |
case Q_OK: |
gettimeofday(&tv, NULL); |
gettimeofday(&tv, NULL); |
|
|
*cp = ':'; |
*cp = ':'; |
return (1); |
return (1); |
default: |
default: |
fprintf(stderr, "bad rpc result, host: %s\n", |
warnx("bad rpc result, host: %s", fst->f_mntfromname); |
fst->f_mntfromname); |
|
break; |
break; |
} |
} |
*cp = ':'; |
*cp = ':'; |
|
|
int |
int |
callaurpc(host, prognum, versnum, procnum, inproc, in, outproc, out) |
callaurpc(host, prognum, versnum, procnum, inproc, in, outproc, out) |
char *host; |
char *host; |
xdrproc_t inproc, outproc; |
int prognum, versnum, procnum; |
char *in, *out; |
xdrproc_t inproc; |
|
void *in; |
|
xdrproc_t outproc; |
|
void *out; |
{ |
{ |
struct sockaddr_in server_addr; |
struct sockaddr_in server_addr; |
enum clnt_stat clnt_stat; |
enum clnt_stat clnt_stat; |
|
|
return ((int) clnt_stat); |
return ((int) clnt_stat); |
} |
} |
|
|
|
int |
alldigits(s) |
alldigits(s) |
register char *s; |
char *s; |
{ |
{ |
register c; |
int c; |
|
|
c = *s++; |
c = *s++; |
do { |
do { |
if (!isdigit(c)) |
if (!isdigit(c)) |
return (0); |
return (0); |
} while (c = *s++); |
} while ((c = *s++)); |
return (1); |
return (1); |
} |
} |