2 * by Manuel Bouyer (bouyer@ensta.fr)
4 * There is no copyright, you can use it as you want.
10 #include <sys/param.h>
11 #include <sys/mount.h>
14 #include <sys/socket.h>
16 #include <ufs/ufs/quota.h>
18 #include <rpcsvc/rquota.h>
19 #include <arpa/inet.h>
35 static void rquota_service(struct svc_req
*request
, SVCXPRT
*transp
);
36 static void sendquota(struct svc_req
*request
, SVCXPRT
*transp
);
37 static void initfs(void);
38 static int getfsquota(long id
, char *path
, struct dqblk
*dqblk
);
40 static struct quotafile
**qfa
; /* array of qfs */
41 static int nqf
, szqf
; /* number of qfs and size of array */
42 static int from_inetd
= 1;
49 (void)rpcb_unset(RQUOTAPROG
, RQUOTAVERS
, NULL
);
58 struct sockaddr_storage from
;
61 fromlen
= sizeof(from
);
62 if (getsockname(0, (struct sockaddr
*)&from
, &fromlen
) < 0)
67 (void)rpcb_unset(RQUOTAPROG
, RQUOTAVERS
, NULL
);
68 (void)signal(SIGINT
, cleanup
);
69 (void)signal(SIGTERM
, cleanup
);
70 (void)signal(SIGHUP
, cleanup
);
73 openlog("rpc.rquotad", LOG_CONS
|LOG_PID
, LOG_DAEMON
);
75 /* create and register the service */
77 transp
= svc_tli_create(0, NULL
, NULL
, 0, 0);
79 syslog(LOG_ERR
, "couldn't create udp service.");
82 ok
= svc_reg(transp
, RQUOTAPROG
, RQUOTAVERS
,
83 rquota_service
, NULL
);
85 ok
= svc_create(rquota_service
,
86 RQUOTAPROG
, RQUOTAVERS
, "udp");
90 "unable to register (RQUOTAPROG, RQUOTAVERS, %s)",
91 from_inetd
? "(inetd)" : "udp");
97 syslog(LOG_ERR
, "svc_run returned");
102 rquota_service(struct svc_req
*request
, SVCXPRT
*transp
)
105 switch (request
->rq_proc
) {
107 (void)svc_sendreply(transp
, (xdrproc_t
)xdr_void
, (char *)NULL
);
109 case RQUOTAPROC_GETQUOTA
:
110 case RQUOTAPROC_GETACTIVEQUOTA
:
111 sendquota(request
, transp
);
114 svcerr_noproc(transp
);
121 /* read quota for the specified id, and send it */
123 sendquota(struct svc_req
*request
, SVCXPRT
*transp
)
125 struct getquota_args getq_args
;
126 struct getquota_rslt getq_rslt
;
128 struct timeval timev
;
131 bzero(&getq_args
, sizeof(getq_args
));
132 if (!svc_getargs(transp
, (xdrproc_t
)xdr_getquota_args
, &getq_args
)) {
133 svcerr_decode(transp
);
136 if (request
->rq_cred
.oa_flavor
!= AUTH_UNIX
) {
138 getq_rslt
.status
= Q_EPERM
;
139 } else if (!getfsquota(getq_args
.gqa_uid
, getq_args
.gqa_pathp
, &dqblk
)) {
140 /* failed, return noquota */
141 getq_rslt
.status
= Q_NOQUOTA
;
143 gettimeofday(&timev
, NULL
);
144 getq_rslt
.status
= Q_OK
;
145 getq_rslt
.getquota_rslt_u
.gqr_rquota
.rq_active
= TRUE
;
146 scale
= 1 << flsll(dqblk
.dqb_bhardlimit
>> 32);
147 getq_rslt
.getquota_rslt_u
.gqr_rquota
.rq_bsize
=
149 getq_rslt
.getquota_rslt_u
.gqr_rquota
.rq_bhardlimit
=
150 dqblk
.dqb_bhardlimit
/ scale
;
151 getq_rslt
.getquota_rslt_u
.gqr_rquota
.rq_bsoftlimit
=
152 dqblk
.dqb_bsoftlimit
/ scale
;
153 getq_rslt
.getquota_rslt_u
.gqr_rquota
.rq_curblocks
=
154 dqblk
.dqb_curblocks
/ scale
;
155 getq_rslt
.getquota_rslt_u
.gqr_rquota
.rq_fhardlimit
=
156 dqblk
.dqb_ihardlimit
;
157 getq_rslt
.getquota_rslt_u
.gqr_rquota
.rq_fsoftlimit
=
158 dqblk
.dqb_isoftlimit
;
159 getq_rslt
.getquota_rslt_u
.gqr_rquota
.rq_curfiles
=
161 getq_rslt
.getquota_rslt_u
.gqr_rquota
.rq_btimeleft
=
162 dqblk
.dqb_btime
- timev
.tv_sec
;
163 getq_rslt
.getquota_rslt_u
.gqr_rquota
.rq_ftimeleft
=
164 dqblk
.dqb_itime
- timev
.tv_sec
;
166 if (!svc_sendreply(transp
, (xdrproc_t
)xdr_getquota_rslt
, &getq_rslt
))
167 svcerr_systemerr(transp
);
168 if (!svc_freeargs(transp
, (xdrproc_t
)xdr_getquota_args
, &getq_args
)) {
169 syslog(LOG_ERR
, "unable to free arguments");
181 if ((qfa
= malloc(szqf
* sizeof *qfa
)) == NULL
)
183 while ((fs
= getfsent())) {
184 if (strcmp(fs
->fs_vfstype
, "ufs"))
188 if ((qfa
= reallocf(qfa
, szqf
* sizeof *qfa
)) == NULL
)
191 if ((qfa
[nqf
] = quota_open(fs
, USRQUOTA
, O_RDONLY
)) == NULL
) {
192 if (errno
!= EOPNOTSUPP
)
202 syslog(LOG_ERR
, "out of memory");
205 syslog(LOG_ERR
, "%s: %s", fs
->fs_file
, strerror(errno
));
210 * gets the quotas for id, filesystem path.
211 * Return 0 if fail, 1 otherwise
214 getfsquota(long id
, char *path
, struct dqblk
*dqblk
)
218 for (i
= 0; i
< nqf
; ++i
)
219 if (quota_check_path(qfa
[i
], path
) == 1)
220 return (quota_read(qfa
[i
], dqblk
, id
) == 0);