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

Revision 5946, 5.9 KB checked in by probe, 32 years ago (diff)
Initial revision
Line 
1/*
2 * NFS quota routines
3 *
4 *   Uses the rcquota rpc call for group and user quotas
5 *
6 * $Id: nfs.c,v 1.1 1992-04-10 20:22:58 probe Exp $
7 */
8
9#include <stdio.h>
10#include <sys/types.h>
11#include <sys/param.h>
12#include <sys/socket.h>
13#include <sys/time.h>
14
15#include <netdb.h>
16#include <netinet/in.h>
17
18#include <rpc/rpc.h>
19#include <rpc/pmap_prot.h>
20#include <rpcsvc/rquota.h>
21#include <rpcsvc/rcquota.h>
22
23
24extern int uflag, gflag, vflag, fsind;
25
26
27int
28getnfsquota(hostp, path, uid, qvp)
29    char *hostp;
30    char *path;
31    int uid;
32    struct getcquota_rslt *qvp;
33{
34    struct getcquota_args gq_args;
35    extern char *index();
36    int oldrpc = 0;
37
38    gq_args.gqa_pathp = path;
39    gq_args.gqa_uid = (gflag ? getuid() : uid);
40    if ((enum clnt_stat)
41        callrpc(hostp, RCQUOTAPROG, RCQUOTAVERS,
42                (vflag? RCQUOTAPROC_GETQUOTA: RCQUOTAPROC_GETACTIVEQUOTA),
43                xdr_getcquota_args, &gq_args, xdr_getcquota_rslt, qvp) ==
44        RPC_PROGNOTREGISTERED){
45
46        /* Fallback on old rpc, unless gflag is true, or caller is root */
47        struct getquota_rslt oldquota_result;
48
49        if (gflag || !getuid()) return(0);
50        oldrpc = 1;
51        if (callaurpc(hostp, RQUOTAPROG, RQUOTAVERS,
52                      (vflag? RQUOTAPROC_GETQUOTA:
53                       RQUOTAPROC_GETACTIVEQUOTA),
54                      xdr_getquota_args, &gq_args,
55                      xdr_getquota_rslt, &oldquota_result) != 0){
56            /* Okay, it really failed */
57            return (0);
58        } else {
59            /* The getquota_rslt structure needs to be converted to
60             * a getcquota_rslt structure. */
61
62            switch (oldquota_result.gqr_status){
63            case Q_OK: qvp->gqr_status = QC_OK; break;
64            case Q_NOQUOTA: qvp->gqr_status = QC_NOQUOTA; break;
65            case Q_EPERM: qvp->gqr_status = QC_EPERM; break;
66            }
67
68            qvp->rq_group = 0;          /* only user quota on old rpc's */
69            qvp->rq_ngrps = 1;
70            qvp->rq_bsize = oldquota_result.gqr_rquota.rq_bsize;
71            bzero(&qvp->gqr_zm, sizeof(struct rcquota));
72
73            qvp->gqr_rcquota[0].rq_id = gq_args.gqa_uid;
74            qvp->gqr_rcquota[0].rq_bhardlimit =
75                oldquota_result.gqr_rquota.rq_bhardlimit;
76            qvp->gqr_rcquota[0].rq_bsoftlimit =
77                oldquota_result.gqr_rquota.rq_bsoftlimit;
78            qvp->gqr_rcquota[0].rq_curblocks =
79                oldquota_result.gqr_rquota.rq_curblocks;
80            qvp->gqr_rcquota[0].rq_fhardlimit =
81                oldquota_result.gqr_rquota.rq_fhardlimit;
82            qvp->gqr_rcquota[0].rq_fsoftlimit =
83                oldquota_result.gqr_rquota.rq_fsoftlimit;
84            qvp->gqr_rcquota[0].rq_curfiles =
85                oldquota_result.gqr_rquota.rq_curfiles;
86            qvp->gqr_rcquota[0].rq_btimeleft =
87                oldquota_result.gqr_rquota.rq_btimeleft;
88            qvp->gqr_rcquota[0].rq_ftimeleft =
89                oldquota_result.gqr_rquota.rq_ftimeleft;
90        }
91    }
92
93    switch (qvp->gqr_status) {
94    case QC_OK:
95        {
96            struct timeval tv;
97            int i;
98            float blockconv;
99
100            if (gflag){
101                if (!qvp->rq_group) return(0);  /* Not group controlled */
102                for(i=0;i<qvp->rq_ngrps;i++)
103                    if (uid == qvp->gqr_rcquota[i].rq_id) break;
104                if (i == qvp->rq_ngrps) return(0); /* group id not in list */
105                bcopy(&(qvp->gqr_rcquota[i]), &(qvp->gqr_rcquota[0]),
106                      sizeof(struct rcquota));
107                qvp->rq_ngrps = 1;
108            }
109
110            if (uflag && qvp->rq_group) return(0); /* Not user-controlled */
111
112            gettimeofday(&tv, NULL);
113
114            blockconv = (float)qvp->rq_bsize / 512;
115            qvp->gqr_zm.rq_bhardlimit *= blockconv;
116            qvp->gqr_zm.rq_bsoftlimit *= blockconv;
117            qvp->gqr_zm.rq_curblocks  *= blockconv;
118            if (!qvp->rq_group) qvp->rq_ngrps = 1;
119            for(i=0;i<qvp->rq_ngrps;i++){
120                qvp->gqr_rcquota[i].rq_bhardlimit *= blockconv;
121                qvp->gqr_rcquota[i].rq_bsoftlimit *= blockconv;
122                qvp->gqr_rcquota[i].rq_curblocks  *= blockconv;
123                qvp->gqr_rcquota[i].rq_btimeleft += tv.tv_sec;
124                qvp->gqr_rcquota[i].rq_ftimeleft += tv.tv_sec;
125            }
126            return (1);
127        }
128
129    case QC_NOQUOTA:
130        break;
131
132    case QC_EPERM:
133        if (vflag && fsind && !oldrpc)
134            fprintf(stderr, "quota: Warning--no NFS mapping on host: %s\n", hostp);
135        if (vflag && fsind && oldrpc)
136            fprintf(stderr, "quota: Permission denied. %s\n", hostp);
137        break;
138
139    default:
140        fprintf(stderr, "bad rpc result, host: %s\n",  hostp);
141        break;
142    }
143    return (0);
144}
145
146callaurpc(host, prognum, versnum, procnum, inproc, in, outproc, out)
147    char *host;
148    xdrproc_t inproc, outproc;
149    struct getcquota_args *in;
150    struct getquota_rslt *out;
151{
152    struct sockaddr_in server_addr;
153    enum clnt_stat clnt_stat;
154    struct hostent *hp;
155    struct timeval timeout, tottimeout;
156
157    static CLIENT *client = NULL;
158    static int socket = RPC_ANYSOCK;
159    static int valid = 0;
160    static int oldprognum, oldversnum;
161    static char oldhost[256];
162
163    if (valid && oldprognum == prognum && oldversnum == versnum
164        && strcmp(oldhost, host) == 0) {
165        /* reuse old client */         
166    }
167    else {
168        valid = 0;
169        close(socket);
170        socket = RPC_ANYSOCK;
171        if (client) {
172            clnt_destroy(client);
173            client = NULL;
174        }
175        if ((hp = gethostbyname(host)) == NULL)
176            return ((int) RPC_UNKNOWNHOST);
177        timeout.tv_usec = 0;
178        timeout.tv_sec = 6;
179        bcopy(hp->h_addr, &server_addr.sin_addr, hp->h_length);
180        server_addr.sin_family = AF_INET;
181        /* ping the remote end via tcp to see if it is up */
182        server_addr.sin_port =  htons(PMAPPORT);
183        if ((client = clnttcp_create(&server_addr, PMAPPROG,
184                                     PMAPVERS, &socket, 0, 0)) == NULL) {
185            return ((int) rpc_createerr.cf_stat);
186        } else {
187            /* the fact we succeeded means the machine is up */
188            close(socket);
189            socket = RPC_ANYSOCK;
190            clnt_destroy(client);
191            client = NULL;
192        }
193        /* now really create a udp client handle */
194        server_addr.sin_port =  0;
195        if ((client = clntudp_create(&server_addr, prognum,
196                                     versnum, timeout, &socket)) == NULL)
197            return ((int) rpc_createerr.cf_stat);
198        client->cl_auth = authunix_create_default();
199        valid = 1;
200        oldprognum = prognum;
201        oldversnum = versnum;
202        strcpy(oldhost, host);
203    }
204    tottimeout.tv_sec = 25;
205    tottimeout.tv_usec = 0;
206    clnt_stat = clnt_call(client, procnum, inproc, in,
207                          outproc, out, tottimeout);
208    /*
209     * if call failed, empty cache
210     */
211    if (clnt_stat != RPC_SUCCESS)
212        valid = 0;
213    return ((int) clnt_stat);
214}
Note: See TracBrowser for help on using the repository browser.