]> arthur.barton.de Git - netatalk.git/blob - etc/afpd/nfsquota.c
- merge branch-netatalk-afp-3x-dev, HEAD was tagged before
[netatalk.git] / etc / afpd / nfsquota.c
1 /*
2  * $Id: nfsquota.c,v 1.12 2005-04-28 20:49:44 bfernhomberg Exp $
3  *
4  * parts of this are lifted from the bsd quota program and are
5  * therefore under the following copyright:
6  *
7  * Copyright (c) 1980, 1990, 1993
8  *      The Regents of the University of California.  All rights reserved.
9  *
10  * This code is derived from software contributed to Berkeley by
11  * Robert Elz at The University of Melbourne.
12  *
13  * Ported for AIX (jfs) by Joerg Schumacher (J.Schumacher@tu-bs.de) at the
14  * Technische Universitaet Braunschweig, FRG
15  */
16
17 #ifdef HAVE_CONFIG_H
18 #include "config.h"
19 #endif /* HAVE_CONFIG_H */
20
21 #ifndef NO_QUOTA_SUPPORT
22 #include <stdio.h>
23 /* STDC check */
24 #if STDC_HEADERS
25 #include <string.h>
26 #else /* STDC_HEADERS */
27 #ifndef HAVE_STRCHR
28 #define strchr index
29 #define strrchr index
30 #endif /* HAVE_STRCHR */
31 char *strchr (), *strrchr ();
32 #ifndef HAVE_MEMCPY
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 */
41 #ifdef HAVE_NETDB_H
42 #include <netdb.h>
43 #endif /* HAVE_NETDB_H */
44 #include <netinet/in.h>
45 #ifndef PORTMAP
46 #define PORTMAP 1
47 #endif
48 #include <rpc/rpc.h>
49 #include <rpc/pmap_prot.h>
50 #include <rpcsvc/rquota.h>
51
52
53 #include <atalk/afp.h>
54 #include <atalk/logger.h>
55
56 #include "unix.h"
57
58 /* lifted (with modifications) from the bsd quota program */
59 static int
60 callaurpc(vol, prognum, versnum, procnum, inproc, in, outproc, out)
61 struct vol *vol;
62 u_long prognum, versnum, procnum;
63 xdrproc_t inproc, outproc;
64 char *in, *out;
65 {
66     enum clnt_stat clnt_stat;
67     struct timeval tottimeout;
68
69     if (!vol->v_nfsclient) {
70         struct hostent *hp;
71         struct sockaddr_in server_addr;
72         struct timeval timeout;
73         int socket = RPC_ANYSOCK;
74
75         if ((hp = gethostbyname(vol->v_gvs)) == NULL)
76             return ((int) RPC_UNKNOWNHOST);
77         timeout.tv_usec = 0;
78         timeout.tv_sec = 6;
79         memcpy(&server_addr.sin_addr, hp->h_addr, hp->h_length);
80         server_addr.sin_family = AF_INET;
81         server_addr.sin_port =  0;
82
83         if ((vol->v_nfsclient = (void *)
84                                 clntudp_create(&server_addr, prognum, versnum,
85                                                timeout, &socket)) == NULL)
86             return ((int) rpc_createerr.cf_stat);
87
88         ((CLIENT *) vol->v_nfsclient)->cl_auth = authunix_create_default();
89     }
90
91     tottimeout.tv_sec = 10;
92     tottimeout.tv_usec = 0;
93     clnt_stat = clnt_call((CLIENT *) vol->v_nfsclient, procnum,
94                           inproc, in, outproc, out, tottimeout);
95     return ((int) clnt_stat);
96 }
97
98
99 /* sunos 4 machines structure things a little differently. */
100 #ifdef USE_OLD_RQUOTA
101 #define GQR_STATUS gqr_status
102 #define GQR_RQUOTA gqr_rquota
103 #else /* USE_OLD_RQUOTA */
104 #define GQR_STATUS status
105 #define GQR_RQUOTA getquota_rslt_u.gqr_rquota
106 #endif /* USE_OLD_RQUOTA */
107
108 int getnfsquota(struct vol *vol, const int uid, const u_int32_t bsize,
109                 struct dqblk *dqp)
110 {
111
112     struct getquota_args gq_args;
113     struct getquota_rslt gq_rslt;
114     struct timeval tv;
115     char *hostpath;
116
117     /* figure out the host and path */
118     if ((hostpath = strchr(vol->v_gvs, ':')) == NULL) {
119         LOG(log_error, logtype_afpd, "can't find hostname for %s", vol->v_gvs);
120         return AFPERR_PARAM;
121     }
122
123     if (*(hostpath + 1) != '/')
124         return AFPERR_PARAM;
125
126     /* separate host from hostpath */
127     *hostpath = '\0';
128
129     gq_args.gqa_pathp = hostpath + 1;
130     gq_args.gqa_uid = uid;
131
132     if(callaurpc(vol, RQUOTAPROG, RQUOTAVERS, RQUOTAPROC_GETQUOTA,
133                  (xdrproc_t) xdr_getquota_args, (char *) &gq_args,
134                  (xdrproc_t) xdr_getquota_rslt, (char *) &gq_rslt) != 0) {
135         LOG(log_info, logtype_afpd, "nfsquota: can't retrieve nfs quota information. \
136             make sure that rpc.rquotad is running on %s.", vol->v_gvs);
137         *hostpath = ':';
138         return AFPERR_PARAM;
139     }
140
141     switch (gq_rslt.GQR_STATUS) {
142     case Q_NOQUOTA:
143         break;
144
145     case Q_EPERM:
146         LOG(log_error, logtype_afpd, "nfsquota: quota permission error, host: %s",
147             vol->v_gvs);
148         break;
149
150     case Q_OK: /* we only copy the bits that we need. */
151         gettimeofday(&tv, NULL);
152
153 #if defined(__svr4__) || defined(TRU64)
154         /* why doesn't using bsize work? */
155 #define NFS_BSIZE gq_rslt.GQR_RQUOTA.rq_bsize / DEV_BSIZE
156 #else /* __svr4__ || TRU64 */
157         /* NOTE: linux' rquotad program doesn't currently report the
158         * correct rq_bsize. */
159         /* NOTE: This is integer division and can introduce rounding errors */
160 #define NFS_BSIZE gq_rslt.GQR_RQUOTA.rq_bsize / bsize
161 #endif /* __svr4__  || TRU64 */
162
163         dqp->dqb_bhardlimit =
164             gq_rslt.GQR_RQUOTA.rq_bhardlimit*NFS_BSIZE;
165         dqp->dqb_bsoftlimit =
166             gq_rslt.GQR_RQUOTA.rq_bsoftlimit*NFS_BSIZE;
167         dqp->dqb_curblocks =
168             gq_rslt.GQR_RQUOTA.rq_curblocks*NFS_BSIZE;
169
170 #ifdef ultrix
171         dqp->dqb_bwarn = gq_rslt.GQR_RQUOTA.rq_btimeleft;
172 #else /* ultrix */
173         dqp->dqb_btimelimit =
174             tv.tv_sec + gq_rslt.GQR_RQUOTA.rq_btimeleft;
175 #endif /* ultrix */
176
177         *hostpath = ':';
178         return AFP_OK;
179         break;
180
181     default:
182         LOG(log_info, logtype_afpd, "bad rpc result, host: %s", vol->v_gvs);
183         break;
184     }
185
186     *hostpath = ':';
187     return AFPERR_PARAM;
188 }
189 #endif /* ! NO_QUOTA_SUPPORT */