Klaus Schmidinger schrieb:
On 03/23/08 10:46, Manfred Schmidt-Voigt wrote:
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

Sorry, but this is really too much to change for implementing quota handling.
Besides, if an application actually needs to do this much to follow system
quotas, doesn't this mean that apps that just don't care about quotas can
do whatever they want?

Shouldn't the presence of quotas mean that *every* application sees only
parameters that fit the current quota, without even "knowing" that it has
been limited?

Klaus

_______________________________________________
vdr mailing list
vdr@linuxtv.org
http://www.linuxtv.org/cgi-bin/mailman/listinfo/vdr


Applications, which do not care about quota, can not really do what they want, they only can not write to the filesystem if the quotalimit is reached. Thats what quota is made for. But if you would like to react on such a limit in a more intelligent way you have to ask for that limit and not only for the simple filesystem limit. statfs(..) only delivers the 'physical' limits of the filesystem. So vdr could not make new recordings when the limit is reached because it checks for the filesystemlimit. This value shows vdr to have enough space. So it never starts to delete old recordings.

I have changed the patch a little bit because there was a logical fault in it. But now it's for vdr-1.6.0. I have not tested the xfs part because currently I use only ext3 or nfs. So this should be tested maybe by somebody else or if you would like to implement such a logic into vdr leave it out or comment it out or do it your own way. The problem here is that by each kind of check of the different filesystems you receive different numberunits of something what is called a block. It seems so that all the people, which implements the quotalogic for the different filesystems, had a different thought what a block should look like...

Manfred

--
-------                   Manfred Schmidt-Voigt                  -------
-----                        www.mannitec.de                       -----
-------          mailto:[EMAIL PROTECTED]        -------
diff -Naur vdr-1.6.0_orig/Makefile vdr-1.6.0/Makefile
--- vdr-1.6.0_orig/Makefile	2008-02-29 22:43:03.000000000 +0100
+++ vdr-1.6.0/Makefile	2008-04-13 23:52:12.000000000 +0200
@@ -41,7 +41,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 shutdown.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
 
 ifndef NO_KBD
 DEFINES += -DREMOTE_KBD
diff -Naur vdr-1.6.0_orig/rquota.h vdr-1.6.0/rquota.h
--- vdr-1.6.0_orig/rquota.h	1970-01-01 01:00:00.000000000 +0100
+++ vdr-1.6.0/rquota.h	2008-04-13 23:52:38.000000000 +0200
@@ -0,0 +1,185 @@
+/*
+ * Please do not edit this file.
+ * It was generated using rpcgen.
+ */
+
+#ifndef _RQUOTA_H_RPCGEN
+#define _RQUOTA_H_RPCGEN
+
+#include <rpc/rpc.h>
+
+
+#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.6.0_orig/rquota.x vdr-1.6.0/rquota.x
--- vdr-1.6.0_orig/rquota.x	1970-01-01 01:00:00.000000000 +0100
+++ vdr-1.6.0/rquota.x	2008-04-13 23:52:39.000000000 +0200
@@ -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<RQ_PATHLEN>;  	/* path to filesystem of interest */
+	int gqa_uid;			/* Inquire about quota for uid */
+};
+
+struct setquota_args {
+	int sqa_qcmd;
+	string sqa_pathp<RQ_PATHLEN>;  	/* path to filesystem of interest */
+	int sqa_id;			/* Set quota for uid */
+	sq_dqblk sqa_dqblk;
+};
+
+struct ext_getquota_args {
+	string gqa_pathp<RQ_PATHLEN>;  	/* 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<RQ_PATHLEN>;  	/* 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.6.0_orig/rquota_xdr.c vdr-1.6.0/rquota_xdr.c
--- vdr-1.6.0_orig/rquota_xdr.c	1970-01-01 01:00:00.000000000 +0100
+++ vdr-1.6.0/rquota_xdr.c	2008-04-13 23:52:54.000000000 +0200
@@ -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.6.0_orig/tools.c vdr-1.6.0/tools.c
--- vdr-1.6.0_orig/tools.c	2008-03-05 18:23:47.000000000 +0100
+++ vdr-1.6.0/tools.c	2008-04-13 23:51:56.000000000 +0200
@@ -28,6 +28,17 @@
 #include "i18n.h"
 #include "thread.h"
 
+#include <netinet/in.h>
+#include <netdb.h>
+#include <linux/dqblk_xfs.h>
+#include <rpc/types.h>
+#include <rpc/xdr.h>
+#include <rpc/rpc.h>
+#include <rpc/pmap_prot.h>
+#include "rquota.h"
+#include <sys/quota.h>
+#include <mntent.h>
+
 int SysLogLevel = 3;
 
 #define MAXSYSLOGBUF 256
@@ -291,24 +302,310 @@
      LOG_ERROR_STR(File1);
   return false;
 }
-
 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 e;
+	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) ) 
+			{
+			     	if ( -1 == quotactl ( QCMD(Q_XGETQUOTA,GRPQUOTA), mp->mnt_fsname, s.st_gid, (caddr_t) &f) )
+				{
+					; // no quota
+				}else{
+					Free = int(f.d_blk_hardlimit - f.d_bcount)/(1024*1024);
+					if (UsedMB)
+						*UsedMB = int((f.d_bcount)/(1024*1024));
+
+					return Free;
+				}
+			}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) &e) ) 
+			{
+			     	if ( -1 == quotactl ( QCMD(Q_GETQUOTA,GRPQUOTA), mp->mnt_fsname, s.st_gid, (caddr_t) &e) )
+				{
+					; // no quota
+				}else{
+					Free = int(e.dqb_bhardlimit - (e.dqb_curspace)/(1024))/1024;
+
+					if (UsedMB)
+						*UsedMB = int(e.dqb_curspace)/(1024*1024);
+
+					return Free;
+				}
+			}else{
+				Free = int(e.dqb_bhardlimit - (e.dqb_curspace)/(1024))/1024;
+
+				if (UsedMB)
+					*UsedMB = int(e.dqb_curspace)/(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.6.0_orig/tools.h vdr-1.6.0/tools.h
--- vdr-1.6.0_orig/tools.h	2008-02-17 14:41:27.000000000 +0100
+++ vdr-1.6.0/tools.h	2008-04-13 23:51:57.000000000 +0200
@@ -23,6 +23,7 @@
 #include <syslog.h>
 #include <sys/stat.h>
 #include <sys/types.h>
+#include "rquota.h"
 
 typedef unsigned char uchar;
 
@@ -195,6 +196,15 @@
 cString itoa(int n);
 cString AddDirectory(const char *DirName, const char *FileName);
 bool EntriesOnSameFileSystem(const char *File1, const char *File2);
+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);
_______________________________________________
vdr mailing list
vdr@linuxtv.org
http://www.linuxtv.org/cgi-bin/mailman/listinfo/vdr

Reply via email to