source: trunk/athena/bin/quota/quota.c @ 7998

Revision 7998, 28.3 KB checked in by cfields, 29 years ago (diff)
SGI changes... (vrt) Reduced an #if !(anysupportedplatform) to #if 0.
Line 
1/*
2 *   Disk quota reporting program.
3 *
4 *   $Id: quota.c,v 1.22 1995-08-23 19:00:08 cfields Exp $
5 */
6
7#ifdef POSIX
8#include <unistd.h>
9#endif
10#include <stdio.h>
11#include <sys/types.h>
12#include <ctype.h>
13#include <errno.h>
14#include <sys/param.h>
15#include <fcntl.h>
16#include <sys/file.h>
17#include <sys/time.h>
18#include <pwd.h>
19#include <grp.h>
20
21#include <rpc/rpc.h>
22#include <rpc/pmap_prot.h>
23#include <rpcsvc/rquota.h>
24#include <rpcsvc/rcquota.h>
25
26#ifdef _IBMR2
27#include <sys/id.h>
28#include <sys/select.h>
29#include <sys/mntctl.h>
30#include <sys/vmount.h>
31#define dbtob(db) ((unsigned)(db) << UBSHIFT)
32
33#else /* !_IBMR2 */
34
35#if defined(SOLARIS)
36/* Sorry, we do not yet support UFS for Solaris */
37#else
38
39#if defined(ultrix) || defined(_I386) || defined(sgi)
40#include <sys/stat.h>
41#include <sys/quota.h>
42#else
43#include <ufs/quota.h>
44#endif
45
46#ifdef ultrix
47#include <sys/mount.h>
48#include <fstab.h>
49#include <sys/fs_types.h>
50#define mntent fs_data
51struct fs_data mountbuffer[NMOUNT];
52#else
53#include <mntent.h>
54#endif
55
56#endif /* !SOLARIS */
57#endif /* !_IBMR2 */
58
59#ifdef ultrix
60#undef mntent
61#endif
62#include "attach.h"
63#ifdef ultrix
64#define mntent fs_data
65#endif
66
67#if defined(vax) || defined(ibm032)
68#include <qoent.h>
69#endif
70
71
72static char *warningstring = NULL;
73
74int     vflag=0, uflag=0, gflag=0, aflag=0;
75#if defined(ultrix) || defined(_I386)
76int     qflag=0, done=0;
77#endif
78
79#define user_and_groups (!uflag && !gflag)
80#define QFNAME  "quotas"
81
82#define kb(n)   (howmany(dbtob(n), 1024))
83
84#define MAXFS 16
85#define MAXID 32
86/* List of id's and filesystems to check */
87char *fslist[MAXFS], *idlist[MAXID];
88int fsind = 0, idind = 0, heading_printed;
89
90main(argc, argv)
91    char *argv[];
92{
93    register char *cp;
94    register int i;
95
96    argc--,argv++;
97    while (argc > 0) {
98        if (argv[0][0] == '-')
99            for (cp = &argv[0][1]; *cp; cp++) switch (*cp) {
100
101            case 'a':
102                aflag=1;
103                break;
104
105            case 'v':
106                vflag=1;
107                break;
108
109#ifdef ultrix
110            case 'q':
111                qflag=1;
112                break;
113#endif
114
115            case 'g':
116                gflag=1;
117                break;
118
119            case 'u':
120                uflag=1;
121                break;
122
123            case 'f':
124                if (fsind < MAXFS)
125                    {
126                        if (argc == 1){
127                            fprintf(stderr, "quota: No filesystem argument\n");
128                            usage();
129                            exit(1);
130                        }
131                        fslist[fsind++] = argv[1];
132                        argv++;
133                        argc--;
134                        break;
135                    }
136                else{
137                    fprintf(stderr, "quota: too many filesystems\n");
138                    exit(1);
139                }
140
141            default:
142                fprintf(stderr, "quota: %c: unknown option\n",
143                        *cp);
144                usage();
145                exit(1);
146            }
147        else if (idind < MAXID)
148            {
149                idlist[idind++] = argv[0];
150            }
151        else{
152            fprintf(stderr, "quota: too many id's\n");
153            exit(1);
154        }
155        argv++;
156        argc--;
157    }
158 
159    if (gflag && uflag) {
160        fprintf(stderr, "quota: Can't use both -g and -u\n");
161        usage();
162        exit(1);
163    }
164
165    if (aflag && fsind) {
166        fprintf(stderr, "quota: Can't use both -a and -f\n");
167        usage();
168        exit(1);
169    }
170
171    if (uflag && idind == 0){
172        idlist[0] = (char*)malloc(20);
173        sprintf(idlist[0],"%d",getuid());
174        idind = 1;
175    }
176
177    if (gflag  && (idind == 0)){
178        fprintf(stderr, "quota: No groups specified\n");
179        usage();
180        exit(1);
181    }
182
183    lock_attachtab();
184    get_attachtab();
185    unlock_attachtab();
186
187    if (fsind) verify_filesystems();
188
189    if (idind == 0) showid(getuid());
190    else
191        for(i=0;i<idind;i++) {
192            heading_printed = 0;
193            if ((!gflag && getpwnam(idlist[i])) ||
194                (gflag && getgrnam(idlist[i])))
195                showname(idlist[i]);
196            else if (alldigits(idlist[i])) showid(atoi(idlist[i]));
197            else showname(idlist[i]);
198        }
199
200    exit(0);
201}
202
203showid(id)
204    int id;
205{
206    register struct passwd *pwd = getpwuid(id);
207    register struct group  *grp = getgrgid(id);
208
209    if (id == 0){
210        if (vflag) printf("no disk quota for %s 0\n",
211                          (gflag ? "gid" : "uid"));
212        return;
213    }
214
215    if (gflag) {
216        if (grp == NULL) showquotas(id, "(no group)");
217        else showquotas(id, grp->gr_name);
218    } else {
219        if (pwd == NULL) showquotas(id, "(no account)");
220        else showquotas(id, pwd->pw_name);
221    }
222    return;
223}
224
225showname(name)
226    char *name;
227{
228    register struct passwd *pwd = getpwnam(name);
229    register struct group  *grp = getgrnam(name);
230
231    if (gflag){
232        if (grp == NULL){
233            fprintf(stderr, "quota: %s: unknown group\n", name);
234            exit(7);
235            return;
236        }
237        if (grp->gr_gid == 0){
238            if (vflag) printf("no disk quota for %s (gid 0)\n", name);
239            return;
240        }
241        showquotas(grp->gr_gid,name);
242    }
243    else{
244        if (pwd == NULL){
245            fprintf(stderr, "quota: %s: unknown user\n", name);
246            exit(8);
247        }
248        if (pwd->pw_uid == 0){
249            if (vflag)
250                printf("no disk quota for %s (uid 0)\n", name);
251            return;
252        }
253        showquotas(pwd->pw_uid,name);
254    }
255}
256
257/* Different enough that it's a mess to ifdef it all individually */
258showquotas(id,name)
259    int id;
260    char *name;
261{
262    int myuid, ngroups, gidset[NGROUPS];
263    struct getcquota_rslt qvalues;
264    struct _attachtab *p;
265    void *v;                            /* Pointer to AFS VolumeStatus */
266    extern void *getafsquota();
267
268#ifdef _IBMR2
269    int mntsize;
270    char *mntbuf;
271    int nmount;
272    struct vmount *vmt;
273    int j;
274#else
275   
276    register struct mntent *mntp;
277    FILE *mtab;
278#ifdef ultrix
279#define mnt_dir fd_path
280#define mnt_fsname fd_devname
281#define Q_GETQUOTA Q_GETDLIM
282    int ultlocalquotas=0;
283    int loc=0, ret;
284#endif
285#ifdef _I386
286#define MNTTYPE_42 MNTTYPE_UFS
287    int ultlocalquotas=0;
288#endif
289
290#endif /* !_IBMR2 */
291#ifdef sgi
292#define MNTTYPE_42 MNTTYPE_EFS
293#endif
294   
295    myuid = getuid();
296
297    if (gflag) {                        /* Must be in group or super-user */
298        if ((ngroups = getgroups(NGROUPS, gidset)) == -1){
299            perror("quota: Couldn't get list of groups.");
300            exit(9);
301        }
302        while(ngroups){ if (id == gidset[ngroups-1]) break; --ngroups;}
303        if (!ngroups && myuid != 0){
304            printf("quota: %s (gid %d): permission denied\n", name, id);
305            return;
306        }
307    }
308    else{
309        if (id != myuid && myuid != 0){
310            printf("quota: %s (uid %d): permission denied\n", name, id);
311            return;
312        }
313    }
314
315#if defined(SOLARIS)
316    /* Don't bother with NFS/UFS yet */
317#else
318   
319#ifdef _IBMR2
320    mntsize = 4096;
321    if ((mntbuf = (char *)malloc(mntsize)) == NULL) {
322        perror("quota: error allocating memory");
323        exit(9);
324    }
325    nmount = mntctl(MCTL_QUERY,mntsize,mntbuf);
326    if (nmount == -1) {
327        perror("quota: mntctl failed");
328        exit(9);
329    }
330    if (nmount == 0) {
331        mntsize = *((int *) mntbuf);
332        if ((mntbuf = (char *)realloc(mntbuf, mntsize)) == NULL) {
333            perror("quota: error reallocing memory");
334            exit(9);
335        }
336        nmount = mntctl(MCTL_QUERY,mntsize,mntbuf);
337        if (nmount == -1) {
338            perror("quota: mntctl failed");
339            exit(9);
340        }
341    }
342
343    vmt = (struct vmount *)mntbuf;
344    for(j=0; j<nmount; j++,vmt=(struct vmount *)((char *)vmt+vmt->vmt_length))
345    {
346        char *dirp;
347
348        dirp = ((char *)vmt+vmt->vmt_data[VMT_STUB].vmt_off);
349        if (fsind) {
350            int i, l;
351            for(i=0;i<fsind;i++){
352                l = strlen(fslist[i]);
353                if(!strncmp(((char *)vmt + vmt->vmt_data[VMT_STUB].vmt_off),
354                            fslist[i], l))
355                    break;
356            }
357            if (i == fsind) continue;   /* Punt filesystems not in fslist */
358        }
359
360        if (!fsind && !aflag && !own(gflag?myuid:id, dirp))
361            continue;
362       
363        if (vmt->vmt_gfstype == MNT_NFS) {
364            if (!getnfsquota(((char *)vmt+vmt->vmt_data[VMT_HOSTNAME].vmt_off),
365                             ((char *)vmt+vmt->vmt_data[VMT_OBJECT].vmt_off),
366                             id, &qvalues))
367                continue;
368        }
369        else
370            continue;
371        if (vflag) prquota(dirp, &qvalues, id, name);     
372        if (user_and_groups || !vflag) warn(dirp, &qvalues);
373    }
374
375#else /* !_IBMR2  */
376
377#ifndef ultrix
378    mtab = setmntent(MOUNTED, "r");
379#else
380    ret = getmountent(&loc, mountbuffer, NMOUNT);
381    if (ret == 0) {
382        perror("getmountent");
383        exit(3);
384    }
385#endif
386
387#ifndef ultrix
388    while(mntp = getmntent(mtab))
389#else
390    for(mntp = mountbuffer; mntp < &mountbuffer[ret]; mntp++)
391#endif
392    {
393        if (fsind)
394        {
395            int i, l;
396
397            for(i=0;i<fsind;i++){
398                l = strlen(fslist[i]);
399                if(!strncmp(mntp->mnt_dir, fslist[i], l))
400                    break;
401            }
402            if (i == fsind) continue;           /* Punt filesystems not
403                                                 * in the fslist */
404        }
405
406#ifndef ultrix
407        if (strcmp(mntp->mnt_type, MNTTYPE_42) == 0) {
408            if (!hasmntopt(mntp, MNTOPT_QUOTA))
409                continue;
410#ifdef _I386
411            ultlocalquotas++;
412            continue;
413#else
414#if !defined(sun) && !defined(sgi)
415            if (getlocalquota(mntp,id,&qvalues) < 0)
416                continue;
417#else
418            continue;
419#endif
420        }
421#endif
422#else /* ultrix */
423        if (mntp->fd_fstype == GT_ULTRIX) {
424            if (mntp->fd_flags & M_QUOTA)
425                ultlocalquotas++;
426            continue;
427        }
428#endif                                          /* ultrix */
429
430#ifndef ultrix
431        if (!strcmp(mntp->mnt_type, MNTTYPE_NFS))
432#else
433        if (mntp->fd_fstype == GT_NFS)
434#endif
435        {
436            char host[128];
437            char path[128];
438            int i;
439
440            if (!fsind && !aflag && !own(gflag?myuid:id, mntp->mnt_dir))
441                continue;
442
443            i = (char *)index(mntp->mnt_fsname, ':') - mntp->mnt_fsname;
444            bcopy(mntp->mnt_fsname, host, i);
445            host[i] = 0;
446            strcpy(path, mntp->mnt_fsname+i+1);
447            if (!getnfsquota(host, path, id, &qvalues))
448                continue;
449        }
450
451        if (vflag) prquota(mntp->mnt_dir, &qvalues, id, name);     
452        if (user_and_groups || !vflag) warn(mntp->mnt_dir, &qvalues);
453    }
454#ifndef ultrix
455    endmntent(mtab);
456#endif
457
458#if defined(ultrix) || defined(_I386)
459    if (ultlocalquotas)
460        ultprintquotas(id,name);
461#endif
462
463#endif /* !_IBMR2 */
464#endif /* !SOLARIS */
465 
466    /* Check afs volumes */
467    for(p = attachtab_first; p!=NULL; p=p->next) {
468        /* Only look at AFS mountpoints; others already done */
469        if ((p->fs->type != TYPE_AFS) || (p->status != STATUS_ATTACHED))
470            continue;
471        if (fsind) {
472            int i, l;
473
474            for(i=0;i<fsind;i++){
475                l = strlen(fslist[i]);
476                if(!strncmp(p->mntpt, fslist[i], l))
477                    break;
478            }
479            if (i == fsind) continue;   /* Punt filesystems not in fslist */
480        }
481
482        if (!fsind && !aflag && !own(gflag?myuid:id, p->mntpt))
483            continue;
484   
485        if ((v = getafsquota(p->mntpt, fsind)) == NULL)
486            continue;
487        if (vflag) prafsquota(p->mntpt, v, id, name);
488        if (user_and_groups || !vflag) afswarn(p->mntpt,v,name);
489    }
490
491    if (warningstring) {
492        printf("\n%s\n", warningstring);
493        free(warningstring);
494        warningstring = NULL;
495    }
496}
497
498/*
499 * FUNCTION:
500 *      own
501 *
502 * ARGUMENTS:
503 *      id      (int)    Id of the person to check.
504 *      dir     (char *) Name of the mountpoint to check.
505 *
506 * RETURN VALUES:
507 *      0       User does not own/maintain the directory in question.
508 *      1       User can modify/maintain the directory in question.
509 *
510 * This routine simply checks the attachtab to see if the id in question
511 * is one of the owners of the filesystem in question.  In addtion, it
512 * performs an access() call to verify the user has write access to the
513 * locker.  The access checks are done as the invoker, and not done as
514 * the passed id, for security reasons.
515 */
516int own(id, dir)
517    int id;
518    char *dir;
519{
520    struct _attachtab *atp;
521    int i;
522    int status;
523
524    atp = attachtab_lookup_mntpt(dir);
525    if (!atp)
526        return 0;
527
528    for(i=0; i<atp->nowners; i++)
529        if (atp->owners[i] == id)
530            return (access(dir, W_OK) == 0);
531
532    return 0;
533}
534
535#ifdef QOTAB
536getlocalquota(mntp, uid, qvp)
537    struct mntent *mntp;
538    int uid;
539    struct getcquota_rslt *qvp;
540{
541    struct qoent *qoent;
542    FILE *qotab;
543    struct dqblk dqblk;
544
545    /* First get the options */
546    qotab = setqoent(QOTAB);
547    while(qoent = getqoent(qotab)){
548        if (!strcmp(mntp->mnt_dir, qoent->mnt_dir))
549            break;
550        else continue;
551    }
552
553    if (!qoent) {       /* this partition has no quota options, use defaults */
554        qvp->rq_group = !strcmp(QOTYPE_DEFAULT, QOTYPE_GROUP);
555        qvp->rq_bsize = DEV_BSIZE;
556        qvp->gqr_zm.rq_bhardlimit = QO_BZHL_DEFAULT;
557        qvp->gqr_zm.rq_bsoftlimit = QO_BZSL_DEFAULT;
558        qvp->gqr_zm.rq_fhardlimit = QO_FZHL_DEFAULT;
559        qvp->gqr_zm.rq_fsoftlimit = QO_FZSL_DEFAULT;
560    }
561    else{
562        /* qoent contains options */
563        qvp->rq_group = QO_GROUP(qoent);
564        qvp->rq_bsize = DEV_BSIZE;
565        qvp->gqr_zm.rq_bhardlimit = qoent->qo_bzhl;
566        qvp->gqr_zm.rq_bsoftlimit = qoent->qo_bzsl;
567        qvp->gqr_zm.rq_fhardlimit = qoent->qo_fzhl;
568        qvp->gqr_zm.rq_fsoftlimit = qoent->qo_fzsl;
569    }
570
571    /* If this filesystem is group controlled and user quota is being
572     * requested, or this is a user controlled filesystem and group
573     * quotas are requested, then punt */
574    if ((qvp->rq_group && uflag) ||
575        (!qvp->rq_group && gflag))
576        return(-1);
577
578    if (uflag || gflag || !qvp->rq_group){
579        if (quotactl(Q_GETQUOTA, mntp->mnt_fsname, uid, &dqblk)){
580            /* ouch! quotas are on, but this failed */
581            fprintf(stderr, "quotactl: %s %d\n", mntp->mnt_fsname, uid);
582            return(-1);
583        }
584
585        qvp->rq_ngrps = 1;
586        dqblk2rcquota(&dqblk,&(qvp->gqr_rcquota[0]), uid);
587        return(0);
588    }
589    else{
590        int groups[NGROUPS], i;
591   
592        qvp->rq_ngrps = getgroups(NGROUPS,groups);
593        for(i=0;i<qvp->rq_ngrps;i++){
594            if (quotactl(Q_GETQUOTA, mntp->mnt_fsname, groups[i], &dqblk)){
595                /* ouch again! */
596                fprintf(stderr, "quotactl: %s %d\n", mntp->mnt_fsname, groups[i]);
597                return(-1);
598            }
599            dqblk2rcquota(&dqblk, &(qvp->gqr_rcquota[i]), groups[i]);
600        }
601        return(0);
602    }
603}
604#endif
605
606void
607simpleheading(id,name)
608    int id;
609    char *name;
610{
611    printf("Disk quotas for %s %s (%s %d):\n",
612           (gflag? "group":"user"), name,
613           (gflag? "gid": "uid"), id);
614    printf("%-12s %7s%7s%7s%12s%7s%7s%7s%12s\n"
615           , "Filesystem"
616           , "usage"
617           , "quota"
618           , "limit"
619           , "timeleft"
620           , "files"
621           , "quota"
622           , "limit"
623           , "timeleft"
624           );
625    heading_printed = 1;
626}
627
628heading(id,name)
629    int id;
630    char *name;
631{
632    printf("Disk quotas for %s (uid %d):\n",name,id);
633    printf("%-16s%-6s%-12s%6s%7s%7s  %7s%7s%7s\n"
634           , "Filesystem"
635           , "Type"
636           , "ID"
637           , "usage", "quota", "limit"
638           , "files", "quota", "limit"
639           );
640    heading_printed = 1;
641}
642
643prquota(dir, qvp, heading_id, heading_name)
644    char *dir;
645    register struct getcquota_rslt *qvp;
646    int heading_id;
647    char *heading_name;
648{
649    struct timeval tv;
650    char ftimeleft[80], btimeleft[80], idbuf[20];
651    char *cp, *id_name = "", *id_type;
652    int i;
653    struct rcquota *rqp;
654
655    id_type = (qvp->rq_group? "group" : "user");
656
657
658    gettimeofday(&tv, NULL);
659
660    for(i=0; i<qvp->rq_ngrps; i++){
661
662        /* If this is root or wheel, then skip */
663        if (qvp->gqr_rcquota[i].rq_id == 0) continue;
664
665        rqp = &(qvp->gqr_rcquota[i]);
666
667        /* We're not interested in this group if all is zero */
668        if (!rqp->rq_bsoftlimit && !rqp->rq_bhardlimit
669            && !rqp->rq_curblocks && !rqp->rq_fsoftlimit
670            && !rqp->rq_fhardlimit && !rqp->rq_curfiles) continue;
671
672        if (user_and_groups){
673            if (qvp->rq_group){
674                getgroupname(qvp->gqr_rcquota[i].rq_id, idbuf);
675                id_name = idbuf;
676            }
677            else{                               /* this is a user quota */
678                getusername(qvp->gqr_rcquota[i].rq_id, idbuf);
679                id_name = idbuf;
680            }
681        }
682
683        /* Correct for zero quotas... */
684        if(!rqp->rq_bsoftlimit)
685            rqp->rq_bsoftlimit = qvp->gqr_zm.rq_bsoftlimit;
686        if(!rqp->rq_bhardlimit)
687            rqp->rq_bhardlimit = qvp->gqr_zm.rq_bhardlimit;
688        if(!rqp->rq_fsoftlimit)
689            rqp->rq_fsoftlimit = qvp->gqr_zm.rq_fsoftlimit;
690        if(!rqp->rq_fhardlimit)
691            rqp->rq_fhardlimit = qvp->gqr_zm.rq_fhardlimit;
692
693        if (!rqp->rq_bsoftlimit && !rqp->rq_bhardlimit &&
694            !rqp->rq_fsoftlimit && !rqp->rq_fhardlimit)
695            /* Skip this entirely for compatibility */
696            continue;
697
698        if (rqp->rq_bsoftlimit &&
699            rqp->rq_curblocks >= rqp->rq_bsoftlimit) {
700            if (rqp->rq_btimeleft == 0) {
701                strcpy(btimeleft, "NOT STARTED");
702            } else if (rqp->rq_btimeleft > tv.tv_sec) {
703                fmttime(btimeleft, rqp->rq_btimeleft - tv.tv_sec);
704            } else {
705                strcpy(btimeleft, "EXPIRED");
706            }
707        } else {
708            btimeleft[0] = '\0';
709        }
710        if (rqp->rq_fsoftlimit &&
711            rqp->rq_curfiles >= rqp->rq_fsoftlimit) {
712            if (rqp->rq_ftimeleft == 0) {
713                strcpy(ftimeleft, "NOT STARTED");
714            } else if (rqp->rq_ftimeleft > tv.tv_sec) {
715                fmttime(ftimeleft, rqp->rq_ftimeleft - tv.tv_sec);
716            } else {
717                strcpy(ftimeleft, "EXPIRED");
718            }
719        } else {
720            ftimeleft[0] = '\0';
721        }
722
723        cp = dir;
724
725        if (!user_and_groups){
726            if (!heading_printed) simpleheading(heading_id,heading_name);
727            if (strlen(cp) > 15){
728                printf("%s\n",cp);
729                cp = "";
730            }
731            printf("%-14s %5d%7d%7d%12s%7d%7d%7d%12s\n",
732                   cp,
733                   kb(rqp->rq_curblocks),
734                   kb(rqp->rq_bsoftlimit),
735                   kb(rqp->rq_bhardlimit),
736                   btimeleft,
737                   rqp->rq_curfiles,
738                   rqp->rq_fsoftlimit,
739                   rqp->rq_fhardlimit,
740                   ftimeleft
741                   );
742        }
743        else{
744            if (!heading_printed) heading(heading_id,heading_name);
745            if (strlen(cp) > 16){
746                printf("%s\n", cp);
747                cp =  "";
748            }
749            printf("%-16s%-6s%-12.12s%6d%7d%7d%-2s%7d%7d%7d%-2s\n",
750                   cp, id_type, id_name,
751                   kb(rqp->rq_curblocks),
752                   kb(rqp->rq_bsoftlimit),
753                   kb(rqp->rq_bhardlimit),
754                   (btimeleft[0]? "<<" : ""),
755                   rqp->rq_curfiles,
756                   rqp->rq_fsoftlimit,
757                   rqp->rq_fhardlimit,
758                   (ftimeleft[0]? "<<" : ""));
759        }
760    }
761}
762 
763warn(dir, qvp)
764    char *dir;
765    register struct getcquota_rslt *qvp;
766{
767    struct timeval tv;
768    int i;
769    char buf[1024], idbuf[20];
770    char *id_name, *id_type;
771    struct rcquota *rqp;
772
773    id_type = (qvp->rq_group? "Group" : "User");
774
775    gettimeofday(&tv, NULL);
776
777    for(i=0; i<qvp->rq_ngrps; i++){
778
779        /* If this is root or wheel, then skip */
780        if (qvp->gqr_rcquota[i].rq_id == 0) continue;
781
782        if (qvp->rq_group){
783            getgroupname(qvp->gqr_rcquota[i].rq_id, idbuf);
784            id_name = idbuf;
785        }
786        else{
787            getusername(qvp->gqr_rcquota[i].rq_id, idbuf);
788            id_name = idbuf;
789        }
790
791        rqp = &(qvp->gqr_rcquota[i]);
792
793        /* Correct for zero quotas... */
794        if(!rqp->rq_bsoftlimit)
795            rqp->rq_bsoftlimit = qvp->gqr_zm.rq_bsoftlimit;
796        if(!rqp->rq_bhardlimit)
797            rqp->rq_bhardlimit = qvp->gqr_zm.rq_bhardlimit;
798        if(!rqp->rq_fsoftlimit)
799            rqp->rq_fsoftlimit = qvp->gqr_zm.rq_fsoftlimit;
800        if(!rqp->rq_fhardlimit)
801            rqp->rq_fhardlimit = qvp->gqr_zm.rq_fhardlimit;
802
803        /* Now check for over...*/
804        if(rqp->rq_bhardlimit &&
805           rqp->rq_curblocks >= rqp->rq_bhardlimit){
806            sprintf(buf,
807                    "Block limit reached for %s %s on %s\n",
808                    id_type, id_name, dir);
809            putwarning(buf);
810        }
811
812        else if (rqp->rq_bsoftlimit &&
813                 rqp->rq_curblocks >= rqp->rq_bsoftlimit){
814            if (rqp->rq_btimeleft == 0) {
815                sprintf(buf,
816                        "%s %s over disk quota on %s, remove %dK\n",
817                        id_type, id_name, dir,
818                        kb(rqp->rq_curblocks - rqp->rq_bsoftlimit + 1));
819                putwarning(buf);
820            }
821            else if (rqp->rq_btimeleft > tv.tv_sec) {
822                char btimeleft[80];
823
824                fmttime(btimeleft, rqp->rq_btimeleft - tv.tv_sec);
825                sprintf(buf,
826                        "%s %s over disk quota on %s, remove %dK within %s\n",
827                        id_type, id_name, dir,
828                        kb(rqp->rq_curblocks - rqp->rq_bsoftlimit + 1),
829                        btimeleft);
830                putwarning(buf);
831            }
832            else {
833                sprintf(buf,
834                        "%s %s over disk quota on %s, time limit has expired, remove %dK\n",
835                        id_type, id_name, dir,
836                        kb(rqp->rq_curblocks - rqp->rq_bsoftlimit + 1));
837                putwarning(buf);
838            }
839        }
840
841        if (rqp->rq_fhardlimit &&
842            rqp->rq_curfiles >= rqp->rq_fhardlimit){
843            sprintf(buf,
844                    "File count limit reached for %s %s on %s\n",
845                    id_type, id_name, dir);
846            putwarning(buf);
847        }
848
849        else if (rqp->rq_fsoftlimit &&
850                 rqp->rq_curfiles >= rqp->rq_fsoftlimit) {
851            if (rqp->rq_ftimeleft == 0) {
852                sprintf(buf,
853                        "%s %s over file quota on %s, remove %d file%s\n",
854                        id_type, id_name, dir,
855                        rqp->rq_curfiles - rqp->rq_fsoftlimit + 1,
856                        ((rqp->rq_curfiles - rqp->rq_fsoftlimit + 1) > 1 ?
857                         "s" : "" ));
858                putwarning(buf);
859            }
860
861            else if (rqp->rq_ftimeleft > tv.tv_sec) {
862                char ftimeleft[80];
863
864                fmttime(ftimeleft, rqp->rq_ftimeleft - tv.tv_sec);
865                sprintf(buf,
866                        "%s %s over file quota on %s, remove %d file%s within %s\n",
867                        id_type, id_name, dir,
868                        rqp->rq_curfiles - rqp->rq_fsoftlimit + 1,
869                        ((rqp->rq_curfiles - rqp->rq_fsoftlimit + 1) > 1 ?
870                         "s" : "" ), ftimeleft);
871                putwarning(buf);
872            }
873            else {
874                sprintf(buf,
875                        "%s %s over file quota on %s, time limit has expired, remove %d file%s\n",
876                        id_type, id_name, dir,
877                        rqp->rq_curfiles - rqp->rq_fsoftlimit + 1,
878                        ((rqp->rq_curfiles - rqp->rq_fsoftlimit + 1) > 1 ?
879                         "s" : "" ));
880                putwarning(buf);
881            }
882        }
883    }
884}
885
886usage()
887{
888    fprintf(stderr,
889            "Usage: quota [-v] [user] [-g group] [-u user] [-f filesystem]\n");
890}
891
892alldigits(s)
893    register char *s;
894{
895    register int c;
896   
897    c = *s++;
898    do {
899        if (!isdigit(c))
900            return (0);
901    } while (c = *s++);
902    return (1);
903}
904
905#if 0
906dqblk2rcquota(dqblkp, rcquotap, uid)
907    struct dqblk *dqblkp;
908    struct rcquota *rcquotap;
909    int uid;
910{
911    rcquotap->rq_id = uid;
912    rcquotap->rq_bhardlimit = dqblkp->dqb_bhardlimit;
913    rcquotap->rq_bsoftlimit = dqblkp->dqb_bsoftlimit;
914    rcquotap->rq_curblocks  = dqblkp->dqb_curblocks;
915    rcquotap->rq_fhardlimit = dqblkp->dqb_fhardlimit;
916    rcquotap->rq_fsoftlimit = dqblkp->dqb_fsoftlimit;
917    rcquotap->rq_curfiles   = dqblkp->dqb_curfiles;
918    rcquotap->rq_btimeleft  = dqblkp->dqb_btimelimit;
919    rcquotap->rq_ftimeleft  = dqblkp->dqb_ftimelimit;
920}
921#endif
922   
923getgroupname(id,buffer)
924    int id;
925    char *buffer;
926{
927    if (getgrgid(id))
928        strcpy(buffer, (getgrgid(id))->gr_name);
929    else{
930        sprintf(buffer, "G%d", id);
931    }
932}
933
934getusername(id,buffer)
935    int id;
936    char *buffer;
937{
938    if (getpwuid(id))
939        strcpy(buffer, (getpwuid(id))->pw_name);
940    else{
941        sprintf(buffer, "#%d", id);
942    }
943}
944
945putwarning(string)
946    char *string;
947{
948    static int warningmaxsize = 0;
949 
950    if (warningstring == 0){
951        warningstring = (char*)malloc(10);
952        warningstring[0] = '\0';
953        warningmaxsize = 10;
954    }
955
956    while (strlen(warningstring) + strlen(string) + 1 > warningmaxsize){
957        warningstring = (char*)realloc(warningstring, (warningmaxsize * 3)/2);
958        warningmaxsize = (warningmaxsize * 3) / 2;
959    }
960
961    sprintf(&warningstring[strlen(warningstring)], "%s", string);
962}
963
964fmttime(buf, time)
965    char *buf;
966    register long time;
967{
968    int i;
969    static struct {
970        int c_secs;                             /* conversion units in secs */
971        char * c_str;                           /* unit string */
972    } cunits [] = {
973        {60*60*24*28, "months"},
974        {60*60*24*7, "weeks"},
975        {60*60*24, "days"},
976        {60*60, "hours"},
977        {60, "mins"},
978        {1, "secs"}
979    };
980
981    if (time <= 0) {
982        strcpy(buf, "EXPIRED");
983        return;
984    }
985    for (i = 0; i < sizeof(cunits)/sizeof(cunits[0]); i++) {
986        if (time >= cunits[i].c_secs)
987            break;
988    }
989    sprintf(buf, "%.1f %s", (double)time/cunits[i].c_secs, cunits[i].c_str);
990}
991
992#ifdef SOLARIS
993verify_filesystems()
994{
995}
996#else
997#ifdef _IBMR2
998verify_filesystems()
999{
1000    int i, j, found, l;
1001    int mntsize;
1002    char *mntbuf;
1003    int nmount;
1004    struct vmount *vmt;
1005    struct _attachtab *atp;
1006
1007    mntsize = 4096;
1008    if ((mntbuf = (char *)malloc(mntsize)) == NULL) {
1009        perror("quota: error allocating memory");
1010        exit(9);
1011    }
1012    nmount = mntctl(MCTL_QUERY,mntsize,mntbuf);
1013    if (nmount == -1) {
1014        perror("quota: mntctl failed");
1015        exit(9);
1016    }
1017    if (nmount == 0) {
1018        mntsize = *((int *) mntbuf);
1019        if ((mntbuf = (char *)realloc(mntbuf, mntsize)) == NULL) {
1020            perror("quota: error reallocing memory");
1021            exit(9);
1022        }
1023        nmount = mntctl(MCTL_QUERY,mntsize,mntbuf);
1024        if (nmount == -1) {
1025            perror("quota: mntctl failed");
1026            exit(9);
1027        }
1028    }
1029
1030    for(i=0;i<fsind;i++){
1031        l = strlen(fslist[i]);
1032        found = 0;
1033        vmt = (struct vmount *)mntbuf;
1034        for(j=0;j<nmount;j++) {
1035            if (!strncmp(fslist[i],
1036                         (char *)vmt+vmt->vmt_data[VMT_STUB].vmt_off,l)) {
1037                found = 1;
1038                break;
1039            }
1040            vmt = (struct vmount *)((char *)vmt + vmt->vmt_length);
1041        }
1042        if (!found && (atp = attachtab_lookup(fslist[i]))) {
1043            fslist[i] = atp->mntpt;
1044            found = 1;
1045            break;
1046        }
1047        if (!found && (attachtab_lookup_mntpt(fslist[i]) == NULL)) {
1048            fprintf(stderr, "quota: '%s' matches no mounted filesystems.\n",
1049                    fslist[i]);
1050            exit(10);
1051        }
1052    }
1053}
1054
1055#else /* _IBMR2 */
1056
1057verify_filesystems()
1058{
1059    struct _attachtab *atp;
1060    struct mntent *mntp;
1061    FILE *mtab;
1062    int i,l, found;
1063#ifdef ultrix
1064    int loc=0, ret;
1065#endif
1066 
1067    for(i=0;i<fsind;i++){
1068        l = strlen(fslist[i]);
1069        found = 0;
1070#ifndef ultrix
1071        mtab = setmntent(MOUNTED, "r");
1072#else
1073        ret = getmountent(&loc, mountbuffer, NMOUNT);
1074        if (ret == 0) {
1075            perror("getmountent");
1076            exit(3);
1077        }
1078#endif
1079       
1080#ifndef ultrix
1081        while(mntp = getmntent(mtab))
1082#else
1083        for(mntp = mountbuffer; mntp < &mountbuffer[ret]; mntp++)
1084#endif
1085        {
1086            if (!strncmp(fslist[i], mntp->mnt_dir,l)){
1087                found = 1;
1088                break;
1089            }
1090        }
1091#ifndef ultrix
1092        endmntent(mtab);
1093#endif
1094        if (!found && (atp = attachtab_lookup(fslist[i]))) {
1095            fslist[i] = atp->mntpt;
1096            found = 1;
1097            break;
1098        }
1099        if (!found && (attachtab_lookup_mntpt(fslist[i]) == NULL)) {
1100            fprintf(stderr, "quota: '%s' matches no mounted filesystems.\n",
1101                    fslist[i]);
1102            exit(10);
1103        }
1104    }
1105}
1106#endif /* IBMR2 */
1107#endif /* SOLARIS */
1108
1109#if defined(_I386) || defined(ultrix)
1110ultprintquotas(uid, name)
1111    int uid;
1112    char *name;
1113{
1114    register char c, *p;
1115    register struct fstab *fs;
1116    int myuid;
1117#ifdef _I386
1118    FILE        *fptr;
1119    struct      mntent  *buf;
1120#endif
1121   
1122    myuid = getuid();
1123    if (uid != myuid && myuid != 0) {
1124        printf("quota: %s (uid %d): permission denied\n", name, uid);
1125        return;
1126    }
1127    done = 0;
1128#ifdef ultrix
1129    setfsent();
1130    while (fs = getfsent()) {
1131#else
1132    /* Deal with FSTAB */
1133    fptr = setmntent("/etc/mtab","r");
1134    while((buf = getmntent(fptr)) != NULL) {
1135        dev_t           qf_gfs;
1136#endif
1137        register char *msgi = (char *)0, *msgb = (char *)0;
1138        register int enab = 1;
1139        dev_t   fsdev;
1140        struct  stat statb;
1141        struct  dqblk dqblk;
1142        char qfilename[MAXPATHLEN + 1], iwarn[8], dwarn[8];
1143        char            *vol;
1144       
1145#ifdef _I386
1146        if (hasmntopt(buf, MNTOPT_QUOTA) == NULL)
1147            continue;
1148        vol = buf->mnt_dir;
1149        (void) sprintf(qfilename, "%s/%s", buf->mnt_dir, QFNAME);
1150        if (stat(qfilename, &statb) < 0)
1151            continue;
1152        qf_gfs = buf->mnt_gfs;
1153        if (quota(Q_SYNC, 0, (gfs_t) qf_gfs, (caddr_t) 0) < 0 &&                                 errno == EINVAL)
1154            continue;
1155        sync();
1156        if (quota(Q_GETDLIM, uid, qf_gfs, (caddr_t) &dqblk) != 0)
1157#else
1158        if (stat(fs->fs_spec, &statb) < 0)
1159            continue;
1160        fsdev = statb.st_rdev;
1161        vol = fs->fs_file;
1162        (void) sprintf(qfilename, "%s/%s", fs->fs_file, QFNAME);
1163        if (stat(qfilename, &statb) < 0 || statb.st_dev != fsdev)
1164            continue;
1165        if (quota(Q_GETDLIM, uid, fsdev, &dqblk) != 0)
1166#endif
1167        {
1168            register fd = open(qfilename, O_RDONLY);
1169
1170            if (fd < 0)
1171                continue;
1172            lseek(fd, (long)(uid * sizeof (dqblk)), L_SET);
1173            if (read(fd, &dqblk, sizeof dqblk) != sizeof (dqblk)) {
1174                close(fd);
1175                continue;
1176            }
1177            close(fd);
1178            if (dqblk.dqb_isoftlimit == 0 &&
1179                dqblk.dqb_bsoftlimit == 0)
1180                continue;
1181            enab = 0;
1182        }
1183        if (dqblk.dqb_ihardlimit &&
1184            dqblk.dqb_curinodes >= dqblk.dqb_ihardlimit)
1185            msgi = "File count limit reached on %s";
1186        else if (enab && dqblk.dqb_iwarn == 0)
1187            msgi = "Out of inode warnings on %s";
1188        else if (dqblk.dqb_isoftlimit &&
1189                 dqblk.dqb_curinodes >= dqblk.dqb_isoftlimit)
1190            msgi = "Too many files on %s";
1191        if (dqblk.dqb_bhardlimit &&
1192            dqblk.dqb_curblocks >= dqblk.dqb_bhardlimit)
1193            msgb = "Block limit reached on %s";
1194        else if (enab && dqblk.dqb_bwarn == 0)
1195            msgb = "Out of block warnings on %s";
1196        else if (dqblk.dqb_bsoftlimit &&
1197                 dqblk.dqb_curblocks >= dqblk.dqb_bsoftlimit)
1198            msgb = "Over disc quota on %s";
1199        if (dqblk.dqb_iwarn < MAX_IQ_WARN)
1200            sprintf(iwarn, "%d", dqblk.dqb_iwarn);
1201        else
1202            iwarn[0] = '\0';
1203        if (dqblk.dqb_bwarn < MAX_DQ_WARN)
1204            sprintf(dwarn, "%d", dqblk.dqb_bwarn);
1205        else
1206            dwarn[0] = '\0';
1207        if (qflag) {
1208            if (msgi != (char *)0 || msgb != (char *)0)
1209                ultheading(uid, name);
1210            if (msgi != (char *)0)
1211                xprintf(msgi, vol);
1212            if (msgb != (char *)0)
1213                xprintf(msgb, vol);
1214            continue;
1215        }
1216        if (vflag || dqblk.dqb_curblocks || dqblk.dqb_curinodes) {
1217            ultheading(uid, name);
1218            printf("%10s%8d%c%7d%8d%8s%8d%c%7d%8d%8s\n"
1219                   , vol
1220                   , (dqblk.dqb_curblocks / btodb(1024))
1221                   , (msgb == (char *)0) ? ' ' : '*'
1222                   , (dqblk.dqb_bsoftlimit / btodb(1024))
1223                   , (dqblk.dqb_bhardlimit / btodb(1024))
1224                   , dwarn
1225                   , dqblk.dqb_curinodes
1226                   , (msgi == (char *)0) ? ' ' : '*'
1227                   , dqblk.dqb_isoftlimit
1228                   , dqblk.dqb_ihardlimit
1229                   , iwarn
1230                   );
1231        }
1232    }
1233#ifdef _I386
1234    endmntent(fptr);
1235#else
1236    endfsent();
1237#endif
1238    if (!done && !qflag) {
1239        if (idind)
1240            putchar('\n');
1241        xprintf("Disc quotas for %s (uid %d):", name, uid);
1242        xprintf("none.");
1243    }
1244    xprintf(0);
1245}
1246
1247ultheading(uid, name)
1248    int uid;
1249    char *name;
1250{
1251   
1252    if (done++)
1253        return;
1254    xprintf(0);
1255    if (qflag) {
1256        if (!idind)
1257            return;
1258        xprintf("User %s (uid %d):", name, uid);
1259        xprintf(0);
1260        return;
1261    }
1262    putchar('\n');
1263#if 0
1264    xprintf("Disc quotas for %s (uid %d):", name, uid);
1265#endif
1266    xprintf(0);
1267    printf("%10s%8s %7s%8s%8s%8s %7s%8s%8s\n"
1268           , "Filsys"
1269           , "current"
1270           , "quota"
1271           , "limit"
1272           , "#warns"
1273           , "files"
1274           , "quota"
1275           , "limit"
1276           , "#warns"
1277           );
1278}
1279
1280xprintf(fmt, arg1, arg2, arg3, arg4, arg5, arg6)
1281    char *fmt;
1282{
1283    char        buf[100];
1284    static int column;
1285
1286    if (fmt == 0 && column || column >= 40) {
1287        putchar('\n');
1288        column = 0;
1289    }
1290    if (fmt == 0)
1291        return;
1292    sprintf(buf, fmt, arg1, arg2, arg3, arg4, arg5, arg6);
1293    if (column != 0 && strlen(buf) < 39)
1294        while (column++ < 40)
1295            putchar(' ');
1296    else if (column) {
1297        putchar('\n');
1298        column = 0;
1299    }
1300    printf("%s", buf);
1301    column += strlen(buf);
1302}
1303#endif /* _I386 || ultrix */
Note: See TracBrowser for help on using the repository browser.