Return to BSD News archive
Path: sserve!newshost.anu.edu.au!harbinger.cc.monash.edu.au!bunyip.cc.uq.oz.au!munnari.oz.au!spool.mu.edu!howland.reston.ans.net!math.ohio-state.edu!jussieu.fr!univ-lyon1.fr!ensta!bsdtest.ensta.fr!bouyer
From: bouyer@bsdtest.ensta.fr (Manuel Bouyer)
Newsgroups: comp.os.386bsd.questions
Subject: Re: [FreeBSD] rquotad wanted !
Date: 21 Jun 1994 13:44:40 GMT
Organization: Ecole Nationale Superieure de Techniques Avancees, Paris
Lines: 355
Distribution: world
Message-ID: <2u6qs8$1aq@ici-paris.ensta.fr>
References: <2u6lrf$kku@news.simplex.nl>
NNTP-Posting-Host: bsdtest.ensta.fr
In article <2u6lrf$kku@news.simplex.nl>, rob@Simplex.NL (Rob Simons) writes:
|> Hi,
|>
|> Is there anyone out there who knows where I can find the rquotad
|> perhaps rpc.rquotad daemon ?
|> This daemon handles requests for quota-information from clients
|> machines to the NFS machine ..
|>
Here is the one i wrote for NetBSD some time ago ...
/* rquotad.c, rquotad service */
/* for NetBSD 0.9 by Manuel Bouyer (bouyer@ensta.fr) */
#include <stdio.h>
#include <fstab.h>
#include <ctype.h>
#include <pwd.h>
#include <grp.h>
#include <errno.h>
#include <syslog.h>
#include <varargs.h>
#include <sys/types.h>
#include <sys/mount.h>
#include <sys/param.h>
#include <sys/file.h>
#include <sys/stat.h>
#include <sys/signal.h>
#include <machine/param.h>
#include <ufs/quota.h>
#include <rpc/rpc.h>
#include <rpcsvc/rquota.h>
void rquota_svc (), exit_svc(), sendquota(), printerr_reply(), initfs();
int getfsquota();
extern int errno;
/* structure containing informations about ufs filesystems */
/*initialised by initfs() */
struct fs_stat {
struct fs_stat *fs_next; /* next element (NULL if end of the list) */
char *fs_file; /* mount point of the filesystem*/
char *qfpathname; /* pathname of the quota file */
dev_t st_dev; /* device of the filesystem */
} fs_stat;
struct fs_stat *fs_begin=NULL; /* first element of the list */
main () /* no options */
{
SVCXPRT *transport;
int sock = 0;
int proto = 0;
int from_inetd = 1;
struct sockaddr_in from;
int fromlen;
/* from rwalld.c NetBSD 0.9 */
openlog ("rquotad",LOG_PID,LOG_DAEMON);
if (getsockname(0, (struct sockaddr *)&from, &fromlen) < 0)
{ from_inetd = 0;
sock = RPC_ANYSOCK;
proto = IPPROTO_UDP;
}
if (!from_inetd)
{daemon(0, 0);
pmap_unset(RQUOTAPROG,RQUOTAVERS);
signal(SIGINT, exit_svc);/* trap some signals */
signal(SIGQUIT, exit_svc);/* to unregister the service*/
signal(SIGTERM, exit_svc);/* before exiting */
}
/* create and register the service*/
if ((transport=svcudp_create(sock))== NULL)
{syslog(LOG_ERR,"couldn't create UDP transport");exit (1);}
if (svc_register(transport,RQUOTAPROG,RQUOTAVERS,rquota_svc,proto)==0)
{syslog(LOG_ERR,"couldn't register service");exit (1);}
initfs();/* init the fs_stat list */
svc_run();
syslog(LOG_ERR,"svc_run has returned !");
exit(1); /* svc_run don't return */
}
/* rquota service */
void rquota_svc (request,transport)
struct svc_req *request;
SVCXPRT *transport;
{
switch (request->rq_proc)
{ case NULLPROC:
errno=0;
if (svc_sendreply(transport,xdr_void,0)==0)
printerr_reply(transport);
return;
case RQUOTAPROC_GETQUOTA:
case RQUOTAPROC_GETACTIVEQUOTA:
sendquota(request,transport);
return;
default:
svcerr_noproc(transport);
return;
}
}
/* read quota for the specified id, and send it */
void sendquota(request,transport)
struct svc_req *request;
SVCXPRT *transport;
{
struct getquota_args getq_args;
struct getquota_rslt getq_rslt;
struct dqblk dqblk;
struct timeval timev;
getq_args.gqa_pathp = NULL;/* allocated by svc_getargs */
if (svc_getargs(transport,xdr_getquota_args,&getq_args)==0)
{svcerr_decode(transport);return;}
if (request->rq_cred.oa_flavor!=AUTH_UNIX)
getq_rslt.status=Q_EPERM; /* bad auth */
else /* try to get fs quotas */
{ if (getfsquota(getq_args.gqa_uid,getq_args.gqa_pathp,&dqblk)
==0)
getq_rslt.status=Q_NOQUOTA; /* failed,return noquota */
else /* set the right values for getq_rslt, and send it */
{gettimeofday(&timev,NULL);
getq_rslt.status=Q_OK;
getq_rslt.getquota_rslt_u.gqr_rquota.rq_active
=TRUE;
getq_rslt.getquota_rslt_u.gqr_rquota.rq_bsize
=DEV_BSIZE;
getq_rslt.getquota_rslt_u.gqr_rquota.rq_bhardlimit
=dqblk.dqb_bhardlimit;
getq_rslt.getquota_rslt_u.gqr_rquota.rq_bsoftlimit
=dqblk.dqb_bsoftlimit;
getq_rslt.getquota_rslt_u.gqr_rquota.rq_curblocks
=dqblk.dqb_curblocks;
getq_rslt.getquota_rslt_u.gqr_rquota.rq_fhardlimit
=dqblk.dqb_ihardlimit;
getq_rslt.getquota_rslt_u.gqr_rquota.rq_fsoftlimit
=dqblk.dqb_isoftlimit;
getq_rslt.getquota_rslt_u.gqr_rquota.rq_curfiles
=dqblk.dqb_curinodes;
getq_rslt.getquota_rslt_u.gqr_rquota.rq_btimeleft
=dqblk.dqb_btime-timev.tv_sec;
getq_rslt.getquota_rslt_u.gqr_rquota.rq_ftimeleft
=dqblk.dqb_itime-timev.tv_sec;
}
}
if (svc_sendreply(transport,xdr_getquota_rslt,(char*)&getq_rslt)==0)
printerr_reply(transport);
return;
}
void exit_svc (signo) /* signal trapped */
int signo;
{
syslog(LOG_ERR,"exiting on signal %d",signo);
pmap_unset(RQUOTAPROG,RQUOTAVERS);
exit (0);
}
void printerr_reply(transport) /* when a reply to a request failed */
SVCXPRT *transport;
{
char *name;
struct sockaddr_in *caller;
int save_errno;
save_errno=errno;
caller=svc_getcaller(transport);
name=(char*)inet_ntoa(caller->sin_addr);
errno=save_errno;
if (errno==0)
syslog(LOG_ERR,"couldn't send reply to %s",name);
else
syslog(LOG_ERR,"couldn't send reply to %s: %m",name);
return;
}
void initfs() /* initialise the fs_tab list */
{
register struct fs_stat *fs_current=NULL;
register struct fs_stat *fs_next=NULL;
register struct fstab *fs;
struct stat st;
char *qfpathname,*malloc();
char *qfextension[] = INITQFNAMES;
setfsent(); /* get entries in /etc/fstab */
while (fs=getfsent())
{
if (strcmp(fs->fs_vfstype, "ufs"))
continue;
if (!hasquota(fs, &qfpathname))
continue;
fs_current=(struct fs_stat*)malloc(sizeof(struct fs_stat));
fs_current->fs_next=fs_next; /* next element */
fs_current->fs_file=malloc(sizeof(char)*(strlen(fs->fs_file)+1));
strcpy(fs_current->fs_file,fs->fs_file);
fs_current->qfpathname=malloc(sizeof(char)*(strlen(qfpathname)+1));
strcpy(fs_current->qfpathname,qfpathname);
stat(qfpathname,&st);
fs_current->st_dev=st.st_dev;
fs_next=fs_current; /* whe are going to get the previous*/
/* of the list */
}
endfsent();
fs_begin=fs_current; /* done. If no quota file where found */
/* fs_begin == NULL */
}
/* gets the quotas for id, filesystem path.Return 0 if fail, 1 otherwise */
int
getfsquota(id, path,dqblk)
register long id;
char *path;
struct dqblk *dqblk;
{
struct stat st_path;
register struct fs_stat *fs;
register int qcmd;
int fd;
register int ret=0;
char *qfextension[] = INITQFNAMES;
if (stat(path,&st_path)<0) return (0);
qcmd = QCMD(Q_GETQUOTA, USRQUOTA);
for (fs=fs_begin;fs!=NULL;fs=fs->fs_next) /* find the fs_stat element*/
/*where the devise is the same as path*/
{
if (fs->st_dev!=st_path.st_dev)
continue;
/* foud the specified filesystem. get and return quota */
/* the section below comes from quota.c, NetBSD 0.9*/
if (quotactl(fs->fs_file, qcmd, id, dqblk) == 0)
ret=1;
else
{
if ((fd = open(fs->qfpathname, O_RDONLY)) < 0) {
syslog(LOG_ERR,"couldn't read %s:%m",fs->qfpathname);
return (0);
}
lseek(fd, (long)(id * sizeof(struct dqblk)), L_SET);
switch (read(fd, dqblk, sizeof(struct dqblk))) {
case 0: /* EOF */
/*
* Convert implicit 0 quota (EOF)
* into an explicit one (zero'ed dqblk)
*/
bzero((caddr_t)dqblk,
sizeof(struct dqblk));
ret=1;
break;
case sizeof(struct dqblk): /* OK */
ret=1;
break;
default: /* ERROR */
syslog(LOG_ERR,"read error: %s: %m",fs->qfpathname);
close(fd);
return (0);
}
close(fd);
}
}
return (ret);
}
/*
* Check to see if a particular quota is to be enabled.
*/
/* Comes from quota.c, NetBSD 0.9 */
hasquota(fs, qfnamep)
register struct fstab *fs;
char **qfnamep;
{
register char *opt;
char *cp, *index(), *strtok();
static char initname, usrname[100];
static char buf[BUFSIZ];
char *qfextension[] = INITQFNAMES;
if (!initname) {
sprintf(usrname, "%s%s", qfextension[USRQUOTA], QUOTAFILENAME);
initname = 1;
}
strcpy(buf, fs->fs_mntops);
for (opt = strtok(buf, ","); opt; opt = strtok(NULL, ",")) {
if (cp = index(opt, '='))
*cp++ = '\0';
if (strcmp(opt, usrname) == 0)
break;
}
if (!opt)
return (0);
if (cp) {
*qfnamep = cp;
return (1);
}
(void) sprintf(buf, "%s/%s.%s", fs->fs_file, QUOTAFILENAME, qfextension[USRQUOTA]);
*qfnamep = buf;
return (1);
}
--
Manuel Bouyer, Ecole Nationale Superieure de Techniques Avancees, Paris
email: bouyer@ensta.fr
--