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

Revision 24068, 6.3 KB checked in by broder, 15 years ago (diff)
cd
Line 
1/* Copyright 1999 by the Massachusetts Institute of Technology.
2 *
3 * Permission to use, copy, modify, and distribute this
4 * software and its documentation for any purpose and without
5 * fee is hereby granted, provided that the above copyright
6 * notice appear in all copies and that both that copyright
7 * notice and this permission notice appear in supporting
8 * documentation, and that the name of M.I.T. not be used in
9 * advertising or publicity pertaining to distribution of the
10 * software without specific, written prior permission.
11 * M.I.T. makes no representations about the suitability of
12 * this software for any purpose.  It is provided "as is"
13 * without express or implied warranty.
14 */
15
16/* This is quota, which abstracts quota-checking mechanisms for
17 * various types of lockers.
18 */
19
20static const char rcsid[] = "$Id: quota.c,v 1.27 1999-11-22 16:00:16 danw Exp $";
21
22#include <ctype.h>
23#include <pwd.h>
24#include <signal.h>
25#include <stdio.h>
26#include <stdlib.h>
27#include <string.h>
28#include <unistd.h>
29
30#include <locker.h>
31#include "quota.h"
32
33char **fsnames;
34locker_context context;
35
36static void usage(void);
37static void print_quota(struct quota_fs *fs);
38static void heading(uid_t uid, char *name);
39static int alldigits(char *s);
40
41int main(int argc, char **argv)
42{
43  int opt, i, status;
44  struct passwd *pw;
45  uid_t myuid;
46  int all = 0;
47  char *user;
48  uid_t uid;
49  int fsind = 0, fssize = 0, heading_printed = 0;
50  int verbose = 0;
51  struct quota_fs *fslist = NULL;
52  sigset_t mask;
53
54  myuid = getuid();
55  if (locker_init(&context, myuid, NULL, NULL) != LOCKER_SUCCESS)
56    {
57      fprintf(stderr, "quota: Could not initialize locker library.\n");
58      exit(1);
59    }
60
61  /* Block ^Z to prevent holding locks on the attachtab. */
62  sigemptyset(&mask);
63  sigaddset(&mask, SIGTSTP);
64  sigaddset(&mask, SIGTTOU);
65  sigaddset(&mask, SIGTTIN);
66  sigprocmask(SIG_BLOCK, &mask, NULL);
67
68  while ((opt = getopt(argc, argv, "af:guv")) != -1)
69    {
70      switch (opt)
71        {
72        case 'a':
73          all = 1;
74          break;
75
76        case 'v':
77          verbose = 1;
78          break;
79
80        case 'g':
81          fprintf(stderr, "quota: Group quotas no longer supported.\n");
82          exit(1);
83          break;
84
85        case 'u':
86          /* Backward-compatibility option. */
87          verbose = 1;
88          break;
89
90        case 'f':
91          if (fsind >= fssize - 1)
92            {
93              fssize = 2 * (fssize + 1);
94              fsnames = realloc(fsnames, fssize * sizeof(char *));
95              if (!fsnames)
96                {
97                  fprintf(stderr, "quota: Out of memory.\n");
98                  exit(1);
99                }
100            }
101
102          if (!strchr(optarg, '/'))
103            {
104              locker_attachent *at;
105
106              if (locker_read_attachent(context, optarg, &at) !=
107                  LOCKER_SUCCESS)
108                {
109                  fprintf(stderr, "quota: Unknown filesystem %s.\n", optarg);
110                  exit(1);
111                }
112              fsnames[fsind++] = strdup(at->mountpoint);
113              locker_free_attachent(context, at);
114            }
115          else
116            fsnames[fsind++] = optarg;
117          break;
118
119        default:
120          fprintf(stderr, "quota: %s: unknown option\n", argv[optind - 1]);
121          usage();
122          exit(1);
123        }
124    }
125
126  if (fsind)
127    {
128      if (all)
129        {
130          fprintf(stderr, "quota: Can't use both -a and -f\n");
131          usage();
132          exit(1);
133        }
134      fsnames[fsind] = NULL;
135    }
136
137  if (optind < argc)
138    {
139      if (optind < argc - 1)
140        {
141          fprintf(stderr, "quota: Can only specify a single user.\n");
142          exit(1);
143        }
144
145      if (alldigits(argv[optind]))
146        {
147          uid = atoi(argv[optind]);
148
149          pw = getpwuid(uid);
150          if (pw)
151            user = strdup(pw->pw_name);
152          else
153            user = "(no account)";
154        }
155      else
156        {
157          user = argv[optind];
158
159          pw = getpwnam(user);
160          if (pw)
161            uid = pw->pw_uid;
162          else
163            {
164              fprintf(stderr, "quota: No passwd entry for user %s.\n", user);
165              exit(1);
166            }
167        }
168
169      /* Check permission if not root. */
170      if (myuid != 0 && uid != myuid)
171        {
172          fprintf(stderr, "quota: %s (uid %lu): permission denied\n",
173                  user, (unsigned long) uid);
174          exit(1);
175        }
176    }
177  else
178    {
179      /* Use real uid. */
180      uid = myuid;
181      pw = getpwuid(myuid);
182      if (!pw)
183        {
184          fprintf(stderr, "quota: Could not get password entry for uid %lu.\n",
185                  (unsigned long) myuid);
186          exit(1);
187        }
188      user = strdup(pw->pw_name);
189    }
190
191  if (uid == 0)
192    {
193      if (verbose)
194        printf("no disk quota for %s (uid 0)\n", user);
195      exit(0);
196    }
197
198  fslist = get_fslist(all ? 0 : uid);
199
200  /* Now print quotas */
201  for (i = 0; fslist[i].type; i++)
202    {
203      if (!strcasecmp(fslist[i].type, "afs"))
204        status = get_afs_quota(&fslist[i], uid, verbose);
205      else if (!strcasecmp(fslist[i].type, "nfs"))
206        {
207#ifdef ENABLE_NFS
208          status = get_nfs_quota(&fslist[i], uid, verbose);
209#else
210          status = 1;
211#endif
212        }
213      else
214        status = get_local_quota(&fslist[i], uid, verbose);
215
216      if (!status && fslist[i].have_quota && verbose)
217        {
218          if (!heading_printed)
219            {
220              heading(uid, user);
221              heading_printed = 1;
222            }
223          print_quota(&fslist[i]);
224        }
225    }
226  printf("\n");
227
228  for (i = 0; fslist[i].type; i++)
229    {
230      if (fslist[i].warn_blocks || fslist[i].warn_files)
231        {
232          if (!strcasecmp(fslist[i].type, "afs"))
233            print_afs_warning(&fslist[i]);
234          else
235            print_mounted_warning(&fslist[i]);
236        }
237    }
238
239  exit(0);
240}
241
242static void heading(uid_t uid, char *name)
243{
244  printf("Disk quotas for %s (uid %lu):\n", name, (unsigned long) uid);
245  printf("%-16s %8s %8s %8s    %8s %8s %8s\n",
246         "Filesystem",
247         "usage", "quota", "limit",
248         "files", "quota", "limit");
249}
250
251static void print_quota(struct quota_fs *fs)
252{
253  /* Ignore all-zero quotas */
254  if (!fs->dqb.dqb_bsoftlimit && !fs->dqb.dqb_bhardlimit
255      && !fs->dqb.dqb_curblocks && !fs->dqb.dqb_fsoftlimit
256      && !fs->dqb.dqb_fhardlimit && !fs->dqb.dqb_curfiles)
257    return;
258
259  if (strlen(fs->mount) > 16)
260    printf("%s\n%-16s ", fs->mount, "");
261  else
262    printf("%-16s ", fs->mount);
263
264  if (fs->have_blocks)
265    {
266      printf("%8u %8u %8u %2s ",
267             fs->dqb.dqb_curblocks / 2,
268             fs->dqb.dqb_bsoftlimit / 2,
269             fs->dqb.dqb_bhardlimit / 2,
270             fs->warn_blocks ? "<<" : "");
271    }
272  else
273    printf("%30s", "");
274
275  if (fs->have_files)
276    {
277      printf("%8u %8u %8u %2s ",
278             fs->dqb.dqb_curfiles,
279             fs->dqb.dqb_fsoftlimit,
280             fs->dqb.dqb_fhardlimit,
281             fs->warn_files ? "<<" : "");
282    }
283
284  printf("\n");
285}
286
287static int alldigits(char *s)
288{
289  int c;
290
291  c = *s++;
292  do {
293    if (!isdigit(c))
294      return 0;
295  } while ((c = *s++));
296  return 1;
297}
298
299static void usage(void)
300{
301  fprintf(stderr, "Usage: quota [-v] [-f filesystem...] [-u] [user]\n");
302  exit(1);
303}
Note: See TracBrowser for help on using the repository browser.