2 * $Id: nfsquota.c,v 1.13 2009-10-13 22:55:37 didg Exp $
4 * parts of this are lifted from the bsd quota program and are
5 * therefore under the following copyright:
7 * Copyright (c) 1980, 1990, 1993
8 * The Regents of the University of California. All rights reserved.
10 * This code is derived from software contributed to Berkeley by
11 * Robert Elz at The University of Melbourne.
13 * Ported for AIX (jfs) by Joerg Schumacher (J.Schumacher@tu-bs.de) at the
14 * Technische Universitaet Braunschweig, FRG
19 #endif /* HAVE_CONFIG_H */
21 #if !defined(NO_QUOTA_SUPPORT) && !defined(HAVE_LIBQUOTA)
26 #else /* STDC_HEADERS */
30 #endif /* HAVE_STRCHR */
31 char *strchr (), *strrchr ();
33 #define memcpy(d,s,n) bcopy ((s), (d), (n))
34 #define memmove(d,s,n) bcopy ((s), (d), (n))
35 #endif /* ! HAVE_MEMCPY */
36 #endif /* STDC_HEADERS */
37 #include <sys/types.h>
38 #include <sys/socket.h>
39 #include <sys/param.h> /* for DEV_BSIZE */
40 #include <sys/time.h> /* <rpc/rpc.h> on ultrix doesn't include this */
43 #endif /* HAVE_NETDB_H */
44 #include <netinet/in.h>
49 #include <rpc/pmap_prot.h>
50 #include <rpcsvc/rquota.h>
53 #include <atalk/afp.h>
54 #include <atalk/logger.h>
58 /* lifted (with modifications) from the bsd quota program */
60 callaurpc(struct vol *vol,
61 u_long prognum, u_long versnum, u_long procnum,
62 xdrproc_t inproc, char *in,
63 xdrproc_t outproc, char *out)
65 enum clnt_stat clnt_stat;
66 struct timeval tottimeout;
68 if (!vol->v_nfsclient) {
70 struct sockaddr_in server_addr;
71 struct timeval timeout;
72 int socket = RPC_ANYSOCK;
74 if ((hp = gethostbyname(vol->v_gvs)) == NULL)
75 return ((int) RPC_UNKNOWNHOST);
78 memcpy(&server_addr.sin_addr, hp->h_addr, hp->h_length);
79 server_addr.sin_family = AF_INET;
80 server_addr.sin_port = 0;
82 if ((vol->v_nfsclient = (void *)
83 clntudp_create(&server_addr, prognum, versnum,
84 timeout, &socket)) == NULL)
85 return ((int) rpc_createerr.cf_stat);
87 ((CLIENT *) vol->v_nfsclient)->cl_auth = authunix_create_default();
90 tottimeout.tv_sec = 10;
91 tottimeout.tv_usec = 0;
92 clnt_stat = clnt_call((CLIENT *) vol->v_nfsclient, procnum,
93 inproc, in, outproc, out, tottimeout);
94 return ((int) clnt_stat);
98 /* sunos 4 machines structure things a little differently. */
100 #define GQR_STATUS gqr_status
101 #define GQR_RQUOTA gqr_rquota
102 #else /* USE_OLD_RQUOTA */
103 #define GQR_STATUS status
104 #define GQR_RQUOTA getquota_rslt_u.gqr_rquota
105 #endif /* USE_OLD_RQUOTA */
107 int getnfsquota(struct vol *vol, const int uid, const u_int32_t bsize,
111 struct getquota_args gq_args;
112 struct getquota_rslt gq_rslt;
116 /* figure out the host and path */
117 if ((hostpath = strchr(vol->v_gvs, ':')) == NULL) {
118 LOG(log_error, logtype_afpd, "can't find hostname for %s", vol->v_gvs);
122 if (*(hostpath + 1) != '/')
125 /* separate host from hostpath */
128 gq_args.gqa_pathp = hostpath + 1;
129 gq_args.gqa_uid = uid;
131 if(callaurpc(vol, RQUOTAPROG, RQUOTAVERS, RQUOTAPROC_GETQUOTA,
132 (xdrproc_t) xdr_getquota_args, (char *) &gq_args,
133 (xdrproc_t) xdr_getquota_rslt, (char *) &gq_rslt) != 0) {
134 LOG(log_info, logtype_afpd, "nfsquota: can't retrieve nfs quota information. \
135 make sure that rpc.rquotad is running on %s.", vol->v_gvs);
140 switch (gq_rslt.GQR_STATUS) {
145 LOG(log_error, logtype_afpd, "nfsquota: quota permission error, host: %s",
149 case Q_OK: /* we only copy the bits that we need. */
150 gettimeofday(&tv, NULL);
152 #if defined(__svr4__) || defined(TRU64)
153 /* why doesn't using bsize work? */
154 #define NFS_BSIZE gq_rslt.GQR_RQUOTA.rq_bsize / DEV_BSIZE
155 #else /* __svr4__ || TRU64 */
156 /* NOTE: linux' rquotad program doesn't currently report the
157 * correct rq_bsize. */
158 /* NOTE: This is integer division and can introduce rounding errors */
159 #define NFS_BSIZE gq_rslt.GQR_RQUOTA.rq_bsize / bsize
160 #endif /* __svr4__ || TRU64 */
162 dqp->dqb_bhardlimit =
163 gq_rslt.GQR_RQUOTA.rq_bhardlimit*NFS_BSIZE;
164 dqp->dqb_bsoftlimit =
165 gq_rslt.GQR_RQUOTA.rq_bsoftlimit*NFS_BSIZE;
167 gq_rslt.GQR_RQUOTA.rq_curblocks*NFS_BSIZE;
170 dqp->dqb_bwarn = gq_rslt.GQR_RQUOTA.rq_btimeleft;
172 dqp->dqb_btimelimit =
173 tv.tv_sec + gq_rslt.GQR_RQUOTA.rq_btimeleft;
181 LOG(log_info, logtype_afpd, "bad rpc result, host: %s", vol->v_gvs);
188 #endif /* ! NO_QUOTA_SUPPORT && !HAVE_LIBQUOTA */