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 --