/* chkquota.c Copyright (c) 2000 Ronny Haryanto Some parts of this code are taken from warnquota.c by Marco van Wieringen. LICENSE: You are free to use and redistribute this source code as long as (1) the copyright notice above remain intact with the source code and (2) you make the source code and any modifications to it available to the public. DISCLAIMER: This is free software. The author(s) offer(s) NO WARRANTY WHATSOEVER. Use at your own risk. Description: Prints a warning message if the user calling this program is over quota, otherwise do nothing (i.e. nothing will be printed). This program is suitable for global login scripts (e.g. call it at the end of /etc/profile). An alternative to using this program is to just call 'quota -q'. COMPILE: gcc -o chkquota chkquota.c INSTALL: anywhere in $PATH, chown 0.0 and chmod 555. Most recently updated: 2000-01-26 rh: initial release 2000-07-31 rh: updated compile instruction and program description BUGS: - only user quota supported at this time - only tested on Linux 2.2.14 TODO: - is there a better way to check if a mounted fs has quota enabled? */ #include #include #include #include #include #include #include #include /* how come it's not in ? */ #define MNTOPT_USRQUOTA "usrquota" /* Calculate the grace period and return a printable string for it */ char *timeprt(time_t seconds) { time_t hours, minutes; static char buf[80]; static time_t now; if (now == 0) time(&now); if (now > seconds) return ("."); seconds -= now; minutes = (seconds + 30) / 60; hours = (minutes + 30) / 60; if (hours >= 36) { sprintf(buf, " within %d days.", (int) (hours + 12) / 24); return (buf); } if (minutes >= 60) { sprintf(buf, " within %2d hours and %2d minutes.", (int) minutes / 60, (int) minutes % 60); return (buf); } sprintf(buf, " within %2d minutes.", (int) minutes); return (buf); } int main() { FILE *fp; struct mntent *mnt; /* check fs that are mounted */ fp = setmntent(_PATH_MOUNTED, "r"); while ((mnt = getmntent(fp)) != (struct mntent *)NULL) { /* does it have quota enabled? */ if(hasmntopt(mnt, MNTOPT_USRQUOTA) != (char *)NULL) { /* yes! check quota for current user */ uid_t uid = getuid(); struct dqblk q; if(quotactl(QCMD(Q_GETQUOTA, USRQUOTA), mnt->mnt_fsname, (int)uid, (caddr_t)&q) < 0) { perror("getquota"); exit(1); } if(q.dqb_bsoftlimit && q.dqb_curblocks >= q.dqb_bsoftlimit) { /* over blocks soft limit */ printf("Over block quota on %s. Please remove %dk%s\n", mnt->mnt_dir, q.dqb_curblocks - q.dqb_bsoftlimit, timeprt(q.dqb_btime)); } if(q.dqb_isoftlimit && q.dqb_curinodes >= q.dqb_isoftlimit) { /* over inodes soft limit */ printf("Over inode quota on %s. Please remove %d files%s\n", mnt->mnt_dir, q.dqb_curinodes - q.dqb_isoftlimit, timeprt(q.dqb_itime)); } } } endmntent(fp); return(0); }