Patch #: 63 Type: operational change Priority: none Modification: improve AUFS group membership handling Modification: continue crusade against #ifdef labels Submitted: Edward Moy Submitted: David Hornsby Archived: munnari.OZ.AU mac/cap.patches/cap60.patch063 Application: 'cd cap60; patch -p < cap60.patches/cap60.patch063' Summary: change internal/external user/group ID mapping Summary: reset file permissions, groups on directory change Summary: allow group change via chown(2), rather than exec chgrp File: cap60/applications/aufs/afpos.c *** applications/aufs/afpos.c.orig Sun Sep 22 01:44:55 1991 --- applications/aufs/afpos.c Sun Nov 17 16:07:57 1991 *************** *** 1,7 **** /* ! * $Author: djh $ $Date: 1991/09/21 15:44:39 $ ! * $Header: /mac/src/cap60/applications/aufs/RCS/afpos.c,v 2.13 1991/09/21 15:44:39 djh Rel djh $ ! * $Revision: 2.13 $ */ /* --- 1,7 ---- /* ! * $Author: djh $ $Date: 1991/11/17 05:07:19 $ ! * $Header: /mac/src/cap60/applications/aufs/RCS/afpos.c,v 2.14 1991/11/17 05:07:19 djh Rel djh $ ! * $Revision: 2.14 $ */ /* *************** *** 100,107 **** #ifdef USESUNQUOTA # ifndef USEQUOTA # define USEQUOTA ! # endif ! #endif #ifdef APPLICATION_MANAGER # define NEEDFCNTLDOTH --- 100,107 ---- #ifdef USESUNQUOTA # ifndef USEQUOTA # define USEQUOTA ! # endif USEQUOTA ! #endif USESUNQUOTA #ifdef APPLICATION_MANAGER # define NEEDFCNTLDOTH *************** *** 109,128 **** #ifdef NEEDFCNTLDOTH # include ! #endif #ifdef USESTRINGDOTH # include ! #else # include ! #endif #ifdef USEUSTAT # include ! #endif #ifdef USESTATFS # include ! #endif #ifdef AIX #include --- 109,128 ---- #ifdef NEEDFCNTLDOTH # include ! #endif NEEDFCNTLDOTH #ifdef USESTRINGDOTH # include ! #else USESTRINGDOTH # include ! #endif USESTRINGDOTH #ifdef USEUSTAT # include ! #endif USEUSTAT #ifdef USESTATFS # include ! #endif USESTATFS #ifdef AIX #include *************** *** 139,156 **** /* NOTE: If there is not sys/quota.h and there is a ufs/quota.h */ /* then you should probably define SUN_QUOTA -- especially if your */ /* NFS is based on the sun model */ ! # else # include # include ! # endif # ifndef Q_GETDLIM # ifdef Q_GETQUOTA # define Q_GETDLIM Q_GETQUOTA ! # else /* You have turned on quotas and aren't using the bsd or sun quota system */ ! # endif /*Q_GETQUOTA*/ ! # endif /* Q_GETDLIM */ ! #endif /* USEQUOTA */ /* assumes that ultrix 1.1 doesn't have getmnt or if it does, then it */ /* has limits.h and uname */ --- 139,156 ---- /* NOTE: If there is not sys/quota.h and there is a ufs/quota.h */ /* then you should probably define SUN_QUOTA -- especially if your */ /* NFS is based on the sun model */ ! # else USESUNQUOTA # include # include ! # endif USESUNQUOTA # ifndef Q_GETDLIM # ifdef Q_GETQUOTA # define Q_GETDLIM Q_GETQUOTA ! # else Q_GETQUOTA /* You have turned on quotas and aren't using the bsd or sun quota system */ ! # endif Q_GETQUOTA ! # endif Q_GETDLIM ! #endif USEQUOTA /* assumes that ultrix 1.1 doesn't have getmnt or if it does, then it */ /* has limits.h and uname */ *************** *** 161,167 **** /* vendor :-) */ # include # include ! #endif #include #include /* flags should be in misc */ --- 161,167 ---- /* vendor :-) */ # include # include ! #endif USEGETMNT #include #include /* flags should be in misc */ *************** *** 189,201 **** #ifdef MAXBSIZE # define IOBSIZE MAXBSIZE /* set to max buf entry size by if there */ ! #else # ifdef BLKDEV_IOSIZE # define IOBSIZE BLKDEV_IOSIZE /* set to std block device read size */ ! # else # define IOBSIZE BUFSIZ /* use stdio bufsiz */ ! # endif ! #endif #define NILPWD ((struct passwd *) 0) --- 189,201 ---- #ifdef MAXBSIZE # define IOBSIZE MAXBSIZE /* set to max buf entry size by if there */ ! #else MAXBSIZE # ifdef BLKDEV_IOSIZE # define IOBSIZE BLKDEV_IOSIZE /* set to std block device read size */ ! # else BLKDEV_IOSIZE # define IOBSIZE BUFSIZ /* use stdio bufsiz */ ! # endif BLKDEV_IOSIZE ! #endif MAXBSIZE #define NILPWD ((struct passwd *) 0) *************** *** 207,212 **** --- 207,215 ---- #define E_IOWN 0x80000000 /* owner of file */ + #define I_SETUID 04000 /* internal set user ID */ + #define I_SETGID 02000 /* internal set group ID */ + #define I_RD 04 /* Internal (Unix) bits for read */ #define I_WR 02 /* write */ #define I_EX 01 /* execute (search) */ *************** *** 237,243 **** private int ngroups; #ifndef GGTYPE # define GGTYPE int ! #endif private GGTYPE groups[NGROUPS+1]; #ifdef USEGETMNT # ifndef NOSTAT_ONE --- 240,246 ---- private int ngroups; #ifndef GGTYPE # define GGTYPE int ! #endif GGTYPE private GGTYPE groups[NGROUPS+1]; #ifdef USEGETMNT # ifndef NOSTAT_ONE *************** *** 247,255 **** /* a compile from ultrix 2.0 from working on 2.2 */ # define NOSTAT_ONE 4 /* as of ultrix 2.2 */ # define ISOLDGETMNT 1 ! # else # define ISOLDGETMNT 0 ! # endif private int oldgetmnt = ISOLDGETMNT; /* use new or old format getmnt */ /* default is based on compiling system */ # ifndef NUMGETMNTBUF --- 250,258 ---- /* a compile from ultrix 2.0 from working on 2.2 */ # define NOSTAT_ONE 4 /* as of ultrix 2.2 */ # define ISOLDGETMNT 1 ! # else NOSTAT_ONE # define ISOLDGETMNT 0 ! # endif NOSTAT_ONE private int oldgetmnt = ISOLDGETMNT; /* use new or old format getmnt */ /* default is based on compiling system */ # ifndef NUMGETMNTBUF *************** *** 257,264 **** /* because on systems with many file */ /* systems we will get killed with 8 */ /* Back off!!!!! struct fs_data is huge */ ! # endif ! #endif import int errno; --- 260,267 ---- /* because on systems with many file */ /* systems we will get killed with 8 */ /* Back off!!!!! struct fs_data is huge */ ! # endif NUMGETMNTBUF ! #endif USEGETMNT import int errno; *************** *** 298,304 **** export OSErr OSSetDirParms(); export OSErr OSSetForklen(); private OSErr os_chmod(); ! private void os_chmod_all(); private u_short EtoIPriv(); private int OSInGroup(); private u_short EtoIAccess(); --- 301,307 ---- export OSErr OSSetDirParms(); export OSErr OSSetForklen(); private OSErr os_chmod(); ! private void os_change_all(); private u_short EtoIPriv(); private int OSInGroup(); private u_short EtoIAccess(); *************** *** 356,362 **** { #ifdef USEGETMNT struct utsname unames; ! #endif #ifdef USEGETMNT if (uname(&unames) >= 0) { --- 359,365 ---- { #ifdef USEGETMNT struct utsname unames; ! #endif USEGETMNT #ifdef USEGETMNT if (uname(&unames) >= 0) { *************** *** 370,385 **** } else oldgetmnt = FALSE; } } ! #endif /* USEGETMNT */ #ifdef aux /* ensure reliable signals, etc */ #define BSDCOMPAT COMPAT_BSDNBIO|COMPAT_BSDPROT|COMPAT_BSDSIGNALS|\ COMPAT_BSDTTY|COMPAT_EXEC|COMPAT_SYSCALLS setcompat(BSDCOMPAT); ! #endif #ifdef USESUNQUOTA build_mount_table(); ! #endif } void --- 373,388 ---- } else oldgetmnt = FALSE; } } ! #endif USEGETMNT #ifdef aux /* ensure reliable signals, etc */ #define BSDCOMPAT COMPAT_BSDNBIO|COMPAT_BSDPROT|COMPAT_BSDSIGNALS|\ COMPAT_BSDTTY|COMPAT_EXEC|COMPAT_SYSCALLS setcompat(BSDCOMPAT); ! #endif aux #ifdef USESUNQUOTA build_mount_table(); ! #endif USESUNQUOTA } void *************** *** 396,422 **** logit(0," Configured: LOCKF"); #ifdef USEUSTAT logit(0," Configured: Volume space information: ustat"); ! #endif #ifdef USESTATFS logit(0," Configured: Volume space information: statfs"); ! #endif #ifdef USEGETMNT logit(0," Configured: Volume space information: getmnt"); if (oldgetmnt) logit(0," using old style (Ultrix 1.2, 2.0) getmnt"); ! #endif #ifdef USESUNQUOTA logit(0," Configured: SUN quota system"); ! #endif #ifndef USESUNQUOTA /* sunquota turns on usequota */ # ifdef USEQUOTA logit(0," Configured: Melbourne (BSD) quota system"); ! # endif ! #endif #ifdef USECHOWN logit(0," Configured: chown: system allows one to give away ownership of files"); ! #endif if (os_issmartunixfi()) logit(0," Configured: reading unknown unix files to get finder information"); logit(0," Configured translation tables are:"); --- 399,425 ---- logit(0," Configured: LOCKF"); #ifdef USEUSTAT logit(0," Configured: Volume space information: ustat"); ! #endif USEUSTAT #ifdef USESTATFS logit(0," Configured: Volume space information: statfs"); ! #endif USESTATFS #ifdef USEGETMNT logit(0," Configured: Volume space information: getmnt"); if (oldgetmnt) logit(0," using old style (Ultrix 1.2, 2.0) getmnt"); ! #endif USEGETMNT #ifdef USESUNQUOTA logit(0," Configured: SUN quota system"); ! #endif USESUNQUOTA #ifndef USESUNQUOTA /* sunquota turns on usequota */ # ifdef USEQUOTA logit(0," Configured: Melbourne (BSD) quota system"); ! # endif USEQUOTA ! #endif USESUNQUOTA #ifdef USECHOWN logit(0," Configured: chown: system allows one to give away ownership of files"); ! #endif USECHOWN if (os_issmartunixfi()) logit(0," Configured: reading unknown unix files to get finder information"); logit(0," Configured translation tables are:"); *************** *** 434,444 **** * */ ! #define NOID (-1) /* unused internal group/user id */ ! #define ItoEID(iid) ((sdword) (iid == 0 ? NOID : iid)) ! #define EtoIID(eid) ((int) (eid == NOID ? 0 : eid)) /* * * OSErr OSMapID(byte fcn,char *name,dword id) --- 437,455 ---- * */ ! #define NOID (-1) /* internal group/user id for */ ! /* ! * Make external and internal ids differ by one. Then 1 (administrator) ! * maps to 0 (root), and 0 (any user or group) maps to -1. Thus the ! * AFP client thinks user ids are 1 higher than what the server (and the ! * unix machine) use internally. ! * ! */ + #define ItoEID(iid) ((sdword) (iid + 1)) + #define EtoIID(eid) ((int) (eid - 1)) + /* * * OSErr OSMapID(byte fcn,char *name,dword id) *************** *** 475,495 **** printf("OSMapID fcn=%s id=%d\n", ((fcn == MapID_C) ? "Creator" : "Group"),id); switch (fcn) { case MapID_C: pwd = getpwuid(id); if (pwd == NULL) ! sprintf(name,"%08d",id); ! else ! strcpy(name,pwd->pw_name); break; case MapID_G: grp = getgrgid(id); if (grp == NULL) ! sprintf(name,"%08d",id); ! else ! strcpy(name,grp->gr_name); break; default: return(aeParamErr); --- 486,509 ---- printf("OSMapID fcn=%s id=%d\n", ((fcn == MapID_C) ? "Creator" : "Group"),id); + if (idd == 0) { + name[0] = '\0'; + return(noErr); + } + switch (fcn) { case MapID_C: pwd = getpwuid(id); if (pwd == NULL) ! return(aeItemNotFound); ! strcpy(name,pwd->pw_name); break; case MapID_G: grp = getgrgid(id); if (grp == NULL) ! return(aeItemNotFound); ! strcpy(name,grp->gr_name); break; default: return(aeParamErr); *************** *** 531,536 **** --- 545,555 ---- printf("OSMapName fcn=%s name=%s\n", (fcn == MapName_C) ? "Creator" : "Group",name); + if (name[0] == '\0') { + *eid = 0; + return(noErr); + } + switch (fcn) { case MapName_C: pwd = getpwnam(name); *************** *** 567,579 **** struct passwd *pwd; if (!doself) { ! if ((pwd = (struct passwd *)getpwuid(userid)) == NULL) return(aeItemNotFound); usr = pwd->pw_uid; grp = pwd->pw_gid; } ! guirp->guir_userid = usr; ! guirp->guir_pgroup = grp; return(noErr); } --- 586,599 ---- struct passwd *pwd; if (!doself) { ! if ((pwd = (struct passwd *)getpwuid(EtoIID(userid))) == NULL) return(aeItemNotFound); usr = pwd->pw_uid; grp = pwd->pw_gid; } ! /* Convert to external form */ ! guirp->guir_userid = ItoEID(usr); ! guirp->guir_pgroup = ItoEID(grp); return(noErr); } *************** *** 889,895 **** return(err); /* then give up */ if (!S_ISDIR(stb.st_mode)) { /* directories have no rsrc fork */ ! unix_chmod(tpath, mo); /* file: try to reset protection */ if (fpdir->flags & DID_RESOURCE) { strcpy(fpath, f_path); strcpy(tpath, t_path); --- 909,915 ---- return(err); /* then give up */ if (!S_ISDIR(stb.st_mode)) { /* directories have no rsrc fork */ ! unix_chmod(t_path, mo); /* file: try to reset protection */ if (fpdir->flags & DID_RESOURCE) { strcpy(fpath, f_path); strcpy(tpath, t_path); *************** *** 1716,1727 **** if ((err = unix_chown(p_ath,own,grp)) != noErr) return(err); #endif NOCASEMATCH ! strcpy(path,p_ath); ! toResFork(path,fn); if ((err = unix_chown(path,own,grp)) != noErr && err != aeObjectNotFound) return(err); ! strcpy(path,p_ath); ! toFinderInfo(path,fn); if ((err = unix_chown(path,own,grp)) != noErr && err != aeObjectNotFound) return(err); EModified(ipdir); --- 1736,1745 ---- if ((err = unix_chown(p_ath,own,grp)) != noErr) return(err); #endif NOCASEMATCH ! strcpy(path,p_ath); strcat(path,RFDIR); if ((err = unix_chown(path,own,grp)) != noErr && err != aeObjectNotFound) return(err); ! strcpy(path,p_ath); strcat(path,FIDIR); if ((err = unix_chown(path,own,grp)) != noErr && err != aeObjectNotFound) return(err); EModified(ipdir); *************** *** 1728,1745 **** } if (fdp->fdp_dbitmap & DP_ACCES) { ! u_short acc = EtoIAccess(dp->dp_accright); ! if ((err = os_chmod(ipdir,fn,acc,F_DATA)) != noErr) return(err); ! os_chmod_all(ipdir, fn, acc, F_DATA); /* change all file protections */ ! os_chmod_all(ipdir, fn, acc, F_RSRC); ! os_chmod_all(ipdir, fn, acc, F_FNDR); if ((err = os_chmod(ipdir,fn,acc,F_RSRC)) != noErr && ! err != aeObjectNotFound) return(err); if ((err = os_chmod(ipdir,fn,acc,F_FNDR)) != noErr && ! err != aeObjectNotFound) return(err); } return(noErr); --- 1746,1781 ---- } if (fdp->fdp_dbitmap & DP_ACCES) { ! u_short acc, accd; ! acc = accd = EtoIAccess(dp->dp_accright); ! #ifdef USEDIRSETGID ! if (grp != usrgid) ! accd |= I_SETGID; ! #endif USEDIRSETGID ! if ((err = os_chmod(ipdir,fn,accd,F_DATA)) != noErr) return(err); ! ! /* change all file protections, owner & group */ ! os_change_all(ipdir, fn, acc, own, grp, F_DATA); ! os_change_all(ipdir, fn, acc, own, grp, F_RSRC); ! os_change_all(ipdir, fn, acc, own, grp, F_FNDR); ! ! OSfname(p_ath,ipdir,fn,F_DATA); ! /* change our .resource DIRECTORY */ ! strcpy(path,p_ath); strcat(path,RFDIR); ! unix_chmod(path,accd); ! /* change our .finderinfo DIRECTORY */ ! strcpy(path,p_ath); strcat(path,FIDIR); ! unix_chmod(path,accd); ! ! /* change our .resource FILE */ if ((err = os_chmod(ipdir,fn,acc,F_RSRC)) != noErr && ! err != aeObjectNotFound) return(err); + /* change our .finderinfo FILE */ if ((err = os_chmod(ipdir,fn,acc,F_FNDR)) != noErr && ! err != aeObjectNotFound) return(err); } return(noErr); *************** *** 1809,1815 **** } /* ! * Change file protection for all files in directory * * Have to do because: * unix has file protection and AFP does not, change the protection --- 1845,1851 ---- } /* ! * Change file protection, owner & group for all files in directory * * Have to do because: * unix has file protection and AFP does not, change the protection *************** *** 1820,1830 **** * */ private void ! os_chmod_all(idir,fn,mode,typ) IDirP idir; char *fn; u_short mode; ! int typ; { char path[MAXPATHLEN]; struct stat stb; --- 1856,1866 ---- * */ private void ! os_change_all(idir,fn,mode,own,grp,typ) IDirP idir; char *fn; u_short mode; ! int own, grp, typ; { char path[MAXPATHLEN]; struct stat stb; *************** *** 1874,1893 **** printf("os_chmod: stat failed for %s\n",path); continue; /* some error... */ } ! if (S_ISDIR(stb.st_mode)) { ! if (dp->d_name[0] != '.') continue; - /* was . or .. */ - if (dp->d_name[1] == '\0' || - (dp->d_name[1] == '.' && dp->d_name[2] == '\0')) - continue; /* skip it */ - /* if not .resource or .finderinfo then skip */ - if (typ != F_DATA && - strcmp(dp->d_name,RFDIRFN) != 0 && strcmp(dp->d_name, FIDIRFN) != 0) - continue; - } - err = unix_chmod(path,mode); /* set the mode for this file */ /* ignore errors */ } closedir(dirp); /* close the directory */ } --- 1910,1920 ---- printf("os_chmod: stat failed for %s\n",path); continue; /* some error... */ } ! if (S_ISDIR(stb.st_mode)) continue; /* ignore errors */ + unix_chmod(path,mode); /* set the mode for this file */ + unix_chown(path,own,grp); /* set owner and group for file */ } closedir(dirp); /* close the directory */ } *************** *** 1982,1987 **** --- 2009,2015 ---- if (DBOSI) printf("EtoIAccess: E=0x%x, I=o%o\n",emode,imode); + return(imode); } *************** *** 2007,2020 **** { dword e = 0; ! if (usruid == 0) /* root? */ ! e |= ((E_RD|E_WR|E_SR)< */ + e |= E_IOWN; /* must set owner bit */ + + /* set owner, group and world bytes */ + e |= (ItoEPriv(imode,IS_OWNER,ES_OWNER) | /* other access */ ItoEPriv(imode,IS_GROUP,ES_GROUP) | ItoEPriv(imode,IS_WORLD,ES_WORLD)); *************** *** 2021,2026 **** --- 2060,2066 ---- if (DBOSI) printf("ItoEAccess: I=o%o, E=0x%x\n",imode,e); + return(e); } *************** *** 3401,3406 **** --- 3441,3452 ---- return(ItoEErr(errno)); } + #ifdef NOCHGRPEXEC + #ifndef USECHOWN + #define USECHOWN + #endif USECHOWN + #endif NOCHGRPEXEC + private OSErr unix_chown(path,own,grp) char *path; *************** *** 3412,3418 **** #ifndef USECHOWN struct stat stb; OSErr err; ! #endif if (DBOSI) printf("unix_chown: Attempting chown %s to owner %d, group %d\n", --- 3458,3464 ---- #ifndef USECHOWN struct stat stb; OSErr err; ! #endif USECHOWN if (DBOSI) printf("unix_chown: Attempting chown %s to owner %d, group %d\n", *************** *** 3419,3426 **** path,own,grp); #ifndef USECHOWN 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 */ --- 3465,3477 ---- path,own,grp); #ifndef USECHOWN if (usruid != 0) { /* not root, then do it hard way */ + if (grp < 0) { + if (DBOSI) + printf("unix_chown: skipping owner and group for %s\n",path); + return(noErr); + } if (DBOSI) ! printf("unix_chown: skipping owner, 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 */ *************** *** 3444,3450 **** return(aeAccessDenied); /* oh well */ return(noErr); } ! #endif /* root can do what it pleases, so can any user on sysv */ if (chown(path, own, grp) < 0) return(ItoEErr(errno)); --- 3495,3513 ---- return(aeAccessDenied); /* oh well */ return(noErr); } ! #endif USECHOWN ! #ifdef NOCHGRPEXEC ! if (usruid != 0) { /* not root, ignore user */ ! if (grp < 0) { ! if (DBOSI) ! printf("unix_chown: skipping owner and group for %s\n",path); ! return(noErr); ! } ! own = -1; ! if (DBOSI) ! printf("unix_chown: skipping owner, chgrp %s to group %d\n",path,grp); ! } ! #endif NOCHGRPEXEC /* root can do what it pleases, so can any user on sysv */ if (chown(path, own, grp) < 0) return(ItoEErr(errno)); *** README.orig Sun Nov 17 16:09:12 1991 --- README Sun Nov 17 16:09:32 1991 *************** *** 3,9 **** (For use with AppleTalk/Ethernet bridge) o RELEASE NOTES ! o CAP Distribution 6.0, Patch Level 62, September 1991 Introduction ------------ --- 3,9 ---- (For use with AppleTalk/Ethernet bridge) o RELEASE NOTES ! o CAP Distribution 6.0, Patch Level 63, November 1991 Introduction ------------