home *** CD-ROM | disk | FTP | other *** search
- Newsgroups: gnu.utils.bug
- Path: sparky!uunet!cis.ohio-state.edu!mercury.cs.mun.ca!michael
- From: michael@mercury.cs.mun.ca (Mike Rendell)
- Subject: fileutils-3.4: chgrp problems on old bsd systems, +fix
- Message-ID: <9212111827.AA19890@mercury.cs.mun.ca>
- Sender: gnulists@ai.mit.edu
- Organization: GNUs Not Usenet
- Distribution: gnu
- Date: Fri, 11 Dec 1992 11:09:55 GMT
- Approved: bug-gnu-utils@prep.ai.mit.edu
- Lines: 322
-
- Machine: vax
- OS: (old) 4.3bsd from Mt. Xinu, Ultrix 2.2, others
-
- The GNU chgrp doesn't work on older versions of bsd because only root can
- use chown(2) (there is a comment to this effect about sequents in the README
- file). I've added (ifdef'd) code to the GNU chgrp to deal with such systems
- when it is installed setuid root. The code checks that the user is in the
- named group, makes sure the user owns all files before changing the group,
- and checks directory permissions before recursing into them. The diffs for
- configure(.in) add a test to see if the system has such a broken chown(2)
- (the test is done in a readable/executable subdirectory, conftest.dir, so it
- will work even if root is running configure). The diffs also add a
- GETGROUPS_T test to the configure scripts since the modified chgrp uses
- getgroups(). Note that the Makefile doesn't install chgrp as setuid
- root - this needs to be done by hand.
-
-
- *** src/chgrp.c.orig Fri Jul 17 17:18:38 1992
- --- src/chgrp.c Fri Dec 11 14:41:06 1992
- ***************
- *** 24,32 ****
- #include <getopt.h>
- #include "system.h"
-
- ! #ifndef _POSIX_VERSION
- struct group *getgrnam ();
- ! #endif
-
- #ifdef _POSIX_SOURCE
- #define endgrent()
- --- 24,48 ----
- #include <getopt.h>
- #include "system.h"
-
- ! #ifdef _POSIX_VERSION
- ! #include <limits.h>
- ! #if !defined(NGROUPS_MAX) || NGROUPS_MAX < 1
- ! #define NGROUPS_MAX sysconf (_SC_NGROUPS_MAX)
- ! #endif /* !NGROUPS_MAX */
- !
- ! #else /* not _POSIX_VERSION */
- struct group *getgrnam ();
- ! uid_t getuid ();
- ! gid_t getgid ();
- ! #include <sys/param.h>
- ! #if !defined(NGROUPS_MAX) && defined(NGROUPS)
- ! #define NGROUPS_MAX NGROUPS
- ! #endif /* not NGROUPS_MAX and NGROUPS */
- ! #endif /* not _POSIX_VERSION */
- !
- ! #ifndef GETGROUPS_T
- ! # define GETGROUPS_T gid_t
- ! #endif /* !GETGROUPS_T */
-
- #ifdef _POSIX_SOURCE
- #define endgrent()
- ***************
- *** 63,68 ****
- --- 79,90 ----
- /* The name of the group to which ownership of the files is being given. */
- char *groupname;
-
- + #ifdef HAVE_BROKEN_CHOWN
- + /* Uid/gid of the user running the program. */
- + uid_t my_uid;
- + gid_t my_gid;
- + #endif /* HAVE_BROKEN_CHOWN */
- +
- struct option long_options[] =
- {
- {"recursive", 0, 0, 'R'},
- ***************
- *** 113,118 ****
- --- 135,166 ----
-
- parse_group (argv[optind++], &group);
-
- + #ifdef HAVE_BROKEN_CHOWN
- + my_uid = getuid ();
- + my_gid = getgid ();
- + /* Check that (non-root) user is in group GROUP */
- + if (my_uid)
- + {
- + # ifdef NGROUPS_MAX
- + GETGROUPS_T *groups;
- + int i, n;
- +
- + groups = (GETGROUPS_T *) xmalloc (NGROUPS_MAX * sizeof(GETGROUPS_T));
- + if ((n = getgroups (NGROUPS_MAX, groups)) < 0)
- + error (1, errno, "cannot get supplemental group list");
- + for (i = 0; i < n; i++)
- + if (groups[i] == group)
- + break;
- + if (i == n)
- + error (1, 0, "you are not in group %s", groupname);
- + free (groups);
- + # else /* not NGROUPS_MAX */
- + if (my_gid != group)
- + error (1, 0, "you are not in group %s", groupname);
- + # endif /* not NGROUPS_MAX */
- + }
- + #endif /* HAVE_BROKEN_CHOWN */
- +
- for (; optind < argc; ++optind)
- errors |= change_file_group (argv[optind], group);
-
- ***************
- *** 165,178 ****
-
- if (group != file_stats.st_gid)
- {
- ! if (verbose)
- ! describe_change (file, 1);
- ! if (chown (file, file_stats.st_uid, group))
- {
- if (force_silent == 0)
- ! error (0, errno, "%s", file);
- errors = 1;
- }
- }
- else if (verbose && changes_only == 0)
- describe_change (file, 0);
- --- 213,237 ----
-
- if (group != file_stats.st_gid)
- {
- ! #ifdef HAVE_BROKEN_CHOWN
- ! if (my_uid && file_stats.st_uid != my_uid)
- {
- if (force_silent == 0)
- ! error (0, 0, "you are not the owner of %s", file);
- errors = 1;
- }
- + else
- + #endif /* HAVE_BROKEN_CHOWN */
- + {
- + if (verbose)
- + describe_change (file, 1);
- + if (chown (file, file_stats.st_uid, group))
- + {
- + if (force_silent == 0)
- + error (0, errno, "%s", file);
- + errors = 1;
- + }
- + }
- }
- else if (verbose && changes_only == 0)
- describe_change (file, 0);
- ***************
- *** 199,204 ****
- --- 258,274 ----
- unsigned filelength; /* Length of each pathname to process. */
- unsigned pathlength; /* Bytes allocated for `path'. */
- int errors = 0;
- +
- + #ifdef HAVE_BROKEN_CHOWN
- + /* If only X_OK were used, chgrp's errors could be used to list the
- + contents of unreadable directories. So use R_OK as well... */
- + if (my_uid && access (dir, R_OK|X_OK))
- + {
- + if (force_silent == 0)
- + error (0, errno, "%s", dir);
- + return 1;
- + }
- + #endif /* HAVE_BROKEN_CHOWN */
-
- errno = 0;
- name_space = savedir (dir, statp->st_size);
-
-
- *** configure.orig Thu Oct 29 18:14:52 1992
- --- configure Fri Dec 11 13:52:57 1992
- ***************
- *** 525,530 ****
- --- 525,582 ----
- fi
- rm -f conftest*
-
- + echo checking getgroups group id type
- + echo "#include <sys/types.h>
- + #define NGID 256
- + main()
- + {
- + gid_t gidset[NGID];
- + int i, n;
- + union { gid_t gval; long lval; } val;
- +
- + val.lval = -1;
- + for (i = 0; i < NGID; i++)
- + gidset[i] = val.gval;
- + n = getgroups(sizeof(gidset) / (sizeof(int) > sizeof(gid_t)
- + ? sizeof(int) : sizeof(gid_t)) - 1, gidset);
- + if (n > 0 && gidset[n] != val.gval)
- + exit(0);
- + exit(1);
- + }" > conftest.c
- + eval $compile
- + if test -s conftest && ./conftest 2>/dev/null ; then
- + DEFS="$DEFS -DGETGROUPS_T=int"
- + fi
- + rm -f conftest*
- +
- + echo checking for broken chown
- + echo "main()
- + {
- + int fd;
- + char *file = "\"conftest.data\"";
- +
- + unlink (file);
- + if ((fd = creat (file, 0644)) < 0)
- + exit (1);
- + close (fd);
- + if (!getuid ())
- + {
- + if (chown (file, 1, getgid ()) < 0)
- + exit (1);
- + setuid (1);
- + }
- + if (chown (file, getuid (), getgid ()) < 0)
- + exit (0);
- + exit (1);
- + }" > conftest.c
- + eval $compile
- + [ -d conftest.dir ] || mkdir conftest.dir
- + chmod 755 conftest.dir
- + if test -s conftest && (cd ./conftest.dir; ../conftest) 2>/dev/null ; then
- + DEFS="$DEFS -DHAVE_BROKEN_CHOWN"
- + fi
- + rm -rf conftest*
- +
- echo checking integer size
- cat <<EOF > conftest.c
- main() { exit(!(sizeof(long) > sizeof(int))); }
- ***************
- *** 715,720 ****
- --- 767,775 ----
- LIBS="$SAVELIBS" ALLOCA=alloca.o
- fi
- fi
- +
- + echo checking for BSD
- + ( test -f /vmunix || test -f /sdmach || test -f /../../mach ) && DEFS="$DEFS -DBSD42=1"
-
- echo checking for st_blocks in struct stat
- echo "#include <sys/types.h>
-
-
- *** configure.in.orig Thu Oct 29 16:27:10 1992
- --- configure.in Fri Dec 11 13:56:32 1992
- ***************
- *** 90,95 ****
- --- 90,144 ----
- fi
-
- AC_UID_T
- + echo checking getgroups group id type
- + echo "#include <sys/types.h>
- + #define NGID 256
- + main()
- + {
- + gid_t gidset[NGID];
- + int i, n;
- + union { gid_t gval; long lval; } val;
- +
- + val.lval = -1;
- + for (i = 0; i < NGID; i++)
- + gidset[i] = val.gval;
- + n = getgroups (sizeof(gidset) / (sizeof(int) > sizeof(gid_t)
- + ? sizeof(int) : sizeof(gid_t)) - 1, gidset);
- + if (n > 0 && gidset[n] != val.gval)
- + exit (0);
- + exit (1);
- + }" > conftest.c
- + eval $compile
- + if test -s conftest && ./conftest 2>/dev/null ; then
- + DEFS="$DEFS -DGETGROUPS_T=int"
- + fi
- + rm -f conftest*
- + echo checking for broken chown
- + echo "main()
- + {
- + int fd;
- + char *file = "\"conftest.data\"";
- +
- + unlink (file);
- + if ((fd = creat (file, 0644)) < 0)
- + exit (1);
- + close (fd);
- + if (!getuid ())
- + {
- + if (chown (file, 1, getgid ()) < 0)
- + exit (1);
- + setuid (1);
- + }
- + if (chown (file, getuid (), getgid ()) < 0)
- + exit (0);
- + exit (1);
- + }" > conftest.c
- + [ -d conftest.dir ] || mkdir conftest.dir
- + chmod 755 conftest.dir
- + if test -s conftest && (cd ./conftest.dir; ../conftest) 2>/dev/null ; then
- + DEFS="$DEFS -DHAVE_BROKEN_CHOWN"
- + fi
- + rm -rf conftest*
- AC_INT_16_BITS
- AC_STDC_HEADERS
- AC_UNISTD_H
- ***************
- *** 117,122 ****
- --- 166,173 ----
-
- AC_VPRINTF
- AC_ALLOCA
- + echo checking for BSD
- + ( test -f /vmunix || test -f /sdmach || test -f /../../mach ) && AC_DEFINE(BSD4_2)
- AC_ST_BLOCKS
- AC_UTIME_NULL
- AC_XENIX_DIR
-
- --
- Michael Rendell - Dept. of Comp. Sci., Memorial University of Newfoundland
-
-