$NetBSD: patch-ab,v 1.10 2012/05/12 23:10:30 dholland Exp $ - fix package's version number - remove a debug printout - need unistd.h for some things - support dragonfly - support linux 2.6+ with slightly different API - support netbsd-3+ with statvfs - support netbsd-6+ with libquota - fix solaris code - ruby API fixes - ...? --- quota.c.orig 2002-03-30 14:59:12.000000000 +0000 +++ quota.c @@ -5,17 +5,25 @@ #include "ruby.h" -#define RUBY_QUOTA_VERSION "0.4.1" +#define RUBY_QUOTA_VERSION "0.5.1" -#ifdef HAVE_LINUX_QUOTA_H /* for linux-2.4.x */ +#ifdef HAVE_UNISTD_H +#include +#endif + +#ifdef HAVE_LINUX_QUOTA_H /* for linux */ # define USE_LINUX_QUOTA #endif #ifdef HAVE_SYS_FS_UFS_QUOTA_H /* for Solaris-2.6,7,8 */ # define USE_SOLARIS_QUOTA #endif -#ifdef HAVE_UFS_UFS_QUOTA_H /* for *BSD */ +#ifdef HAVE_QUOTA_H /* for NetBSD-6 and up */ +# define USE_NETBSD_QUOTA +#else +#ifdef HAVE_UFS_UFS_QUOTA_H /* for traditional *BSD */ # define USE_BSD_QUOTA #endif +#endif #ifdef USE_LINUX_QUOTA #ifdef HAVE_LINUX_TYPES_H @@ -29,10 +37,16 @@ # include #endif #include -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) +# define USE_LINUX_QUOTA_26 +# define qid_t uid_t +# define dqblk if_dqblk +#else +# if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) # define USE_LINUX_QUOTA_24 # define uid_t qid_t # define dqblk disk_dqblk +# endif #endif #endif @@ -42,6 +56,12 @@ #include #endif +#ifdef USE_NETBSD_QUOTA +#include +#include +#include +#endif + #ifdef USE_BSD_QUOTA #include #include @@ -51,6 +71,12 @@ #if defined(SYS_UCRED_H) # include /* required by NetBSD,FreeBSD */ #endif +#if defined(__DragonFly__) +# include +# if __DragonFly_version >= 160000 +# define dqblk ufs_dqblk +# endif +#endif #endif static VALUE rb_mQuota; @@ -144,7 +170,6 @@ rb_quotactl(int cmd, char *dev, VALUE vu uid_t uid; get_uid(vuid, &uid, &is_gid); - printf("cmd = %d, dev = %s, uid = %d, gid? = %d\n", cmd, dev, uid, is_gid); if( is_gid ){ return quotactl(QCMD(cmd,GRPQUOTA),dev,(qid_t)uid,addr); } @@ -152,14 +177,18 @@ rb_quotactl(int cmd, char *dev, VALUE vu return quotactl(QCMD(cmd,USRQUOTA),dev,(qid_t)uid,addr); }; }; -#elif defined(USE_BSD_QUOTA) /* for *BSD */ +#elif defined(USE_BSD_QUOTA) /* for traditional *BSD */ static int rb_quotactl(int cmd, char *dev, VALUE vuid, caddr_t addr) { char *path; int is_gid; uid_t uid; +#if defined(HAVE_SYS_STATVFS_H) && !defined(__DragonFly__) + struct statvfs *buff; +#else struct statfs *buff; +#endif int i, count, ret; buff = 0; @@ -187,12 +216,16 @@ rb_quotactl(int cmd, char *dev, VALUE vu static int rb_quotactl(int cmd, char *dev, VALUE vuid, caddr_t addr) { - struct quotctl qctl = {cmd, uid, addr}; + struct quotctl qctl; int fd; uid_t uid; get_uid(vuid, &uid, 0); + qctl.op = cmd; + qctl.uid = uid; + qctl.addr = addr; + switch( cmd ){ case Q_QUOTAON: case Q_QUOTAOFF: @@ -225,17 +258,217 @@ rb_quotactl(int cmd, char *dev, VALUE vu }; #endif +#ifdef USE_NETBSD_QUOTA + +static struct quotahandle * +rb_quotaopen(char *dev) +{ + char *path; +#if defined(HAVE_SYS_STATVFS_H) && !defined(__DragonFly__) + struct statvfs *buff; +#else + struct statfs *buff; +#endif + int i, count; + + buff = 0; + path = dev; + count = getmntinfo(&buff, MNT_WAIT); + for( i=0; iqv_hardlimit = GetMemberU("bhardlimit"); + c_blocks->qv_softlimit = GetMemberU("bsoftlimit"); + c_blocks->qv_usage = GetMemberU("curblocks"); + c_blocks->qv_expiretime = GetMemberS("btimelimit"); + c_blocks->qv_grace = GetMemberS("bgrace"); + c_files->qv_hardlimit = GetMemberU("ihardlimit"); + c_files->qv_softlimit = GetMemberU("isoftlimit"); + c_files->qv_usage = GetMemberU("curinodes"); + c_files->qv_expiretime = GetMemberS("itimelimit"); + c_files->qv_grace = GetMemberS("igrace"); + +#undef GetMemberU +#undef GetMemberS +} + +VALUE +rb_diskquota_new(struct quotaval *c_blocks, struct quotaval *c_files) +{ + VALUE dqb; + + dqb = rb_struct_new(rb_sDiskQuota, + ULL2NUM(c_blocks->qv_hardlimit), + ULL2NUM(c_blocks->qv_softlimit), + ULL2NUM(c_blocks->qv_usage), + ULL2NUM(c_files->qv_hardlimit), + ULL2NUM(c_files->qv_softlimit), + ULL2NUM(c_files->qv_usage), + LL2NUM(c_blocks->qv_expiretime), + LL2NUM(c_files->qv_expiretime), +#if 0 /* not yet */ + LL2NUM(c_blocks->qv_grace), + LL2NUM(c_files->qv_grace), +#endif + 0); + return dqb; +} + +#else /* not USE_NETBSD_QUOTA */ + void rb_diskquota_get(VALUE dqb, struct dqblk * c_dqb) { VALUE v; +#if defined(USE_LINUX_QUOTA) && \ + (defined(USE_LINUX_QUOTA_24) || defined(USE_LINUX_QUOTA_26)) +#define GetMember(mem) \ + ((v = rb_struct_getmember(dqb,rb_intern(mem))) == Qnil) ? 0 : (NUM2ULL(v)) +#else #define GetMember(mem) \ ((v = rb_struct_getmember(dqb,rb_intern(mem))) == Qnil) ? 0 : (NUM2UINT(v)) +#endif #if defined(USE_LINUX_QUOTA) c_dqb->dqb_bhardlimit = GetMember("bhardlimit"); c_dqb->dqb_bsoftlimit = GetMember("bsoftlimit"); -#if !defined(USE_LINUX_QUOTA_24) +#if defined(USE_LINUX_QUOTA_24) || defined(USE_LINUX_QUOTA_26) + c_dqb->dqb_curspace = GetMember("curspace"); +#else c_dqb->dqb_curblocks = GetMember("curblocks"); #endif c_dqb->dqb_ihardlimit = GetMember("ihardlimit"); @@ -271,20 +504,29 @@ rb_diskquota_new(struct dqblk *c_dqb) VALUE dqb; #if defined(USE_LINUX_QUOTA) +#if defined(USE_LINUX_QUOTA_24) || defined(USE_LINUX_QUOTA_26) + dqb = rb_struct_new(rb_sDiskQuota, + ULL2NUM(c_dqb->dqb_bhardlimit), + ULL2NUM(c_dqb->dqb_bsoftlimit), + ULL2NUM(c_dqb->dqb_curspace), + ULL2NUM(c_dqb->dqb_ihardlimit), + ULL2NUM(c_dqb->dqb_isoftlimit), + ULL2NUM(c_dqb->dqb_curinodes), + ULL2NUM(c_dqb->dqb_btime), + ULL2NUM(c_dqb->dqb_itime), + 0); +#else dqb = rb_struct_new(rb_sDiskQuota, UINT2NUM(c_dqb->dqb_bhardlimit), UINT2NUM(c_dqb->dqb_bsoftlimit), -#if defined(USE_LINUX_QUOTA_24) - UINT2NUM(c_dqb->dqb_curspace), -#else UINT2NUM(c_dqb->dqb_curblocks), -#endif UINT2NUM(c_dqb->dqb_ihardlimit), UINT2NUM(c_dqb->dqb_isoftlimit), UINT2NUM(c_dqb->dqb_curinodes), UINT2NUM(c_dqb->dqb_btime), UINT2NUM(c_dqb->dqb_itime), 0); +#endif #elif defined(USE_BSD_QUOTA) dqb = rb_struct_new(rb_sDiskQuota, UINT2NUM(c_dqb->dqb_bhardlimit), @@ -296,7 +538,7 @@ rb_diskquota_new(struct dqblk *c_dqb) UINT2NUM(c_dqb->dqb_btime), UINT2NUM(c_dqb->dqb_itime), 0); -#elif defined(USE_SOLARIS) +#elif defined(USE_SOLARIS_QUOTA) dqb = rb_struct_new(rb_sDiskQuota, UINT2NUM(c_dqb->dqb_bhardlimit), UINT2NUM(c_dqb->dqb_bsoftlimit), @@ -311,18 +553,34 @@ rb_diskquota_new(struct dqblk *c_dqb) return dqb; }; +#endif /* USE_NETBSD_QUOTA */ + static VALUE rb_quota_getquota(VALUE self, VALUE dev, VALUE uid) { - char *c_dev = STR2CSTR(dev); + char *c_dev = StringValuePtr(dev); +#ifdef USE_NETBSD_QUOTA + struct quotaval c_blocks, c_files; +#else struct dqblk c_dqb; +#endif VALUE dqb = Qnil; +#ifdef USE_NETBSD_QUOTA + if( rb_quotaget(c_dev, uid, &c_blocks, &c_files) == -1 ){ + rb_sys_fail("quota_get"); + }; +#else if( rb_quotactl(Q_GETQUOTA,c_dev,uid,(caddr_t)(&c_dqb)) == -1 ){ rb_sys_fail("quotactl"); }; +#endif +#ifdef USE_NETBSD_QUOTA + dqb = rb_diskquota_new(&c_blocks, &c_files); +#else dqb = rb_diskquota_new(&c_dqb); +#endif return dqb; }; @@ -330,11 +588,17 @@ rb_quota_getquota(VALUE self, VALUE dev, VALUE rb_quota_quotaoff(VALUE self, VALUE dev) { - char *c_dev = STR2CSTR(dev); + char *c_dev = StringValuePtr(dev); +#ifdef USE_NETBSD_QUOTA + if( rb_quotaoff(c_dev) == -1 ){ + rb_sys_fail("quota_quotaoff"); + }; +#else if( rb_quotactl(Q_QUOTAOFF,c_dev,Qnil,NULL) == -1 ){ rb_sys_fail("quotactl"); }; +#endif return Qnil; }; @@ -342,12 +606,20 @@ rb_quota_quotaoff(VALUE self, VALUE dev) VALUE rb_quota_quotaon(VALUE self, VALUE dev, VALUE quotas) { - char *c_dev = STR2CSTR(dev); - char *c_quotas = STR2CSTR(quotas); + char *c_dev = StringValuePtr(dev); + char *c_quotas = StringValuePtr(quotas); +#ifdef USE_NETBSD_QUOTA + /* ignore the quota file names - they must be placed in /etc/fstab */ + (void)quotas; + if( rb_quotaon(c_dev) == -1 ){ + rb_sys_fail("quota_quotaon"); + }; +#else if( rb_quotactl(Q_QUOTAON,c_dev,Qnil,(caddr_t)c_quotas) == -1 ){ rb_sys_fail("quotactl"); }; +#endif return Qnil; }; @@ -355,14 +627,28 @@ rb_quota_quotaon(VALUE self, VALUE dev, VALUE rb_quota_setquota(VALUE self, VALUE dev, VALUE uid, VALUE dqb) { - char *c_dev = STR2CSTR(dev); + char *c_dev = StringValuePtr(dev); +#ifdef USE_NETBSD_QUOTA + struct quotaval c_qvb, c_qvf; +#else struct dqblk c_dqb; +#endif +#ifdef USE_NETBSD_QUOTA + rb_diskquota_get(dqb, &c_qvb, &c_qvf); +#else rb_diskquota_get(dqb, &c_dqb); +#endif +#ifdef USE_NETBSD_QUOTA + if( rb_quotaput(c_dev,uid,&c_qvb, &c_qvf) == -1 ){ + rb_sys_fail("quota_put"); + }; +#else if( rb_quotactl(Q_SETQUOTA,c_dev,uid,(caddr_t)(&c_dqb)) == -1 ){ rb_sys_fail("quotactl"); }; +#endif return Qnil; }; @@ -371,7 +657,7 @@ VALUE rb_quota_setqlim(VALUE self, VALUE dev, VALUE uid, VALUE dqb) { #ifdef Q_SETQLIM - char *c_dev = STR2CSTR(dev); + char *c_dev = StringValuePtr(dev); struct dqblk c_dqb; rb_diskquota_get(dqb, &c_dqb); @@ -392,18 +678,22 @@ rb_quota_setqlim(VALUE self, VALUE dev, VALUE rb_quota_sync(VALUE self, VALUE dev) { +#ifdef USE_NETBSD_QUOTA + /* nothing */ +#else char *c_dev; if( dev == Qnil ){ c_dev = NULL; } else{ - c_dev = STR2CSTR(dev); + c_dev = StringValuePtr(dev); }; if( rb_quotactl(Q_SYNC,c_dev,Qnil,NULL) == -1 ){ /* uid and addr are ignored */ rb_sys_fail("quotactl"); }; +#endif /* USE_NETBSD_QUOTA */ return Qnil; }; @@ -442,7 +732,7 @@ Init_quota() "curinodes", "btimelimit", "itimelimit", - 0); + NULL); /* for compatibility */ #define DQ_ALIAS(a,b) rb_alias(rb_sDiskQuota,rb_intern(#a),rb_intern(#b)) @@ -454,7 +744,7 @@ Init_quota() DQ_ALIAS(fsoftlimit=, isoftlimit=); DQ_ALIAS(curfiles=, curinodes=); DQ_ALIAS(ftimelimit=, itimelimit=); -#if defined(USE_LINUX_QUOTA_24) +#if defined(USE_LINUX_QUOTA_24) || defined(USE_LINUX_QUOTA_26) DQ_ALIAS(curspace, curblocks); DQ_ALIAS(curspace=, curblocks=); #endif