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

Revision 24068, 5.1 KB checked in by broder, 15 years ago (diff)
cd
RevLine 
[12786]1/* Copyright 1999 by the Massachusetts Institute of Technology.
[5946]2 *
[12786]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.
[5946]14 */
15
[24068]16#ifdef ENABLE_NFS
17
[12786]18/* This contains the NFS quota-checking routines. */
19
[13698]20static const char rcsid[] = "$Id: nfs.c,v 1.4 1999-10-07 17:06:22 rbasch Exp $";
[12786]21
[5946]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>
[13168]30#ifdef HAVE_RPC_CLNT_SOC_H
[12786]31#include <rpc/clnt_soc.h>
[13168]32#endif
[5946]33#include <rpc/pmap_prot.h>
[13698]34#include <rpc/pmap_clnt.h>
[5946]35#include <rpcsvc/rquota.h>
36
[12786]37#include <netdb.h>
38#include <stdio.h>
39#include <stdlib.h>
40#include <string.h>
41#include <unistd.h>
[5946]42
[12786]43#include "quota.h"
[5946]44
[13168]45#ifndef GQR_RQUOTA_USES_GQR_RQUOTA
[12786]46#define gqr_rquota getquota_rslt_u.gqr_rquota
[13168]47#endif
48
49#ifndef GQR_RQUOTA_USES_GQR_STATUS
[12786]50#define gqr_status status
51#endif
[5946]52
[12786]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)
[5946]58{
[12786]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;
[5946]65
[12786]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;
[5946]71
[12786]72  host = strdup(fs->device);
73  path = strchr(host, ':');
74  if (!path)
75    return -1;
76  *path++ = '\0';
[5946]77
[12786]78  gq_args.gqa_pathp = path;
79  gq_args.gqa_uid = uid;
[5946]80
[12786]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;
[5946]88    }
89
[12786]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;
[5946]104
[12786]105      if (fs->dqb.dqb_btimelimit)
106        fs->warn_blocks = 1;
107      if (fs->dqb.dqb_ftimelimit)
108        fs->warn_files = 1;
[5946]109
[12786]110      status = 0;
[13698]111      break;
[5946]112
[12786]113    case Q_NOQUOTA:
114      fs->have_quota = 0;
115      status = -1;
[13698]116      break;
[5946]117
[12786]118    case Q_EPERM:
119      if (verbose)
[13698]120        fprintf(stderr, "quota: %s: Permission denied\n", host);
[12786]121      status = -1;
[13698]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
[5946]130    }
[12786]131
132  free(host);
133  return status;
[5946]134}
135
[12786]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)
[5946]139{
[12786]140  struct sockaddr_in server_addr;
141  struct hostent *hp;
142  struct timeval timeout;
143  CLIENT *client;
144  int socket, status;
[13698]145  u_short port;
146  u_long pmap_port;
147  struct pmap map;
[5946]148
[12786]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;
[5946]156
[13698]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;
[12786]172
173  /* now really create a udp client handle */
[13698]174  server_addr.sin_port = htons(port);
[12786]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;
[5946]189}
[24068]190
191#endif /* ENABLE_NFS */
Note: See TracBrowser for help on using the repository browser.