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