[comp.protocols.appletalk] aufs and NFS quotas, a quick patch...

mckay@COURAGEOUS.ECN.PURDUE.EDU (Dwight D McKay) (11/24/87)

	Kent W. England's article mentioned bring up AUFS on a Sun.  We've
done that here and had to make a couple minor alterations to make it work
correctly with regard to NFS quotas.  The diffs below patch afpos.c and
aufs.c to handle NFS quotas. They also include the last patch from Columbia
to fix "Access Privledges", we put both in at the same time.
	The NFS quotactl call unfortunately needs the ASCII string of the
special device to retrieve the quota info (ick).  To do this quickly we
build a table of special devices and device numbers at aufs startup time and
consult that table later when making quotactl calls.  We also default to
returning the entire disk's space numbers if the quotactl fails.
	The code is written my student programmer Ed Neiters.

--Dwight Mckay, ECN Workstation Software Support
[arpanet: mckay@ee.ecn.purdue.edu, usenet: ...ihnp4!pur-ee!mckay]
[Compu-serve: 75776,1521, office: EE 348B, phone: (317) 494-3561]

------------------------------ Cut Here -----------------------------------
*** /tmp/,RCSt1014052	Tue Nov 24 09:30:52 1987
--- afpos.c	Tue Nov 17 17:27:01 1987
***************
*** 1,7
  /*
!  * $Author: mckay $ $Date: 87/11/16 13:54:27 $
!  * $Header: /usr/src/ecn/cap/aufs/RCS/afpos.c,v 1.1 87/11/16 13:54:27 mckay Exp Locker: mckay $
!  * $Revision: 1.1 $
  */
  
  /*

--- 1,7 -----
  /*
!  * $Author: cck $ $Date: 87/08/25 14:44:00 $
!  * $Header: afpos.c,v 1.47 87/08/25 14:44:00 cck Rel $
!  * $Revision: 1.47 $
  */
  
  /*
***************
*** 51,56
  /* 	at Purdue, ECN.						*/
  #ifdef USEQUOTA
  #ifdef SUN
  # include <ufs/quota.h>
  #else
  # include <sys/quota.h>

--- 51,57 -----
  /* 	at Purdue, ECN.						*/
  #ifdef USEQUOTA
  #ifdef SUN
+ # include <sys/vfs.h>
  # include <ufs/quota.h>
  # include <fstab.h>
  #else
***************
*** 52,57
  #ifdef USEQUOTA
  #ifdef SUN
  # include <ufs/quota.h>
  #else
  # include <sys/quota.h>
  #endif

--- 53,59 -----
  #ifdef SUN
  # include <sys/vfs.h>
  # include <ufs/quota.h>
+ # include <fstab.h>
  #else
  # include <sys/quota.h>
  # include <sys/vfs.h>
***************
*** 54,59
  # include <ufs/quota.h>
  #else
  # include <sys/quota.h>
  #endif
  #endif
  

--- 56,62 -----
  # include <fstab.h>
  #else
  # include <sys/quota.h>
+ # include <sys/vfs.h>
  #endif
  #endif
  
***************
*** 111,116
  		   (I_EX << IS_GROUP) | \
  		   (I_EX << IS_WORLD))
  
  private char *usrnam,*usrdir;
  private int usruid;
  private int ngroups;

--- 114,125 -----
  		   (I_EX << IS_GROUP) | \
  		   (I_EX << IS_WORLD))
  
+ #ifdef SUN
+ struct table {
+ 	int device;
+ 	char path[16];
+ } spec_devices[32];
+ #endif
  private char *usrnam,*usrdir;
  private int usruid;
  private int ngroups;
***************
*** 141,146
  #define ItoEID(iid) ((sdword) (iid == 0 ? NOID : iid))
  #define EtoIID(eid) ((int) (eid == NOID ? 0 : eid))
  
  /*
   *
   * OSErr OSMapID(byte fcn,char *name,dword id)

--- 150,156 -----
  #define ItoEID(iid) ((sdword) (iid == 0 ? NOID : iid))
  #define EtoIID(eid) ((int) (eid == NOID ? 0 : eid))
  
+ #ifdef SUN
  /*
   *  build_table will build a table of the special device pathnames-
   *  available from fstab(5)- and the corresponding device inode-
***************
*** 142,147
  #define EtoIID(eid) ((int) (eid == NOID ? 0 : eid))
  
  /*
   *
   * OSErr OSMapID(byte fcn,char *name,dword id)
   *

--- 152,206 -----
  
  #ifdef SUN
  /*
+  *  build_table will build a table of the special device pathnames-
+  *  available from fstab(5)- and the corresponding device inode-
+  *  available from stat(2).  --ejn 11/15/87
+  */
+ 
+ build_table()
+ {
+ struct fstab *devtable;
+ struct stat buf;
+ int size=0;
+ 	
+ 	while((devtable = getfsent()) != NULL) {
+ 		stat(devtable->fs_spec, &buf);
+ 		spec_devices[size].device = buf.st_rdev;
+ 		strcpy(spec_devices[size++].path,devtable->fs_spec);
+ 	}
+ 	if (size)
+ 		log("spec_devices table has been built.\n");
+ 	else log("a zero sized spec_devices table is a bad thing.\n");
+ 		/* put in an End Of Table mark */
+ 	strcpy(spec_devices[size++].path, "");
+ 	return(size);
+ }
+ 
+ /*
+  * find_spec returns a pointer to the null_terminated string
+  * containing the path name of the block special device specified
+  * by the minor device number passed as it's argument; ie. the
+  * st_rdev field of stat(2).
+  */
+ 
+ char *find_spec(device)
+ dev_t device;
+ {
+ int i=0;
+ 
+ 	while(spec_devices[i].path != "") {
+ 		if(spec_devices[i].device == device) {
+ 			return(spec_devices[i].path);
+ 		}
+ 		i++;
+ 	}
+ 	/* problems */
+ 	log("device %d not found in spec_devices table.",device);
+ 	return("");
+ }
+ #endif
+ 
+ /*
   *
   * OSErr OSMapID(byte fcn,char *name,dword id)
   *
***************
*** 1444,1449
    struct fs_data buffer[NUMGETMNTBUF];
    int nbytes = sizeof(struct fs_data)*NUMGETMNTBUF;
  #endif
    time_t sometime;
  
    if (stat(path,&buf) != 0)	/* directory exists? */

--- 1503,1512 -----
    struct fs_data buffer[NUMGETMNTBUF];
    int nbytes = sizeof(struct fs_data)*NUMGETMNTBUF;
  #endif
+ #ifdef SUN
+ char *find_spec();
+ struct statfs fsbuf;
+ #endif
    time_t sometime;
  
    if (stat(path,&buf) != 0)	/* directory exists? */
***************
*** 1495,1501
  /* define more than one then you must define in order you wish */
  #ifdef USEQUOTA
  /* put in to allow compiliation on Suns here at ECN, Purdue */
! /* by Ed Nieters			*/
  #ifndef SUN
    if (quota(Q_GETDLIM, getuid(), buf.st_dev, &dqblk) == 0 &&
        dqblk.dqb_bhardlimit != 0) { /* make sure not unlimited */

--- 1558,1564 -----
  /* define more than one then you must define in order you wish */
  #ifdef USEQUOTA
  /* put in to allow compiliation on Suns here at ECN, Purdue */
! /* Ed Nieters   11/10/87			*/
  #ifndef SUN
    if (quota(Q_GETDLIM, getuid(), buf.st_dev, &dqblk) == 0 &&
        dqblk.dqb_bhardlimit != 0) { /* make sure not unlimited */
***************
*** 1501,1507
        dqblk.dqb_bhardlimit != 0) { /* make sure not unlimited */
  #else
  /*  if (quotactl(Q_GETQUOTA, getuid(), buf.st_dev, &dqblk) == 0 &&  */
!   if (quotactl(Q_GETQUOTA, buf.st_dev, getuid(), &dqblk) == 0 &&
        dqblk.dqb_bhardlimit != 0) { /* make sure not unlimited */
  #endif
      v->v_size = dqblk.dqb_bhardlimit*512;

--- 1564,1570 -----
        dqblk.dqb_bhardlimit != 0) { /* make sure not unlimited */
  #else
  /*  if (quotactl(Q_GETQUOTA, getuid(), buf.st_dev, &dqblk) == 0 &&  */
!   if (quotactl(Q_GETQUOTA, find_spec(buf.st_dev), getuid(), &dqblk) == 0 &&
        dqblk.dqb_bhardlimit != 0) { /* make sure not unlimited */
  #endif
      v->v_size = dqblk.dqb_bhardlimit*512;
***************
*** 1507,1512
      v->v_size = dqblk.dqb_bhardlimit*512;
      v->v_free = (dqblk.dqb_bhardlimit-dqblk.dqb_curblocks)*512;
      return(noErr);
    }
  #endif
  #ifdef USEGETMNT

--- 1570,1579 -----
      v->v_size = dqblk.dqb_bhardlimit*512;
      v->v_free = (dqblk.dqb_bhardlimit-dqblk.dqb_curblocks)*512;
      return(noErr);
+   } else if (statfs(path, &fsbuf) >= 0) {
+     v->v_size = fsbuf.f_bsize * fsbuf.f_blocks;
+     v->v_free = fsbuf.f_bsize * fsbuf.f_bavail;
+     return(noErr);
    }
  #endif
  #ifdef USEGETMNT
***************
*** 2196,2201
    char gid[20];			/* big enough */
    int pid, npid;
    int status;
    if (DBOSI) 
      printf("unix_chown: Attempting chown %s to owner %d, group %d\n",
  	   path,own,grp);

--- 2263,2273 -----
    char gid[20];			/* big enough */
    int pid, npid;
    int status;
+ #ifndef USECHOWN
+   struct stat stb;
+   OSErr err;
+ #endif
+ 
    if (DBOSI) 
      printf("unix_chown: Attempting chown %s to owner %d, group %d\n",
  	   path,own,grp);
***************
*** 2203,2208
    if (usruid != 0) {		/* not root, then do it hard way */
      if (DBOSI) 
        printf("unix_chown: skipping owern, chgrp %s to group %d\n",path,grp);
      sprintf(gid, "%d",grp);
      if ((pid=vfork()) == 0) {
        execl("/bin/chgrp","chgrp",gid,path, 0);

--- 2275,2284 -----
    if (usruid != 0) {		/* not root, then do it hard way */
      if (DBOSI) 
        printf("unix_chown: skipping owern, chgrp %s to group %d\n",path,grp);
+     if ((err = unix_stat(path, &stb)) != noErr)
+       return(err);
+     if (stb.st_gid == grp)	/* naught to do */
+       return(noErr);
      sprintf(gid, "%d",grp);
      if ((pid=vfork()) == 0) {
        execl("/bin/chgrp","chgrp",gid,path, 0);