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

Revision 24068, 5.1 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#ifdef ENABLE_NFS
17
18/* This contains the NFS quota-checking routines. */
19
20static const char rcsid[] = "$Id: nfs.c,v 1.4 1999-10-07 17:06:22 rbasch Exp $";
21
22#include <sys/types.h>
23#include <sys/param.h>
24#include <sys/socket.h>
25#include <sys/time.h>
26
27#include <netinet/in.h>
28
29#include <rpc/rpc.h>
30#ifdef HAVE_RPC_CLNT_SOC_H
31#include <rpc/clnt_soc.h>
32#endif
33#include <rpc/pmap_prot.h>
34#include <rpc/pmap_clnt.h>
35#include <rpcsvc/rquota.h>
36
37#include <netdb.h>
38#include <stdio.h>
39#include <stdlib.h>
40#include <string.h>
41#include <unistd.h>
42
43#include "quota.h"
44
45#ifndef GQR_RQUOTA_USES_GQR_RQUOTA
46#define gqr_rquota getquota_rslt_u.gqr_rquota
47#endif
48
49#ifndef GQR_RQUOTA_USES_GQR_STATUS
50#define gqr_status status
51#endif
52
53static int callaurpc(char *host, int prognum, int versnum, int procnum,
54                     xdrproc_t inproc, struct getquota_args *in,
55                     xdrproc_t outproc, struct getquota_rslt *out);
56
57int get_nfs_quota(struct quota_fs *fs, uid_t uid, int verbose)
58{
59  struct getquota_args gq_args;
60  struct getquota_rslt gq_result;
61  struct rquota quota;
62  int status;
63  char *host, *path;
64  double bscale;
65
66  /* If user is root, punt. (I don't know why. This is just what the
67   * old code did. Probably assuming root will be mapped to "nobody"?)
68   */
69  if (getuid() == 0)
70    return -1;
71
72  host = strdup(fs->device);
73  path = strchr(host, ':');
74  if (!path)
75    return -1;
76  *path++ = '\0';
77
78  gq_args.gqa_pathp = path;
79  gq_args.gqa_uid = uid;
80
81  if (callaurpc(host, RQUOTAPROG, RQUOTAVERS,
82                (verbose ? RQUOTAPROC_GETQUOTA : RQUOTAPROC_GETACTIVEQUOTA),
83                xdr_getquota_args, &gq_args,
84                xdr_getquota_rslt, &gq_result) != 0)
85    {
86      free(host);
87      return -1;
88    }
89
90  quota = gq_result.gqr_rquota;
91  switch (gq_result.gqr_status)
92    {
93    case Q_OK:
94      bscale = quota.rq_bsize / 512.0;
95      fs->have_quota = fs->have_blocks = fs->have_files = 1;
96      fs->dqb.dqb_curblocks = quota.rq_curblocks * bscale;
97      fs->dqb.dqb_bsoftlimit = quota.rq_bsoftlimit * bscale;
98      fs->dqb.dqb_bhardlimit = quota.rq_bhardlimit * bscale;
99      fs->dqb.dqb_btimelimit = quota.rq_btimeleft;
100      fs->dqb.dqb_curfiles = quota.rq_curfiles;
101      fs->dqb.dqb_fsoftlimit = quota.rq_fsoftlimit;
102      fs->dqb.dqb_fhardlimit = quota.rq_fhardlimit;
103      fs->dqb.dqb_ftimelimit = quota.rq_ftimeleft;
104
105      if (fs->dqb.dqb_btimelimit)
106        fs->warn_blocks = 1;
107      if (fs->dqb.dqb_ftimelimit)
108        fs->warn_files = 1;
109
110      status = 0;
111      break;
112
113    case Q_NOQUOTA:
114      fs->have_quota = 0;
115      status = -1;
116      break;
117
118    case Q_EPERM:
119      if (verbose)
120        fprintf(stderr, "quota: %s: Permission denied\n", host);
121      status = -1;
122      break;
123
124    default:
125      if (verbose)
126        fprintf(stderr, "quota: %s: Unrecognized status %d\n", host, status);
127      status = -1;
128      break;
129
130    }
131
132  free(host);
133  return status;
134}
135
136static int callaurpc(char *host, int prognum, int versnum, int procnum,
137                     xdrproc_t inproc, struct getquota_args *in,
138                     xdrproc_t outproc, struct getquota_rslt *out)
139{
140  struct sockaddr_in server_addr;
141  struct hostent *hp;
142  struct timeval timeout;
143  CLIENT *client;
144  int socket, status;
145  u_short port;
146  u_long pmap_port;
147  struct pmap map;
148
149  socket = RPC_ANYSOCK;
150  if ((hp = gethostbyname(host)) == NULL)
151    return RPC_UNKNOWNHOST;
152  timeout.tv_usec = 0;
153  timeout.tv_sec = 6;
154  memcpy(&server_addr.sin_addr, hp->h_addr, hp->h_length);
155  server_addr.sin_family = AF_INET;
156
157  /* Ask the remote portmapper for the program's UDP port number.
158   * This also provides a handy ping of the remote host, as we can
159   * thus specify a non-default (shorter) timeout for the portmapper
160   * exchange.
161   */
162  map.pm_prog = prognum;
163  map.pm_vers = versnum;
164  map.pm_prot = IPPROTO_UDP;
165  map.pm_port = 0;
166  status = pmap_rmtcall(&server_addr, PMAPPROG, PMAPVERS, PMAPPROC_GETPORT,
167                        xdr_pmap, (caddr_t) &map,
168                        xdr_u_short, (caddr_t) &port,
169                        timeout, &pmap_port);
170  if (status != RPC_SUCCESS)
171    return status;
172
173  /* now really create a udp client handle */
174  server_addr.sin_port = htons(port);
175  if ((client = clntudp_create(&server_addr, prognum,
176                               versnum, timeout, &socket)) == NULL)
177    return rpc_createerr.cf_stat;
178  auth_destroy(client->cl_auth);
179  client->cl_auth = authunix_create_default();
180
181  timeout.tv_usec = 0;
182  timeout.tv_sec = 25;
183  status = clnt_call(client, procnum, inproc, (caddr_t) in, outproc,
184                     (caddr_t) out, timeout);
185
186  auth_destroy(client->cl_auth);
187  clnt_destroy(client);
188  return status;
189}
190
191#endif /* ENABLE_NFS */
Note: See TracBrowser for help on using the repository browser.