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

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