source: trunk/athena/bin/quota/ufs.c @ 13168

Revision 13168, 5.0 KB checked in by danw, 25 years ago (diff)
Add some more autoconfiscation to deal with the struct dqblk and rquota struct elements having different names on different OSes
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/* Routines for retrieving local filesystem quotas. */
17
18static const char rcsid[] = "$Id: ufs.c,v 1.2 1999-06-03 14:54:24 danw Exp $";
19
20#include <errno.h>
21#include <fcntl.h>
22#include <stdio.h>
23#include <stdlib.h>
24#include <string.h>
25#include <time.h>
26#include <unistd.h>
27
28#include "quota.h"
29
30static void print_timeout(time_t time);
31static int os_quotactl(struct quota_fs *fs, uid_t uid);
32
33int get_local_quota(struct quota_fs *fs, uid_t uid, int verbose)
34{
35  int status;
36#ifdef IRIX
37  struct fs_disk_quota fdq;
38
39  /* Irix uses a different quota structure for XFS only. */
40  if (!strcmp(fs->type, "xfs"))
41    {
42      status = quotactl(Q_XGETQUOTA, fs->device, uid, (caddr_t)&fdq);
43      if (status == 0)
44        {
45          fs->dqb.dqb_curblocks = fdq.d_bcount;
46          fs->dqb.dqb_bsoftlimit = fdq.d_blk_softlimit;
47          fs->dqb.dqb_bhardlimit = fdq.d_blk_hardlimit;
48          fs->dqb.dqb_btimelimit = fdq.d_btimer;
49          fs->dqb.dqb_curfiles = fdq.d_icount;
50          fs->dqb.dqb_fsoftlimit = fdq.d_ino_softlimit;
51          fs->dqb.dqb_fhardlimit= fdq.d_ino_hardlimit;
52          fs->dqb.dqb_ftimelimit = fdq.d_itimer;
53          fs->have_quota = fs->have_files = fs->have_blocks = 1;
54        }
55    }
56  else
57#endif /* IRIX */
58    {
59      status = os_quotactl(fs, uid);
60      if (status == 0)
61        fs->have_quota = fs->have_files = fs->have_blocks = 1;
62    }
63
64  if (fs->have_quota)
65    {
66      if (fs->dqb.dqb_btimelimit)
67        fs->warn_blocks = 1;
68      if (fs->dqb.dqb_ftimelimit)
69        fs->warn_files = 1;
70    }
71
72  /* Give an error message for anything but ESRCH ("Quotas not enabled
73   * for this filesystem.") or EOPNOTSUPP ("No kernel support for
74   * quotas.")
75   */
76  if (status == -1 && errno != ESRCH && errno != EOPNOTSUPP)
77    {
78      fprintf(stderr, "quota: Could not get quota for %s (%s): %s\n",
79              fs->mount, fs->device, strerror(errno));
80      return -1;
81    }
82
83  return 0;
84}
85
86#ifndef SOLARIS
87
88int os_quotactl(struct quota_fs *fs, uid_t uid)
89{
90#ifdef BSD_QUOTACTL
91  return quotactl(fs->mount, QCMD(Q_GETQUOTA, USRQUOTA), uid,
92                  (caddr_t)&fs->dqb);
93#else
94  return quotactl(Q_GETQUOTA, fs->device, uid, (caddr_t)&fs->dqb);
95#endif
96}
97
98#else
99
100int os_quotactl(struct quota_fs *fs, uid_t uid)
101{
102  int fd, status;
103  char *path;
104  struct quotctl qctl;
105
106  path = malloc(strlen(fs->mount) + 8);
107  if (!path)
108    return -1;
109  sprintf(path, "%s/quotas", fs->mount);
110
111  fd = open(path, O_RDONLY);
112  free(path);
113  if (fd == -1)
114    {
115      if (errno == ENOENT)
116        errno = ESRCH;
117      return -1;
118    }
119
120  qctl.op = Q_GETQUOTA;
121  qctl.uid = uid;
122  qctl.addr = (caddr_t)&fs->dqb;
123  status = ioctl(fd, Q_QUOTACTL, &qctl);
124  close(fd);
125  return status;
126}
127#endif
128
129/* This is used for both UFS and NFS. */
130void print_mounted_warning(struct quota_fs *fs)
131{
132  time_t now = time(NULL);
133
134  if (fs->dqb.dqb_bhardlimit &&
135      (fs->dqb.dqb_curblocks >= fs->dqb.dqb_bhardlimit))
136    printf("Block limit reached on %s\n", fs->mount);
137  else if (fs->dqb.dqb_bsoftlimit &&
138           (fs->dqb.dqb_curblocks >= fs->dqb.dqb_bsoftlimit))
139    {
140      printf("Over disk quota on %s, remove %dK", fs->mount,
141             (fs->dqb.dqb_curblocks - fs->dqb.dqb_bsoftlimit + 1) / 2);
142
143      if (fs->dqb.dqb_btimelimit > now)
144        print_timeout(fs->dqb.dqb_btimelimit - now);
145      else if (fs->dqb.dqb_btimelimit != 0)
146        printf(" immediately");
147      printf("\n");
148    }
149
150  if (fs->dqb.dqb_fhardlimit &&
151      (fs->dqb.dqb_curfiles >= fs->dqb.dqb_fhardlimit))
152    printf("File count limit reached on %s\n", fs->mount);
153  else if (fs->dqb.dqb_fsoftlimit &&
154           (fs->dqb.dqb_curfiles >= fs->dqb.dqb_fsoftlimit))
155    {
156      int remfiles = fs->dqb.dqb_curfiles - fs->dqb.dqb_fsoftlimit + 1;
157
158      printf("Over file quota on %s, remove %d file%s",
159              fs->mount, remfiles, remfiles > 1 ? "s" : "");
160
161      if (fs->dqb.dqb_ftimelimit > now)
162        print_timeout(fs->dqb.dqb_ftimelimit - now);
163      else if (fs->dqb.dqb_ftimelimit != 0)
164        printf(" immediately");
165      printf("\n");
166    }
167}
168
169static void print_timeout(time_t time)
170{
171  int i;
172  static struct {
173    int c_secs;                         /* conversion units in secs */
174    char *c_str;                        /* unit string */
175  } cunits [] = {
176    {60 * 60 * 24 * 7 * 4, "months"},
177    {60 * 60 * 24 * 7, "weeks"},
178    {60 * 60 * 24, "days"},
179    {60 * 60, "hours"},
180    {60, "mins"},
181    {1, "secs"}
182  };
183
184  for (i = 0; i < sizeof(cunits) / sizeof(cunits[0]); i++)
185    {
186      if (time >= cunits[i].c_secs)
187        break;
188    }
189  printf(" within %.1f %s", (double)time / cunits[i].c_secs, cunits[i].c_str);
190}
Note: See TracBrowser for help on using the repository browser.