/* Copyright 1999 by the Massachusetts Institute of Technology. * * Permission to use, copy, modify, and distribute this * software and its documentation for any purpose and without * fee is hereby granted, provided that the above copyright * notice appear in all copies and that both that copyright * notice and this permission notice appear in supporting * documentation, and that the name of M.I.T. not be used in * advertising or publicity pertaining to distribution of the * software without specific, written prior permission. * M.I.T. makes no representations about the suitability of * this software for any purpose. It is provided "as is" * without express or implied warranty. */ /* Routines for retrieving local filesystem quotas. */ static const char rcsid[] = "$Id: ufs.c,v 1.3 1999-07-07 22:39:17 danw Exp $"; #include #include #include #include #include #include #include #include "quota.h" static void print_timeout(time_t time); static int os_quotactl(struct quota_fs *fs, uid_t uid); int get_local_quota(struct quota_fs *fs, uid_t uid, int verbose) { int status; #ifdef IRIX struct fs_disk_quota fdq; /* Irix uses a different quota structure for XFS only. */ if (!strcmp(fs->type, "xfs")) { status = quotactl(Q_XGETQUOTA, fs->device, uid, (caddr_t)&fdq); if (status == 0) { fs->dqb.dqb_curblocks = fdq.d_bcount; fs->dqb.dqb_bsoftlimit = fdq.d_blk_softlimit; fs->dqb.dqb_bhardlimit = fdq.d_blk_hardlimit; fs->dqb.dqb_btimelimit = fdq.d_btimer; fs->dqb.dqb_curfiles = fdq.d_icount; fs->dqb.dqb_fsoftlimit = fdq.d_ino_softlimit; fs->dqb.dqb_fhardlimit= fdq.d_ino_hardlimit; fs->dqb.dqb_ftimelimit = fdq.d_itimer; fs->have_quota = fs->have_files = fs->have_blocks = 1; } } else #endif /* IRIX */ { status = os_quotactl(fs, uid); if (status == 0) fs->have_quota = fs->have_files = fs->have_blocks = 1; } if (fs->have_quota) { if (fs->dqb.dqb_btimelimit) fs->warn_blocks = 1; if (fs->dqb.dqb_ftimelimit) fs->warn_files = 1; } /* Give an error message for anything but ESRCH/EINVAL ("Quotas not * enabled for this filesystem.") or EOPNOTSUPP ("No kernel support * for quotas.") */ if (status == -1 && errno != ESRCH && errno != EINVAL && errno != EOPNOTSUPP) { fprintf(stderr, "quota: Could not get quota for %s (%s): %s\n", fs->mount, fs->device, strerror(errno)); return -1; } return 0; } #ifndef SOLARIS int os_quotactl(struct quota_fs *fs, uid_t uid) { #ifdef BSD_QUOTACTL return quotactl(fs->mount, QCMD(Q_GETQUOTA, USRQUOTA), uid, (caddr_t)&fs->dqb); #else return quotactl(Q_GETQUOTA, fs->device, uid, (caddr_t)&fs->dqb); #endif } #else int os_quotactl(struct quota_fs *fs, uid_t uid) { int fd, status; char *path; struct quotctl qctl; path = malloc(strlen(fs->mount) + 8); if (!path) return -1; sprintf(path, "%s/quotas", fs->mount); fd = open(path, O_RDONLY); free(path); if (fd == -1) { if (errno == ENOENT) errno = ESRCH; return -1; } qctl.op = Q_GETQUOTA; qctl.uid = uid; qctl.addr = (caddr_t)&fs->dqb; status = ioctl(fd, Q_QUOTACTL, &qctl); close(fd); return status; } #endif /* This is used for both UFS and NFS. */ void print_mounted_warning(struct quota_fs *fs) { time_t now = time(NULL); if (fs->dqb.dqb_bhardlimit && (fs->dqb.dqb_curblocks >= fs->dqb.dqb_bhardlimit)) printf("Block limit reached on %s\n", fs->mount); else if (fs->dqb.dqb_bsoftlimit && (fs->dqb.dqb_curblocks >= fs->dqb.dqb_bsoftlimit)) { printf("Over disk quota on %s, remove %dK", fs->mount, (fs->dqb.dqb_curblocks - fs->dqb.dqb_bsoftlimit + 1) / 2); if (fs->dqb.dqb_btimelimit > now) print_timeout(fs->dqb.dqb_btimelimit - now); else if (fs->dqb.dqb_btimelimit != 0) printf(" immediately"); printf("\n"); } if (fs->dqb.dqb_fhardlimit && (fs->dqb.dqb_curfiles >= fs->dqb.dqb_fhardlimit)) printf("File count limit reached on %s\n", fs->mount); else if (fs->dqb.dqb_fsoftlimit && (fs->dqb.dqb_curfiles >= fs->dqb.dqb_fsoftlimit)) { int remfiles = fs->dqb.dqb_curfiles - fs->dqb.dqb_fsoftlimit + 1; printf("Over file quota on %s, remove %d file%s", fs->mount, remfiles, remfiles > 1 ? "s" : ""); if (fs->dqb.dqb_ftimelimit > now) print_timeout(fs->dqb.dqb_ftimelimit - now); else if (fs->dqb.dqb_ftimelimit != 0) printf(" immediately"); printf("\n"); } } static void print_timeout(time_t time) { int i; static struct { int c_secs; /* conversion units in secs */ char *c_str; /* unit string */ } cunits [] = { {60 * 60 * 24 * 7 * 4, "months"}, {60 * 60 * 24 * 7, "weeks"}, {60 * 60 * 24, "days"}, {60 * 60, "hours"}, {60, "mins"}, {1, "secs"} }; for (i = 0; i < sizeof(cunits) / sizeof(cunits[0]); i++) { if (time >= cunits[i].c_secs) break; } printf(" within %.1f %s", (double)time / cunits[i].c_secs, cunits[i].c_str); }