From patchwork Sun Mar 23 09:46:05 2008 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Manfred Schmidt-Voigt X-Patchwork-Id: 12635 Received: from moutng.kundenserver.de ([212.227.126.171]) by www.linuxtv.org with esmtp (Exim 4.63) (envelope-from ) id 1JdMml-0002gy-Do for vdr@linuxtv.org; Sun, 23 Mar 2008 10:46:42 +0100 Received: from [192.168.123.109] (f054064069.adsl.alicedsl.de [78.54.64.69]) by mrelayeu.kundenserver.de (node=mrelayeu8) with ESMTP (Nemesis) id 0ML31I-1JdMmD1l51-0003X3; Sun, 23 Mar 2008 10:46:06 +0100 Message-ID: <47E626DD.7020207@mannitec.de> Date: Sun, 23 Mar 2008 10:46:05 +0100 From: Manfred Schmidt-Voigt Organization: private User-Agent: Mozilla-Thunderbird 2.0.0.9 (X11/20080110) MIME-Version: 1.0 To: manfred.schmidt-voigt@mannitec.de, VDR Mailing List References: <47D3A1DD.40403@mannitec.de> In-Reply-To: <47D3A1DD.40403@mannitec.de> X-Provags-ID: V01U2FsdGVkX19kRmUBZ7hAYhaSg+0mRYY2z1Aby/AIuTZQNv6 cg5K9uJyTE9mYQHGV3AIre8jMsKYKJbmE3oSYMlkJ7IHsWWZfT g05B/61KRJdB3s5ckOuiA== X-LSpam-Score: -1.3 (-) X-LSpam-Report: No, score=-1.3 required=5.0 tests=AWL=1.300, BAYES_00=-2.599 autolearn=ham Subject: Re: [vdr] Quota and VDR X-BeenThere: vdr@linuxtv.org X-Mailman-Version: 2.1.9 Precedence: list Reply-To: manfred.schmidt-voigt@mannitec.de, VDR Mailing List List-Id: VDR Mailing List List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 23 Mar 2008 09:46:42 -0000 Status: O X-Status: X-Keywords: X-UID: 16229 Manfred Schmidt-Voigt schrieb: > Hello List, > > I have a diskless VDR machine in my livingroom (so its very quit). My > /video is mounted by nfs from a Servermachine under the roof. On that > server I have set a groupquota for that /video directory to save some > place for other applikations on that filesystem (raid 5 - 4x400G). > > I have exeeded now the space on that filesystem for that group and in > the syslog of the VDR I can see related messages. > > Example: > Mar 9 08:52:32 stereo vdr: [4167] switching device 1 to channel 1 > Mar 9 08:52:32 stereo vdr: [4167] timer 18 (1 0852-1152 '@TITLE > EPISODE') start > Mar 9 08:52:32 stereo vdr: [4167] Title: 'Tigerenten Club' Subtitle: > 'Der Club zum Mitmachen' > Mar 9 08:52:32 stereo vdr: [4167] record > /video/@Tigerenten_Club_Der_Club_zum_Mitmachen/2008-03-09.08.52.50.99.rec > Mar 9 08:52:32 stereo vdr: [4167] creating directory > /video/@Tigerenten_Club_Der_Club_zum_Mitmachen > Mar 9 08:52:32 stereo vdr: [4167] ERROR: > /video/@Tigerenten_Club_Der_Club_zum_Mitmachen: Disk quota exceeded > > > But the VDR Software doesn't recognize that. It does not start to mark > old recording for removing. In the menu overview it show still some > hours free space util the end of the complete filesystem. > > Now my question: Do I have to configure something special in VDR that it > recognizes the Quota setting of that directory or have I to use > userquota for the user of VDR (in my case it is root but if it is the > only solution I could change it to a regular user, but only if it helps > for my problem)? > > Some revision data: > VDR 1.4.5 ( yes, I'm waiting for 1.6 ) > Debian Etch on both VDR and Server > > > Thank you > Manfred > > Hi List, because nobody answers me I have to answer myself: No, VDR is not able to follow Quota. It is looking only for the standard size parameters of the filesystem... ;-( So I had to help myself. The outcome is a patch/hack for my current VDR Version 1.4.5. But it should be easy to apopt it also to newer versions. I have glued it together out of several GOOGLE sniplets. Maybe somebody can look over this patch who has more ability to code this according real C++ styles. I'm not used to progamm in C++. But for this little patch it was sufficient. To use this you have to install the quota package on your server and maybe the quota-utils on your client. For your convenience I have included already the rquota-files into this patch. (I hope its according to any licenses) Have fun Manfred diff -Naur vdr-1.4.5_orig/Makefile vdr-1.4.5/Makefile --- vdr-1.4.5_orig/Makefile 2006-08-20 12:44:22.000000000 +0200 +++ vdr-1.4.5/Makefile 2008-03-23 09:32:25.000000000 +0100 @@ -37,7 +37,7 @@ lirc.o menu.o menuitems.o nit.o osdbase.o osd.o pat.o player.o plugin.o rcu.o\ receiver.o recorder.o recording.o remote.o remux.o ringbuffer.o sdt.o sections.o\ skinclassic.o skins.o skinsttng.o sources.o spu.o status.o svdrp.o themes.o thread.o\ - timers.o tools.o transfer.o vdr.o videodir.o + timers.o tools.o transfer.o vdr.o videodir.o rquota_xdr.o FIXFONT_ISO8859_1 = -adobe-courier-bold-r-normal--25-*-100-100-m-*-iso8859-1 OSDFONT_ISO8859_1 = -adobe-helvetica-medium-r-normal--23-*-100-100-p-*-iso8859-1 diff -Naur vdr-1.4.5_orig/rquota.h vdr-1.4.5/rquota.h --- vdr-1.4.5_orig/rquota.h 1970-01-01 01:00:00.000000000 +0100 +++ vdr-1.4.5/rquota.h 2008-03-23 09:31:01.000000000 +0100 @@ -0,0 +1,185 @@ +/* + * Please do not edit this file. + * It was generated using rpcgen. + */ + +#ifndef _RQUOTA_H_RPCGEN +#define _RQUOTA_H_RPCGEN + +#include + + +#ifdef __cplusplus +extern "C" { +#endif + +#define RQ_PATHLEN 1024 + +struct sq_dqblk { + u_int rq_bhardlimit; + u_int rq_bsoftlimit; + u_int rq_curblocks; + u_int rq_fhardlimit; + u_int rq_fsoftlimit; + u_int rq_curfiles; + u_int rq_btimeleft; + u_int rq_ftimeleft; +}; +typedef struct sq_dqblk sq_dqblk; + +struct getquota_args { + char *gqa_pathp; + int gqa_uid; +}; +typedef struct getquota_args getquota_args; + +struct setquota_args { + int sqa_qcmd; + char *sqa_pathp; + int sqa_id; + sq_dqblk sqa_dqblk; +}; +typedef struct setquota_args setquota_args; + +struct ext_getquota_args { + char *gqa_pathp; + int gqa_type; + int gqa_id; +}; +typedef struct ext_getquota_args ext_getquota_args; + +struct ext_setquota_args { + int sqa_qcmd; + char *sqa_pathp; + int sqa_id; + int sqa_type; + sq_dqblk sqa_dqblk; +}; +typedef struct ext_setquota_args ext_setquota_args; + +struct rquota { + int rq_bsize; + bool_t rq_active; + u_int rq_bhardlimit; + u_int rq_bsoftlimit; + u_int rq_curblocks; + u_int rq_fhardlimit; + u_int rq_fsoftlimit; + u_int rq_curfiles; + u_int rq_btimeleft; + u_int rq_ftimeleft; +}; +typedef struct rquota rquota; + +enum qr_status { + Q_OK = 1, + Q_NOQUOTA = 2, + Q_EPERM = 3, +}; +typedef enum qr_status qr_status; + +struct getquota_rslt { + qr_status status; + union { + rquota gqr_rquota; + } getquota_rslt_u; +}; +typedef struct getquota_rslt getquota_rslt; + +struct setquota_rslt { + qr_status status; + union { + rquota sqr_rquota; + } setquota_rslt_u; +}; +typedef struct setquota_rslt setquota_rslt; + +#define RQUOTAPROG 100011 +#define RQUOTAVERS 1 + +#if defined(__STDC__) || defined(__cplusplus) +#define RQUOTAPROC_GETQUOTA 1 +extern getquota_rslt * rquotaproc_getquota_1(getquota_args *, CLIENT *); +extern getquota_rslt * rquotaproc_getquota_1_svc(getquota_args *, struct svc_req *); +#define RQUOTAPROC_GETACTIVEQUOTA 2 +extern getquota_rslt * rquotaproc_getactivequota_1(getquota_args *, CLIENT *); +extern getquota_rslt * rquotaproc_getactivequota_1_svc(getquota_args *, struct svc_req *); +#define RQUOTAPROC_SETQUOTA 3 +extern setquota_rslt * rquotaproc_setquota_1(setquota_args *, CLIENT *); +extern setquota_rslt * rquotaproc_setquota_1_svc(setquota_args *, struct svc_req *); +#define RQUOTAPROC_SETACTIVEQUOTA 4 +extern setquota_rslt * rquotaproc_setactivequota_1(setquota_args *, CLIENT *); +extern setquota_rslt * rquotaproc_setactivequota_1_svc(setquota_args *, struct svc_req *); +extern int rquotaprog_1_freeresult (SVCXPRT *, xdrproc_t, caddr_t); + +#else /* K&R C */ +#define RQUOTAPROC_GETQUOTA 1 +extern getquota_rslt * rquotaproc_getquota_1(); +extern getquota_rslt * rquotaproc_getquota_1_svc(); +#define RQUOTAPROC_GETACTIVEQUOTA 2 +extern getquota_rslt * rquotaproc_getactivequota_1(); +extern getquota_rslt * rquotaproc_getactivequota_1_svc(); +#define RQUOTAPROC_SETQUOTA 3 +extern setquota_rslt * rquotaproc_setquota_1(); +extern setquota_rslt * rquotaproc_setquota_1_svc(); +#define RQUOTAPROC_SETACTIVEQUOTA 4 +extern setquota_rslt * rquotaproc_setactivequota_1(); +extern setquota_rslt * rquotaproc_setactivequota_1_svc(); +extern int rquotaprog_1_freeresult (); +#endif /* K&R C */ +#define EXT_RQUOTAVERS 2 + +#if defined(__STDC__) || defined(__cplusplus) +extern getquota_rslt * rquotaproc_getquota_2(ext_getquota_args *, CLIENT *); +extern getquota_rslt * rquotaproc_getquota_2_svc(ext_getquota_args *, struct svc_req *); +extern getquota_rslt * rquotaproc_getactivequota_2(ext_getquota_args *, CLIENT *); +extern getquota_rslt * rquotaproc_getactivequota_2_svc(ext_getquota_args *, struct svc_req *); +extern setquota_rslt * rquotaproc_setquota_2(ext_setquota_args *, CLIENT *); +extern setquota_rslt * rquotaproc_setquota_2_svc(ext_setquota_args *, struct svc_req *); +extern setquota_rslt * rquotaproc_setactivequota_2(ext_setquota_args *, CLIENT *); +extern setquota_rslt * rquotaproc_setactivequota_2_svc(ext_setquota_args *, struct svc_req *); +extern int rquotaprog_2_freeresult (SVCXPRT *, xdrproc_t, caddr_t); + +#else /* K&R C */ +extern getquota_rslt * rquotaproc_getquota_2(); +extern getquota_rslt * rquotaproc_getquota_2_svc(); +extern getquota_rslt * rquotaproc_getactivequota_2(); +extern getquota_rslt * rquotaproc_getactivequota_2_svc(); +extern setquota_rslt * rquotaproc_setquota_2(); +extern setquota_rslt * rquotaproc_setquota_2_svc(); +extern setquota_rslt * rquotaproc_setactivequota_2(); +extern setquota_rslt * rquotaproc_setactivequota_2_svc(); +extern int rquotaprog_2_freeresult (); +#endif /* K&R C */ + +/* the xdr functions */ + +#if defined(__STDC__) || defined(__cplusplus) +extern bool_t xdr_sq_dqblk (XDR *, sq_dqblk*); +extern bool_t xdr_getquota_args (XDR *, getquota_args*); +extern bool_t xdr_setquota_args (XDR *, setquota_args*); +extern bool_t xdr_ext_getquota_args (XDR *, ext_getquota_args*); +extern bool_t xdr_ext_setquota_args (XDR *, ext_setquota_args*); +extern bool_t xdr_rquota (XDR *, rquota*); +extern bool_t xdr_qr_status (XDR *, qr_status*); +extern bool_t xdr_getquota_rslt (XDR *, getquota_rslt*); +extern bool_t xdr_setquota_rslt (XDR *, setquota_rslt*); + +#else /* K&R C */ +extern bool_t xdr_sq_dqblk (); +extern bool_t xdr_getquota_args (); +extern bool_t xdr_setquota_args (); +extern bool_t xdr_ext_getquota_args (); +extern bool_t xdr_ext_setquota_args (); +extern bool_t xdr_rquota (); +extern bool_t xdr_qr_status (); +extern bool_t xdr_getquota_rslt (); +extern bool_t xdr_setquota_rslt (); + +#endif /* K&R C */ + +#ifdef __cplusplus +} +#endif + +#endif /* !_RQUOTA_H_RPCGEN */ diff -Naur vdr-1.4.5_orig/rquota.x vdr-1.4.5/rquota.x --- vdr-1.4.5_orig/rquota.x 1970-01-01 01:00:00.000000000 +0100 +++ vdr-1.4.5/rquota.x 2008-03-23 09:31:01.000000000 +0100 @@ -0,0 +1,139 @@ +/* @(#)rquota.x 2.1 88/08/01 4.0 RPCSRC */ +/* @(#)rquota.x 1.2 87/09/20 Copyr 1987 Sun Micro */ + +/* + * Remote quota protocol + * Requires unix authentication + */ + +const RQ_PATHLEN = 1024; + +struct sq_dqblk { + unsigned int rq_bhardlimit; /* absolute limit on disk blks alloc */ + unsigned int rq_bsoftlimit; /* preferred limit on disk blks */ + unsigned int rq_curblocks; /* current block count */ + unsigned int rq_fhardlimit; /* absolute limit on allocated files */ + unsigned int rq_fsoftlimit; /* preferred file limit */ + unsigned int rq_curfiles; /* current # allocated files */ + unsigned int rq_btimeleft; /* time left for excessive disk use */ + unsigned int rq_ftimeleft; /* time left for excessive files */ +}; + +struct getquota_args { + string gqa_pathp; /* path to filesystem of interest */ + int gqa_uid; /* Inquire about quota for uid */ +}; + +struct setquota_args { + int sqa_qcmd; + string sqa_pathp; /* path to filesystem of interest */ + int sqa_id; /* Set quota for uid */ + sq_dqblk sqa_dqblk; +}; + +struct ext_getquota_args { + string gqa_pathp; /* path to filesystem of interest */ + int gqa_type; /* Type of quota info is needed about */ + int gqa_id; /* Inquire about quota for id */ +}; + +struct ext_setquota_args { + int sqa_qcmd; + string sqa_pathp; /* path to filesystem of interest */ + int sqa_id; /* Set quota for id */ + int sqa_type; /* Type of quota to set */ + sq_dqblk sqa_dqblk; +}; + +/* + * remote quota structure + */ +struct rquota { + int rq_bsize; /* block size for block counts */ + bool rq_active; /* indicates whether quota is active */ + unsigned int rq_bhardlimit; /* absolute limit on disk blks alloc */ + unsigned int rq_bsoftlimit; /* preferred limit on disk blks */ + unsigned int rq_curblocks; /* current block count */ + unsigned int rq_fhardlimit; /* absolute limit on allocated files */ + unsigned int rq_fsoftlimit; /* preferred file limit */ + unsigned int rq_curfiles; /* current # allocated files */ + unsigned int rq_btimeleft; /* time left for excessive disk use */ + unsigned int rq_ftimeleft; /* time left for excessive files */ +}; + +enum qr_status { + Q_OK = 1, /* quota returned */ + Q_NOQUOTA = 2, /* noquota for uid */ + Q_EPERM = 3 /* no permission to access quota */ +}; + +union getquota_rslt switch (qr_status status) { +case Q_OK: + rquota gqr_rquota; /* valid if status == Q_OK */ +case Q_NOQUOTA: + void; +case Q_EPERM: + void; +}; + +union setquota_rslt switch (qr_status status) { +case Q_OK: + rquota sqr_rquota; /* valid if status == Q_OK */ +case Q_NOQUOTA: + void; +case Q_EPERM: + void; +}; + +program RQUOTAPROG { + version RQUOTAVERS { + /* + * Get all quotas + */ + getquota_rslt + RQUOTAPROC_GETQUOTA(getquota_args) = 1; + + /* + * Get active quotas only + */ + getquota_rslt + RQUOTAPROC_GETACTIVEQUOTA(getquota_args) = 2; + + /* + * Set all quotas + */ + setquota_rslt + RQUOTAPROC_SETQUOTA(setquota_args) = 3; + + /* + * Get active quotas only + */ + setquota_rslt + RQUOTAPROC_SETACTIVEQUOTA(setquota_args) = 4; + } = 1; + version EXT_RQUOTAVERS { + /* + * Get all quotas + */ + getquota_rslt + RQUOTAPROC_GETQUOTA(ext_getquota_args) = 1; + + /* + * Get active quotas only + */ + getquota_rslt + RQUOTAPROC_GETACTIVEQUOTA(ext_getquota_args) = 2; + + /* + * Set all quotas + */ + setquota_rslt + RQUOTAPROC_SETQUOTA(ext_setquota_args) = 3; + + /* + * Set active quotas only + */ + setquota_rslt + RQUOTAPROC_SETACTIVEQUOTA(ext_setquota_args) = 4; + } = 2; +} = 100011; diff -Naur vdr-1.4.5_orig/rquota_xdr.c vdr-1.4.5/rquota_xdr.c --- vdr-1.4.5_orig/rquota_xdr.c 1970-01-01 01:00:00.000000000 +0100 +++ vdr-1.4.5/rquota_xdr.c 2008-03-23 09:56:02.000000000 +0100 @@ -0,0 +1,310 @@ +/* + * Please do not edit this file. + * It was generated using rpcgen. + */ + +#include "rquota.h" + +bool_t +xdr_sq_dqblk (XDR *xdrs, sq_dqblk *objp) +{ + register int32_t *buf; + + + if (xdrs->x_op == XDR_ENCODE) { + buf = XDR_INLINE (xdrs, 8 * BYTES_PER_XDR_UNIT); + if (buf == NULL) { + if (!xdr_u_int (xdrs, &objp->rq_bhardlimit)) + return FALSE; + if (!xdr_u_int (xdrs, &objp->rq_bsoftlimit)) + return FALSE; + if (!xdr_u_int (xdrs, &objp->rq_curblocks)) + return FALSE; + if (!xdr_u_int (xdrs, &objp->rq_fhardlimit)) + return FALSE; + if (!xdr_u_int (xdrs, &objp->rq_fsoftlimit)) + return FALSE; + if (!xdr_u_int (xdrs, &objp->rq_curfiles)) + return FALSE; + if (!xdr_u_int (xdrs, &objp->rq_btimeleft)) + return FALSE; + if (!xdr_u_int (xdrs, &objp->rq_ftimeleft)) + return FALSE; + } else { + IXDR_PUT_U_LONG(buf, objp->rq_bhardlimit); + IXDR_PUT_U_LONG(buf, objp->rq_bsoftlimit); + IXDR_PUT_U_LONG(buf, objp->rq_curblocks); + IXDR_PUT_U_LONG(buf, objp->rq_fhardlimit); + IXDR_PUT_U_LONG(buf, objp->rq_fsoftlimit); + IXDR_PUT_U_LONG(buf, objp->rq_curfiles); + IXDR_PUT_U_LONG(buf, objp->rq_btimeleft); + IXDR_PUT_U_LONG(buf, objp->rq_ftimeleft); + } + return TRUE; + } else if (xdrs->x_op == XDR_DECODE) { + buf = XDR_INLINE (xdrs, 8 * BYTES_PER_XDR_UNIT); + if (buf == NULL) { + if (!xdr_u_int (xdrs, &objp->rq_bhardlimit)) + return FALSE; + if (!xdr_u_int (xdrs, &objp->rq_bsoftlimit)) + return FALSE; + if (!xdr_u_int (xdrs, &objp->rq_curblocks)) + return FALSE; + if (!xdr_u_int (xdrs, &objp->rq_fhardlimit)) + return FALSE; + if (!xdr_u_int (xdrs, &objp->rq_fsoftlimit)) + return FALSE; + if (!xdr_u_int (xdrs, &objp->rq_curfiles)) + return FALSE; + if (!xdr_u_int (xdrs, &objp->rq_btimeleft)) + return FALSE; + if (!xdr_u_int (xdrs, &objp->rq_ftimeleft)) + return FALSE; + } else { + objp->rq_bhardlimit = IXDR_GET_U_LONG(buf); + objp->rq_bsoftlimit = IXDR_GET_U_LONG(buf); + objp->rq_curblocks = IXDR_GET_U_LONG(buf); + objp->rq_fhardlimit = IXDR_GET_U_LONG(buf); + objp->rq_fsoftlimit = IXDR_GET_U_LONG(buf); + objp->rq_curfiles = IXDR_GET_U_LONG(buf); + objp->rq_btimeleft = IXDR_GET_U_LONG(buf); + objp->rq_ftimeleft = IXDR_GET_U_LONG(buf); + } + return TRUE; + } + + if (!xdr_u_int (xdrs, &objp->rq_bhardlimit)) + return FALSE; + if (!xdr_u_int (xdrs, &objp->rq_bsoftlimit)) + return FALSE; + if (!xdr_u_int (xdrs, &objp->rq_curblocks)) + return FALSE; + if (!xdr_u_int (xdrs, &objp->rq_fhardlimit)) + return FALSE; + if (!xdr_u_int (xdrs, &objp->rq_fsoftlimit)) + return FALSE; + if (!xdr_u_int (xdrs, &objp->rq_curfiles)) + return FALSE; + if (!xdr_u_int (xdrs, &objp->rq_btimeleft)) + return FALSE; + if (!xdr_u_int (xdrs, &objp->rq_ftimeleft)) + return FALSE; + return TRUE; +} + +bool_t +xdr_getquota_args (XDR *xdrs, getquota_args *objp) +{ + register int32_t *buf; + + if (!xdr_string (xdrs, &objp->gqa_pathp, RQ_PATHLEN)) + return FALSE; + if (!xdr_int (xdrs, &objp->gqa_uid)) + return FALSE; + return TRUE; +} + +bool_t +xdr_setquota_args (XDR *xdrs, setquota_args *objp) +{ + register int32_t *buf; + + if (!xdr_int (xdrs, &objp->sqa_qcmd)) + return FALSE; + if (!xdr_string (xdrs, &objp->sqa_pathp, RQ_PATHLEN)) + return FALSE; + if (!xdr_int (xdrs, &objp->sqa_id)) + return FALSE; + if (!xdr_sq_dqblk (xdrs, &objp->sqa_dqblk)) + return FALSE; + return TRUE; +} + +bool_t +xdr_ext_getquota_args (XDR *xdrs, ext_getquota_args *objp) +{ + register int32_t *buf; + + if (!xdr_string (xdrs, &objp->gqa_pathp, RQ_PATHLEN)) + return FALSE; + if (!xdr_int (xdrs, &objp->gqa_type)) + return FALSE; + if (!xdr_int (xdrs, &objp->gqa_id)) + return FALSE; + return TRUE; +} + +bool_t +xdr_ext_setquota_args (XDR *xdrs, ext_setquota_args *objp) +{ + register int32_t *buf; + + if (!xdr_int (xdrs, &objp->sqa_qcmd)) + return FALSE; + if (!xdr_string (xdrs, &objp->sqa_pathp, RQ_PATHLEN)) + return FALSE; + if (!xdr_int (xdrs, &objp->sqa_id)) + return FALSE; + if (!xdr_int (xdrs, &objp->sqa_type)) + return FALSE; + if (!xdr_sq_dqblk (xdrs, &objp->sqa_dqblk)) + return FALSE; + return TRUE; +} + +bool_t +xdr_rquota (XDR *xdrs, rquota *objp) +{ + register int32_t *buf; + + + if (xdrs->x_op == XDR_ENCODE) { + buf = XDR_INLINE (xdrs, 10 * BYTES_PER_XDR_UNIT); + if (buf == NULL) { + if (!xdr_int (xdrs, &objp->rq_bsize)) + return FALSE; + if (!xdr_bool (xdrs, &objp->rq_active)) + return FALSE; + if (!xdr_u_int (xdrs, &objp->rq_bhardlimit)) + return FALSE; + if (!xdr_u_int (xdrs, &objp->rq_bsoftlimit)) + return FALSE; + if (!xdr_u_int (xdrs, &objp->rq_curblocks)) + return FALSE; + if (!xdr_u_int (xdrs, &objp->rq_fhardlimit)) + return FALSE; + if (!xdr_u_int (xdrs, &objp->rq_fsoftlimit)) + return FALSE; + if (!xdr_u_int (xdrs, &objp->rq_curfiles)) + return FALSE; + if (!xdr_u_int (xdrs, &objp->rq_btimeleft)) + return FALSE; + if (!xdr_u_int (xdrs, &objp->rq_ftimeleft)) + return FALSE; + } else { + IXDR_PUT_LONG(buf, objp->rq_bsize); + IXDR_PUT_BOOL(buf, objp->rq_active); + IXDR_PUT_U_LONG(buf, objp->rq_bhardlimit); + IXDR_PUT_U_LONG(buf, objp->rq_bsoftlimit); + IXDR_PUT_U_LONG(buf, objp->rq_curblocks); + IXDR_PUT_U_LONG(buf, objp->rq_fhardlimit); + IXDR_PUT_U_LONG(buf, objp->rq_fsoftlimit); + IXDR_PUT_U_LONG(buf, objp->rq_curfiles); + IXDR_PUT_U_LONG(buf, objp->rq_btimeleft); + IXDR_PUT_U_LONG(buf, objp->rq_ftimeleft); + } + return TRUE; + } else if (xdrs->x_op == XDR_DECODE) { + buf = XDR_INLINE (xdrs, 10 * BYTES_PER_XDR_UNIT); + if (buf == NULL) { + if (!xdr_int (xdrs, &objp->rq_bsize)) + return FALSE; + if (!xdr_bool (xdrs, &objp->rq_active)) + return FALSE; + if (!xdr_u_int (xdrs, &objp->rq_bhardlimit)) + return FALSE; + if (!xdr_u_int (xdrs, &objp->rq_bsoftlimit)) + return FALSE; + if (!xdr_u_int (xdrs, &objp->rq_curblocks)) + return FALSE; + if (!xdr_u_int (xdrs, &objp->rq_fhardlimit)) + return FALSE; + if (!xdr_u_int (xdrs, &objp->rq_fsoftlimit)) + return FALSE; + if (!xdr_u_int (xdrs, &objp->rq_curfiles)) + return FALSE; + if (!xdr_u_int (xdrs, &objp->rq_btimeleft)) + return FALSE; + if (!xdr_u_int (xdrs, &objp->rq_ftimeleft)) + return FALSE; + } else { + objp->rq_bsize = IXDR_GET_LONG(buf); + objp->rq_active = IXDR_GET_BOOL(buf); + objp->rq_bhardlimit = IXDR_GET_U_LONG(buf); + objp->rq_bsoftlimit = IXDR_GET_U_LONG(buf); + objp->rq_curblocks = IXDR_GET_U_LONG(buf); + objp->rq_fhardlimit = IXDR_GET_U_LONG(buf); + objp->rq_fsoftlimit = IXDR_GET_U_LONG(buf); + objp->rq_curfiles = IXDR_GET_U_LONG(buf); + objp->rq_btimeleft = IXDR_GET_U_LONG(buf); + objp->rq_ftimeleft = IXDR_GET_U_LONG(buf); + } + return TRUE; + } + + if (!xdr_int (xdrs, &objp->rq_bsize)) + return FALSE; + if (!xdr_bool (xdrs, &objp->rq_active)) + return FALSE; + if (!xdr_u_int (xdrs, &objp->rq_bhardlimit)) + return FALSE; + if (!xdr_u_int (xdrs, &objp->rq_bsoftlimit)) + return FALSE; + if (!xdr_u_int (xdrs, &objp->rq_curblocks)) + return FALSE; + if (!xdr_u_int (xdrs, &objp->rq_fhardlimit)) + return FALSE; + if (!xdr_u_int (xdrs, &objp->rq_fsoftlimit)) + return FALSE; + if (!xdr_u_int (xdrs, &objp->rq_curfiles)) + return FALSE; + if (!xdr_u_int (xdrs, &objp->rq_btimeleft)) + return FALSE; + if (!xdr_u_int (xdrs, &objp->rq_ftimeleft)) + return FALSE; + return TRUE; +} + +bool_t +xdr_qr_status (XDR *xdrs, qr_status *objp) +{ + register int32_t *buf; + + if (!xdr_enum (xdrs, (enum_t *) objp)) + return FALSE; + return TRUE; +} + +bool_t +xdr_getquota_rslt (XDR *xdrs, getquota_rslt *objp) +{ + register int32_t *buf; + + if (!xdr_qr_status (xdrs, &objp->status)) + return FALSE; + switch (objp->status) { + case Q_OK: + if (!xdr_rquota (xdrs, &objp->getquota_rslt_u.gqr_rquota)) + return FALSE; + break; + case Q_NOQUOTA: + break; + case Q_EPERM: + break; + default: + return FALSE; + } + return TRUE; +} + +bool_t +xdr_setquota_rslt (XDR *xdrs, setquota_rslt *objp) +{ + register int32_t *buf; + + if (!xdr_qr_status (xdrs, &objp->status)) + return FALSE; + switch (objp->status) { + case Q_OK: + if (!xdr_rquota (xdrs, &objp->setquota_rslt_u.sqr_rquota)) + return FALSE; + break; + case Q_NOQUOTA: + break; + case Q_EPERM: + break; + default: + return FALSE; + } + return TRUE; +} diff -Naur vdr-1.4.5_orig/tools.c vdr-1.4.5/tools.c --- vdr-1.4.5_orig/tools.c 2006-12-02 12:12:59.000000000 +0100 +++ vdr-1.4.5/tools.c 2008-03-23 10:16:15.000000000 +0100 @@ -28,6 +28,17 @@ #include "i18n.h" #include "thread.h" +#include +#include +#include +#include +#include +#include +#include +#include "rquota.h" +#include +#include + int SysLogLevel = 3; #define MAXSYSLOGBUF 256 @@ -282,24 +293,311 @@ snprintf(buf, sizeof(buf), "%d", n); return buf; } - int FreeDiskSpaceMB(const char *Directory, int *UsedMB) { - if (UsedMB) - *UsedMB = 0; - int Free = 0; - struct statfs statFs; - if (statfs(Directory, &statFs) == 0) { - double blocksPerMeg = 1024.0 * 1024.0 / statFs.f_bsize; - if (UsedMB) - *UsedMB = int((statFs.f_blocks - statFs.f_bfree) / blocksPerMeg); - Free = int(statFs.f_bavail / blocksPerMeg); - } - else - LOG_ERROR_STR(Directory); - return Free; -} + if (UsedMB) + *UsedMB = 0; + int Free = 0; + struct statfs statFs; + + //struct dqblk q; + struct fs_disk_quota f; + struct getquota_rslt gqr; + struct ext_getquota_args gqa; + FILE *mnt; + struct mntent *mp; + struct stat s,t; + uid_t euser_id; + + if ( -1 == ( stat(Directory, &s))) + { + LOG_ERROR_STR(Directory); + return Free; + } + + euser_id=geteuid(); + + if ( NULL == ( mnt = setmntent("/etc/mtab","r"))) + { + LOG_ERROR_STR(Directory); + return Free; + } + else + { + + while ( (mp = getmntent(mnt)) ) + { + if ( -1 == ( stat(mp->mnt_dir,&t))) + continue; + + if (t.st_dev == s.st_dev) + break; + } + + endmntent( mnt ); + + if (t.st_dev != s.st_dev) + { + LOG_ERROR_STR(Directory); + return Free; + } + if ( 0 == strcmp ( mp->mnt_type, "xfs" )) + { + if ( -1 == quotactl ( + QCMD(Q_XGETQUOTA,USRQUOTA), + mp->mnt_fsname, + getuid(), + (caddr_t) &f) + ) { + ;// perror("quotactl"); + if ( -1 == quotactl ( + QCMD(Q_XGETQUOTA,GRPQUOTA), + mp->mnt_fsname, + s.st_gid, + (caddr_t) &f) + ) + ;// perror("quotactl"); + }else{ + Free = int(f.d_blk_hardlimit - f.d_bcount)/(1024*1024); + if (UsedMB) + *UsedMB = int((f.d_bcount)/(1024*1024)); + + return Free; + } + + } + + else if ( 0 == strncmp ( mp->mnt_type, "ext3", 3 )) + { + if ( -1 == quotactl ( + QCMD(Q_GETQUOTA,USRQUOTA), + mp->mnt_fsname, + getuid(), + (caddr_t) &f) + ) { + ;// perror("quotactl"); + if ( -1 == quotactl ( + QCMD(Q_GETQUOTA,GRPQUOTA), + mp->mnt_fsname, + s.st_gid, + (caddr_t) &f) + ) + ;// perror("quotactl"); + }else{ + Free = int(f.d_blk_hardlimit - f.d_bcount)/(1024*1024); + if (UsedMB) + *UsedMB = int(f.d_bcount)/(1024*1024); + + return Free; + } + } + else if ( 0 == strncmp ( mp->mnt_type, "nfs", 3 )) + { + char *p; + char *hostname; + + p=strchr(mp->mnt_fsname, ':'); + *p=0x00; + gqa.gqa_pathp = p+1; + gqa.gqa_id = s.st_gid; + gqa.gqa_type = GRPQUOTA; + + hostname = mp->mnt_fsname; + + if ( 0!= call_rpc( + hostname, + RQUOTAPROG, + EXT_RQUOTAVERS, + RQUOTAPROC_GETQUOTA, + (xdrproc_t)xdr_ext_getquota_args, + &gqa, + (xdrproc_t)xdr_getquota_rslt, + &gqr + )) + { + ;// perror("rpc"); + } + else + { + switch (gqr.status) + { + case Q_OK: + Free = int(gqr.getquota_rslt_u.gqr_rquota.rq_bsoftlimit - gqr.getquota_rslt_u.gqr_rquota.rq_curblocks)/1024; + if (UsedMB) + *UsedMB = int(gqr.getquota_rslt_u.gqr_rquota.rq_curblocks)/1024; + + return Free; + break; + + case Q_NOQUOTA: + // same for UserID + + gqa.gqa_id = euser_id; + gqa.gqa_type = USRQUOTA; + + hostname = mp->mnt_fsname; + + if ( 0!= call_rpc( + hostname, + RQUOTAPROG, + EXT_RQUOTAVERS, + RQUOTAPROC_GETQUOTA, + (xdrproc_t)xdr_ext_getquota_args, + &gqa, + (xdrproc_t)xdr_getquota_rslt, + &gqr + )) + { + ;// perror("rpc"); + } + else + { + switch (gqr.status) + { + case Q_OK: + + + Free = int(gqr.getquota_rslt_u.gqr_rquota.rq_bsoftlimit - gqr.getquota_rslt_u.gqr_rquota.rq_curblocks)/1024; + if (UsedMB) + *UsedMB = int(gqr.getquota_rslt_u.gqr_rquota.rq_curblocks)/1024; + + return Free; + break; + + case Q_NOQUOTA: + + + break; + + case Q_EPERM: + fprintf(stderr, "quota permission error, host: %s\n", + hostname); + break; + default: + fprintf(stderr, "bad rpc result, host: %s\n", + hostname); + break; + + + } + } + + + break; + + case Q_EPERM: + fprintf(stderr, "quota permission error, host: %s\n", + hostname); + break; + default: + fprintf(stderr, "bad rpc result, host: %s\n", + hostname); + break; + + } + + } + } + + if (statfs(Directory, &statFs) == 0) { + double blocksPerMeg = 1024.0 * 1024.0 / statFs.f_bsize; + if (UsedMB) + *UsedMB = int((statFs.f_blocks - statFs.f_bfree) / blocksPerMeg); + Free = int(statFs.f_bavail / blocksPerMeg); + } + else + LOG_ERROR_STR(Directory); + return Free; + + + } + return Free; +} +int call_rpc( + char *host, + int prognum, int versnum, int procnum, + xdrproc_t inproc, + struct ext_getquota_args *in, + xdrproc_t outproc, + struct getquota_rslt *out +) +{ + struct sockaddr_in server_addr; + enum clnt_stat clnt_stat; + struct hostent *hp; + struct timeval timeout, tottimeout; + + static CLIENT *client = NULL; + static int socket = RPC_ANYSOCK; + static int valid = 0; + static int oldprognum, oldversnum; + static char oldhost[256]; + + if (valid && oldprognum == prognum && oldversnum == versnum + && strcmp(oldhost, host) == 0) + { + /* reuse old client */ + } + else + { + valid = 0; + close(socket); + socket = RPC_ANYSOCK; + if (client) + { + clnt_destroy(client); + client = NULL; + } + if ((hp = gethostbyname(host)) == NULL) + return ((int) RPC_UNKNOWNHOST); + timeout.tv_usec = 0; + timeout.tv_sec = 6; + // bcopy(hp->h_addr, &server_addr.sin_addr, hp->h_length); + memcpy(&server_addr.sin_addr, hp->h_addr, hp->h_length); + + server_addr.sin_family = AF_INET; + /* ping the remote end via tcp to see if it is up */ + server_addr.sin_port = htons(PMAPPORT); + if ((client = clnttcp_create(&server_addr, PMAPPROG, + PMAPVERS, &socket, 0, 0)) == NULL) + { + printf("%d - error clnttcp_create \n",(int) rpc_createerr.cf_stat); + return ((int) rpc_createerr.cf_stat); + } + else + { + /* the fact we succeeded means the machine is up */ + close(socket); + socket = RPC_ANYSOCK; + clnt_destroy(client); + client = NULL; + } + /* now really create a udp client handle */ + server_addr.sin_port = 0; + if ((client = clntudp_create(&server_addr, prognum, + versnum, timeout, &socket)) == NULL) + { + return ((int) rpc_createerr.cf_stat); + } + client->cl_auth = authunix_create_default(); + valid = 1; + oldprognum = prognum; + oldversnum = versnum; + strcpy(oldhost, host); + } + tottimeout.tv_sec = 25; + tottimeout.tv_usec = 0; + clnt_stat = clnt_call(client, procnum, inproc, (char*)in, outproc, (char*)out, tottimeout); + /* + * if call failed, empty cache + */ + if (clnt_stat != RPC_SUCCESS) + { + valid = 0; + } + return ((int) clnt_stat); +} bool DirectoryOk(const char *DirName, bool LogErrors) { struct stat ds; diff -Naur vdr-1.4.5_orig/tools.h vdr-1.4.5/tools.h --- vdr-1.4.5_orig/tools.h 2006-12-03 18:38:38.000000000 +0100 +++ vdr-1.4.5/tools.h 2008-03-23 09:58:05.000000000 +0100 @@ -21,6 +21,7 @@ #include #include #include +#include "rquota.h" typedef unsigned char uchar; #define uint64 uint64_t // for compatibility - TODO remove in version 1.5 @@ -108,6 +109,14 @@ bool isnumber(const char *s); cString itoa(int n); cString AddDirectory(const char *DirName, const char *FileName); +int call_rpc( + char *host, + int prognum, int versnum, int procnum, + xdrproc_t inproc, + struct ext_getquota_args *in, + xdrproc_t outproc, + struct getquota_rslt *out +); int FreeDiskSpaceMB(const char *Directory, int *UsedMB = NULL); bool DirectoryOk(const char *DirName, bool LogErrors = false); bool MakeDirs(const char *FileName, bool IsDirectory = false);