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
--
------- Manfred Schmidt-Voigt -------
----- www.mannitec.de -----
------- mailto:[EMAIL PROTECTED] -------
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 <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.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<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.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 <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
@@ -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 <syslog.h>
#include <sys/stat.h>
#include <sys/types.h>
+#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);
_______________________________________________
vdr mailing list
vdr@linuxtv.org
http://www.linuxtv.org/cgi-bin/mailman/listinfo/vdr