Subject: Quota magic cookies

From: Eilon Gishri <[email-masked]>
Date: Thu, 23 May 1996 23:43:25 +0300 (IDT)

Here is the code with the mapping of the magic cookies.

Forgive me for being lazy...

struct	dqblk {
%B	u_long	dqb_bhardlimit;	/* absolute limit on disk blks alloc */
%b	u_long	dqb_bsoftlimit;	/* preferred limit on disk blks */
%Q	u_long	dqb_curblocks;	/* current block count */
%I	u_long	dqb_ihardlimit;	/* maximum # allocated inodes + 1 */
%i	u_long	dqb_isoftlimit;	/* preferred inode limit */
%q	u_long	dqb_curinodes;	/* current # allocated inodes */
%H	time_t	dqb_btime;	/* time limit for excessive disk use */
%h	time_t	dqb_itime;	/* time limit for excessive files */
};

diff -u -r --new-file wu-ftpd-2.4.2-beta-10.old/src/config/config.aix wu-ftpd-2.4.2-beta-10/src/config/config.aix
--- wu-ftpd-2.4.2-beta-10.old/src/config/config.aix	Tue Dec  5 06:31:28 1995
+++ wu-ftpd-2.4.2-beta-10/src/config/config.aix	Thu May 23 17:48:46 1996
@@ -34,3 +34,7 @@
 typedef void	SIGNAL_TYPE;
 
 #include "../config.h"
+
+#define VIRTUAL
+#define QUOTA
+#define CANT_BIND
diff -u -r --new-file wu-ftpd-2.4.2-beta-10.old/src/extensions.c wu-ftpd-2.4.2-beta-10/src/extensions.c
--- wu-ftpd-2.4.2-beta-10.old/src/extensions.c	Sat Mar 16 07:00:08 1996
+++ wu-ftpd-2.4.2-beta-10/src/extensions.c	Thu May 23 18:31:42 1996
@@ -63,6 +63,16 @@
 #include "extensions.h"
 #include "support/ftw.h"
 
+#ifdef QUOTA
+struct dqblk quota;
+char
+#ifdef __STDC__
+*time_quota(long curstate, long softlimit, long timelimit);
+#else
+*time_quota();
+#endif
+#endif /* QUOTA */
+
 #ifdef HAVE_REGEX_H
 #include <regex.h>
 #endif
@@ -184,6 +194,9 @@
 {
     char *inptr = inbuf;
     char *outptr = outbuf;
+#ifdef QUOTA
+    char *timeleft;
+#endif
     char buffer[MAXPATHLEN];
     time_t curtime;
     int limit;
@@ -264,6 +277,44 @@
                 *(outptr + 24) = '\0';
                 break;
 
+#ifdef QUOTA		/* eilon : cookies for quota */
+            case 'B':
+                sprintf(outptr, "%d", quota.dqb_bhardlimit);
+                break;
+
+            case 'b':
+                sprintf(outptr, "%d", quota.dqb_bsoftlimit);
+                break;
+
+            case 'Q':
+                sprintf(outptr, "%d", quota.dqb_curblocks);
+                break;
+
+            case 'I':
+                sprintf(outptr, "%d", quota.dqb_ihardlimit);
+                break;
+
+            case 'i':
+                sprintf(outptr, "%d", quota.dqb_isoftlimit);
+                break;
+
+            case 'q':
+                sprintf(outptr, "%d", quota.dqb_curinodes);
+                break;
+
+            case 'H':
+                timeleft = time_quota(quota.dqb_curblocks,quota.dqb_bsoftlimit,
+				quota.dqb_btime);
+                strcpy(outptr, timeleft);
+                break;
+
+            case 'h':
+                timeleft = time_quota(quota.dqb_curinodes,quota.dqb_isoftlimit,
+				quota.dqb_itime);
+                strcpy(outptr, timeleft);
+                break;
+#endif /* QUOTA */
+
             case '%':
                 *outptr++ = '%';
                 *outptr = '\0';
@@ -1152,7 +1203,80 @@
    return 0;
 }
 
+#ifdef QUOTA
+void
+#ifdef __STDC__
+get_quota(char *fs,int uid)
+#else
+get_quota(fs, uid)
+char *fs;
+int uid;
+#endif
+{
+#ifdef AIX
+  if(quotactl(fs,QCMD(Q_GETQUOTA,USRQUOTA),uid,&quota))
+#else
+  if(quotactl(Q_GETQUOTA,fs,uid,&quota))
+#endif
+     syslog(LOG_WARNING, "quotactl (Q_GETQUOTA): %m");
+}
 
+char
+#ifdef __STDC__
+*time_quota(long curstate, long softlimit, long timelimit)
+#else
+*time_quota(curstate, softlimit, timelimit)
+long curstate, softlimit, timelimit;
+#endif
+{
+	struct timeval tv;
+	char timeleft[80];
 
+	gettimeofday(&tv, NULL);
+	if (softlimit && curstate >= softlimit) {
+		if (timelimit == 0) {
+			strcpy(timeleft, "NOT STARTED");
+		} else if (timelimit > tv.tv_sec) {
+			fmttime(timeleft, timelimit - tv.tv_sec);
+		} else {
+			strcpy(timeleft, "EXPIRED");
+		}
+	} else {
+		timeleft[0] = '\0';
+	}
+	return(timeleft);
+}
 
-
+void
+#ifdef __STDC__
+fmttime(char *buf, register long time)
+#else
+fmttime(buf, time)
+	char *buf;
+	register long time;
+#endif
+{
+	int i;
+	static struct {
+		int c_secs;		/* conversion units in secs */
+		char * c_str;		/* unit string */
+	} cunits [] = {
+		{60*60*24*28, "months"},
+		{60*60*24*7, "weeks"},
+		{60*60*24, "days"},
+		{60*60, "hours"},
+		{60, "mins"},
+		{1, "secs"}
+	};
+
+	if (time <= 0) {
+		strcpy(buf, "EXPIRED");
+		return;
+	}
+	for (i = 0; i < sizeof(cunits)/sizeof(cunits[0]); i++) {
+		if (time >= cunits[i].c_secs)
+			break;
+	}
+	sprintf(buf, "%.1f %s", (double)time/cunits[i].c_secs, cunits[i].c_str);
+}
+#endif /* QUOTA */
diff -u -r --new-file wu-ftpd-2.4.2-beta-10.old/src/extensions.h wu-ftpd-2.4.2-beta-10/src/extensions.h
--- wu-ftpd-2.4.2-beta-10.old/src/extensions.h	Fri Apr  1 22:03:40 1994
+++ wu-ftpd-2.4.2-beta-10/src/extensions.h	Thu May 23 17:48:45 1996
@@ -44,3 +44,16 @@
 #define ARG8    entry->arg[8]
 #define ARG9    entry->arg[9]
 #define ARG     entry->arg
+
+#ifdef QUOTA
+#include<sys/time.h>
+#ifdef IRIX
+#include<sys/quota.h>
+#endif
+#ifdef SUNOS
+#include<ufs/quota.h>
+#endif
+#ifdef AIX
+#include<jfs/quota.h>
+#endif
+#endif /* QUOTA */
diff -u -r --new-file wu-ftpd-2.4.2-beta-10.old/src/ftpd.c wu-ftpd-2.4.2-beta-10/src/ftpd.c
--- wu-ftpd-2.4.2-beta-10.old/src/ftpd.c	Sat Mar 16 07:00:09 1996
+++ wu-ftpd-2.4.2-beta-10/src/ftpd.c	Thu May 23 17:48:45 1996
@@ -211,6 +211,10 @@
 char virtual_logfile[MAXPATHLEN];
 #endif
 
+#ifdef QUOTA
+extern struct dqblk quota;
+#endif
+
 int data;
 jmp_buf errcatch,
   urgcatch;
@@ -1418,10 +1422,13 @@
         /* We MUST do a chdir() after the chroot. Otherwise the old current
          * directory will be accessible as "." outside the new root! */
 #ifdef VIRTUAL
-      if (virtual_mode) {
+      if (virtual_mode && !guest) {
         strcpy(pw->pw_dir, virtual_root);
       }
 #endif 
+#ifdef QUOTA
+	get_quota(pw->pw_dir,pw->pw_uid);
+#endif
         if (anonymous) {
             if (chroot(pw->pw_dir) < 0 || chdir("/") < 0) {
                 reply(550, "Can't set guest privileges.");
@@ -2072,6 +2079,11 @@
     /* anchor socket to avoid multi-homing problems */
     data_source.sin_family = AF_INET;
     data_source.sin_addr = ctrl_addr.sin_addr;
+
+#if defined(VIRTUAL) && defined(CANT_BIND) /* can't bind to virtual address */
+    data_source.sin_addr.s_addr = htonl(INADDR_ANY);
+#endif 
+
     for (tries = 1;; tries++) {
         if (bind(s, (struct sockaddr *) &data_source,
                  sizeof(data_source)) >= 0)

-- 
		Eilon Gishri, Tel-Aviv University Computation Center
		Home 03-5078671
		E-mail: [email-masked]