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

Revision 13340, 5.0 KB checked in by danw, 25 years ago (diff)
NetBSD returns EINVAL for "no quotas on this filesystem"
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.3 1999-07-07 22:39:17 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/EINVAL ("Quotas not
73   * enabled for this filesystem.") or EOPNOTSUPP ("No kernel support
74   * for quotas.")
75   */
76  if (status == -1 && errno != ESRCH && errno != EINVAL && 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.