NFS quota support for FreeBSD
Stefan (metze) Metzmacher
metze at samba.org
Wed Jun 2 06:58:00 GMT 2004
Jeremy, Jerry,
any objectsions if I apply this?
I can't test it here and I don't want to break the next release:-)
But the patch looks good and it only takes effect when using --with-quotas
> I seem to have Samba 3.0.4 on FreeBSD properly fetching quota information
> for NFS filesystems. The code that does the work (nfs_quotas() and friends)
> was taken from the Sun implementation so I can't take much credit. :-)
>
> Patch attached and suggestions welcome.
>
>
>
> ------------------------------------------------------------------------
>
> --- smbd/quotas.c.orig Sun May 30 23:31:06 2004
> +++ smbd/quotas.c Sun May 30 23:44:35 2004
> @@ -933,6 +933,176 @@
> #include <devnm.h>
> #endif
>
> +#if defined(__FreeBSD__)
> +
> +#include <rpc/rpc.h>
> +#include <rpc/types.h>
> +#include <rpcsvc/rquota.h>
> +#include <rpc/nettype.h>
> +#include <rpc/xdr.h>
> +
> +static int quotastat;
> +
> +static int my_xdr_getquota_args(XDR *xdrsp, struct getquota_args *args)
> +{
> + if (!xdr_string(xdrsp, &args->gqa_pathp, RQ_PATHLEN ))
> + return(0);
> + if (!xdr_int(xdrsp, &args->gqa_uid))
> + return(0);
> + return (1);
> +}
> +
> +static int my_xdr_getquota_rslt(XDR *xdrsp, struct getquota_rslt *gqr)
> +{
> + if (!xdr_int(xdrsp, "astat)) {
> + DEBUG(6,("nfs_quotas: Status bad or zero\n"));
> + return 0;
> + }
> + if (!xdr_int(xdrsp, &gqr->getquota_rslt_u.gqr_rquota.rq_bsize)) {
> + DEBUG(6,("nfs_quotas: Block size bad or zero\n"));
> + return 0;
> + }
> + if (!xdr_bool(xdrsp, &gqr->getquota_rslt_u.gqr_rquota.rq_active)) {
> + DEBUG(6,("nfs_quotas: Active bad or zero\n"));
> + return 0;
> + }
> + if (!xdr_int(xdrsp, &gqr->getquota_rslt_u.gqr_rquota.rq_bhardlimit)) {
> + DEBUG(6,("nfs_quotas: Hardlimit bad or zero\n"));
> + return 0;
> + }
> + if (!xdr_int(xdrsp, &gqr->getquota_rslt_u.gqr_rquota.rq_bsoftlimit)) {
> + DEBUG(6,("nfs_quotas: Softlimit bad or zero\n"));
> + return 0;
> + }
> + if (!xdr_int(xdrsp, &gqr->getquota_rslt_u.gqr_rquota.rq_curblocks)) {
> + DEBUG(6,("nfs_quotas: Currentblocks bad or zero\n"));
> + return 0;
> + }
> + return (1);
> +}
> +
> +/* Works on FreeBSD, too. :-) */
> +static BOOL nfs_quotas(char *nfspath, uid_t euser_id, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize)
> +{
> + uid_t uid = euser_id;
> + struct dqblk D;
> + char *mnttype = nfspath;
> + CLIENT *clnt;
> + struct getquota_rslt gqr;
> + struct getquota_args args;
> + char *cutstr, *pathname, *host, *testpath;
> + int len;
> + static struct timeval timeout = {2,0};
> + enum clnt_stat clnt_stat;
> + BOOL ret = True;
> +
> + *bsize = *dfree = *dsize = (SMB_BIG_UINT)0;
> +
> + len=strcspn(mnttype, ":");
> + pathname=strstr(mnttype, ":");
> + cutstr = (char *) malloc(len+1);
> + if (!cutstr)
> + return False;
> +
> + memset(cutstr, '\0', len+1);
> + host = strncat(cutstr,mnttype, sizeof(char) * len );
> + DEBUG(5,("nfs_quotas: looking for mount on \"%s\"\n", cutstr));
> + DEBUG(5,("nfs_quotas: of path \"%s\"\n", mnttype));
> + testpath=strchr_m(mnttype, ':');
> + args.gqa_pathp = testpath+1;
> + args.gqa_uid = uid;
> +
> + DEBUG(5,("nfs_quotas: Asking for host \"%s\" rpcprog \"%i\" rpcvers \"%i\" network \"%s\"\n", host, RQUOTAPROG, RQUOTAVERS, "udp"));
> +
> + if ((clnt = clnt_create(host, RQUOTAPROG, RQUOTAVERS, "udp")) == NULL) {
> + ret = False;
> + goto out;
> + }
> +
> + clnt->cl_auth = authunix_create_default();
> + DEBUG(9,("nfs_quotas: auth_success\n"));
> +
> + clnt_stat=clnt_call(clnt, RQUOTAPROC_GETQUOTA, (const xdrproc_t) my_xdr_getquota_args, (caddr_t)&args, (const xdrproc_t) my_xdr_getquota_rslt, (caddr_t)&gqr, timeout);
> +
> + if (clnt_stat != RPC_SUCCESS) {
> + DEBUG(9,("nfs_quotas: clnt_call fail\n"));
> + ret = False;
> + goto out;
> + }
> +
> + /*
> + * quotastat returns 0 if the rpc call fails, 1 if quotas exist, 2 if there is
> + * no quota set, and 3 if no permission to get the quota. If 0 or 3 return
> + * something sensible.
> + */
> +
> + switch ( quotastat ) {
> + case 0:
> + DEBUG(9,("nfs_quotas: Remote Quotas Failed! Error \"%i\" \n", quotastat ));
> + ret = False;
> + goto out;
> +
> + case 1:
> + DEBUG(9,("nfs_quotas: Good quota data\n"));
> + D.dqb_bsoftlimit = gqr.getquota_rslt_u.gqr_rquota.rq_bsoftlimit;
> + D.dqb_bhardlimit = gqr.getquota_rslt_u.gqr_rquota.rq_bhardlimit;
> + D.dqb_curblocks = gqr.getquota_rslt_u.gqr_rquota.rq_curblocks;
> + break;
> +
> + case 2:
> + case 3:
> + D.dqb_bsoftlimit = 1;
> + D.dqb_curblocks = 1;
> + DEBUG(9,("nfs_quotas: Remote Quotas returned \"%i\" \n", quotastat ));
> + break;
> +
> + default:
> + DEBUG(9,("nfs_quotas: Remote Quotas Questionable! Error \"%i\" \n", quotastat ));
> + break;
> + }
> +
> + DEBUG(10,("nfs_quotas: Let`s look at D a bit closer... status \"%i\" bsize \"%i\" active? \"%i\" bhard \"%i\" bsoft \"%i\" curb \"%i\" \n",
> + quotastat,
> + gqr.getquota_rslt_u.gqr_rquota.rq_bsize,
> + gqr.getquota_rslt_u.gqr_rquota.rq_active,
> + gqr.getquota_rslt_u.gqr_rquota.rq_bhardlimit,
> + gqr.getquota_rslt_u.gqr_rquota.rq_bsoftlimit,
> + gqr.getquota_rslt_u.gqr_rquota.rq_curblocks));
> +
> + if (D.dqb_bsoftlimit == 0)
> + D.dqb_bsoftlimit = D.dqb_bhardlimit;
> + if (D.dqb_bsoftlimit == 0)
> + return False;
> +
> + *bsize = gqr.getquota_rslt_u.gqr_rquota.rq_bsize;
> + *dsize = D.dqb_bsoftlimit;
> +
> + if (D.dqb_curblocks == D.dqb_curblocks == 1)
> + *bsize = DEV_BSIZE;
> +
> + if (D.dqb_curblocks > D.dqb_bsoftlimit) {
> + *dfree = 0;
> + *dsize = D.dqb_curblocks;
> + } else
> + *dfree = D.dqb_bsoftlimit - D.dqb_curblocks;
> +
> + out:
> +
> + if (clnt) {
> + if (clnt->cl_auth)
> + auth_destroy(clnt->cl_auth);
> + clnt_destroy(clnt);
> + }
> +
> + DEBUG(5,("nfs_quotas: For path \"%s\" returning bsize %.0f, dfree %.0f, dsize %.0f\n",args.gqa_pathp,(double)*bsize,(double)*dfree,(double)*dsize));
> +
> + SAFE_FREE(cutstr);
> + DEBUG(10,("nfs_quotas: End of nfs_quotas\n" ));
> + return ret;
> +}
> +
> +#endif
> +
> /****************************************************************************
> try to get the disk space from disk quotas - default version
> ****************************************************************************/
> @@ -976,9 +1146,41 @@
> {
> /* FreeBSD patches from Marty Moll <martym at arbor.edu> */
> gid_t egrp_id;
> -
> +#if defined(__FreeBSD__)
> + SMB_DEV_T devno;
> + struct statfs *mnts;
> + SMB_STRUCT_STAT st;
> + int mntsize, i;
> +
> + if (sys_stat(path,&st) < 0)
> + return False;
> + devno = st.st_dev;
> +
> + mntsize = getmntinfo(&mnts,MNT_NOWAIT);
> + if (mntsize <= 0)
> + return False;
> +
> + for (i = 0; i < mntsize; i++) {
> + if (sys_stat(mnts[i].f_mntonname,&st) < 0)
> + return False;
> + if (st.st_dev == devno)
> + break;
> + }
> + if (i == mntsize)
> + return False;
> +#endif
> +
> save_re_uid();
> set_effective_uid(0);
> +
> +#if defined(__FreeBSD__)
> + if (strcmp(mnts[i].f_fstypename,"nfs") == 0) {
> + BOOL retval;
> + retval = nfs_quotas(mnts[i].f_mntfromname,euser_id,bsize,dfree,dsize);
> + restore_re_uid();
> + return retval;
> + }
> +#endif
>
> egrp_id = getegid();
> r= quotactl(path,QCMD(Q_GETQUOTA,USRQUOTA),euser_id,(char *) &D);
--
metze
Stefan Metzmacher <metze at samba.org> www.samba.org
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 194 bytes
Desc: OpenPGP digital signature
Url : http://lists.samba.org/archive/samba-technical/attachments/20040602/de0b877a/signature.bin
More information about the samba-technical
mailing list