summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJim Meyering <jim@meyering.net>1994-07-01 19:45:39 +0000
committerJim Meyering <jim@meyering.net>1994-07-01 19:45:39 +0000
commitaee34fb09c156cd049ff12c5bb4a89167a82ee5e (patch)
treec1cec4888d1aed559534fe0a570489afb94933af
parentc56261a766f293c4d8e7cf962a72d4f926ed6d5f (diff)
downloadgnulib-aee34fb09c156cd049ff12c5bb4a89167a82ee5e.tar.gz
GNU file utilitiesFILEUTILS-3_9d
-rw-r--r--lib/Makefile.in13
-rw-r--r--lib/fsusage.c42
-rw-r--r--lib/full-write.c2
-rw-r--r--lib/modechange.c3
-rw-r--r--lib/safe-read.c1
-rw-r--r--lib/userspec.c255
6 files changed, 211 insertions, 105 deletions
diff --git a/lib/Makefile.in b/lib/Makefile.in
index c08ed462b3..fc6f35d95d 100644
--- a/lib/Makefile.in
+++ b/lib/Makefile.in
@@ -27,35 +27,38 @@ DEFS = -DCONFIG_BROKETS @DEFS@
CFLAGS = @CFLAGS@
YACC = @YACC@
-prefix = /usr/local
+prefix = @prefix@
exec_prefix = $(prefix)
libdir = $(exec_prefix)/lib
SOURCES = getdate.y posixtm.y \
argmatch.c backupfile.c basename.c dirname.c eaccess.c \
error.c filemode.c fsusage.c full-write.c getopt.c getopt1.c \
-getversion.c idcache.c isdir.c makepath.c \
+getversion.c group-member.c idcache.c isdir.c makepath.c \
modechange.c mountlist.c safe-read.c savedir.c \
stripslash.c xgetcwd.c xmalloc.c xstrdup.c userspec.c yesno.c \
fileblocks.c fnmatch.c ftruncate.c mkdir.c mktime.c rename.c stpcpy.c \
-strdup.c strstr.c alloca.c
+strdup.c strstr.c alloca.c long-options.c
OBJECTS = getdate.o posixtm.o \
argmatch.o backupfile.o basename.o dirname.o eaccess.o \
error.o filemode.o full-write.o getopt.o getopt1.o \
-getversion.o idcache.o isdir.o makepath.o \
+getversion.o group-member.o idcache.o isdir.o long-options.o makepath.o \
modechange.o safe-read.o savedir.o \
stripslash.o xgetcwd.o xmalloc.o xstrdup.o userspec.o yesno.o \
@LIBOBJS@ @ALLOCA@
DISTFILES = Makefile.in backupfile.h getopt.h modechange.h \
-fnmatch.h fsusage.h mountlist.h pathmax.h system.h $(SOURCES)
+fnmatch.h fsusage.h mountlist.h pathmax.h $(SOURCES)
all: libfu.a
.c.o:
$(CC) -c $(CPPFLAGS) $(DEFS) -I.. -I$(srcdir) $(CFLAGS) $<
+Makefile: ../config.status Makefile.in
+ CONFIG_FILES=$@ CONFIG_HEADERS= ../config.status
+
install: all
uninstall:
diff --git a/lib/fsusage.c b/lib/fsusage.c
index 96860ebc51..d0d746556e 100644
--- a/lib/fsusage.c
+++ b/lib/fsusage.c
@@ -69,13 +69,19 @@ int statvfs ();
#endif
/* Return the number of TOSIZE-byte blocks used by
- BLOCKS FROMSIZE-byte blocks, rounding away from zero. */
+ BLOCKS FROMSIZE-byte blocks, rounding away from zero.
+ TOSIZE must be positive. Return -1 if FROMSIZE is not positive. */
static long
adjust_blocks (blocks, fromsize, tosize)
long blocks;
int fromsize, tosize;
{
+ if (tosize <= 0)
+ abort ();
+ if (fromsize <= 0)
+ return -1;
+
if (fromsize == tosize) /* E.g., from 512 to 512. */
return blocks;
else if (fromsize > tosize) /* E.g., from 2048 to 512. */
@@ -99,8 +105,8 @@ get_fs_usage (path, disk, fsp)
struct statfs fsd;
if (statfs (path, &fsd, sizeof (struct statfs)) != 0)
- return (-1);
-#define convert_blocks(b) adjust_blocks ((b),fsd.f_fsize, 512)
+ return -1;
+#define CONVERT_BLOCKS(b) adjust_blocks ((b), fsd.f_fsize, 512)
#endif /* STAT_STATFS3_OSF1 */
#ifdef STAT_STATFS2_FS_DATA /* Ultrix. */
@@ -108,10 +114,10 @@ get_fs_usage (path, disk, fsp)
if (statfs (path, &fsd) != 1)
return -1;
-#define convert_blocks(b) adjust_blocks ((b), 1024, 512)
- fsp->fsu_blocks = convert_blocks (fsd.fd_req.btot);
- fsp->fsu_bfree = convert_blocks (fsd.fd_req.bfree);
- fsp->fsu_bavail = convert_blocks (fsd.fd_req.bfreen);
+#define CONVERT_BLOCKS(b) adjust_blocks ((b), 1024, 512)
+ fsp->fsu_blocks = CONVERT_BLOCKS (fsd.fd_req.btot);
+ fsp->fsu_bfree = CONVERT_BLOCKS (fsd.fd_req.bfree);
+ fsp->fsu_bavail = CONVERT_BLOCKS (fsd.fd_req.bfreen);
fsp->fsu_files = fsd.fd_req.gtot;
fsp->fsu_ffree = fsd.fd_req.gfree;
#endif
@@ -133,10 +139,10 @@ get_fs_usage (path, disk, fsp)
return -1;
}
close (fd);
-#define convert_blocks(b) adjust_blocks ((b), (fsd.s_type == Fs2b ? 1024 : 512), 512)
- fsp->fsu_blocks = convert_blocks (fsd.s_fsize);
- fsp->fsu_bfree = convert_blocks (fsd.s_tfree);
- fsp->fsu_bavail = convert_blocks (fsd.s_tfree);
+#define CONVERT_BLOCKS(b) adjust_blocks ((b), (fsd.s_type == Fs2b ? 1024 : 512), 512)
+ fsp->fsu_blocks = CONVERT_BLOCKS (fsd.s_fsize);
+ fsp->fsu_bfree = CONVERT_BLOCKS (fsd.s_tfree);
+ fsp->fsu_bavail = CONVERT_BLOCKS (fsd.s_tfree);
fsp->fsu_files = (fsd.s_isize - 2) * INOPB * (fsd.s_type == Fs2b ? 2 : 1);
fsp->fsu_ffree = fsd.s_tinode;
#endif
@@ -146,7 +152,7 @@ get_fs_usage (path, disk, fsp)
if (statfs (path, &fsd) < 0)
return -1;
-#define convert_blocks(b) adjust_blocks ((b), fsd.f_bsize, 512)
+#define CONVERT_BLOCKS(b) adjust_blocks ((b), fsd.f_bsize, 512)
#endif
#ifdef STAT_STATFS2_FSIZE /* 4.4BSD. */
@@ -154,7 +160,7 @@ get_fs_usage (path, disk, fsp)
if (statfs (path, &fsd) < 0)
return -1;
-#define convert_blocks(b) adjust_blocks ((b), fsd.f_fsize, 512)
+#define CONVERT_BLOCKS(b) adjust_blocks ((b), fsd.f_fsize, 512)
#endif
#ifdef STAT_STATFS4 /* SVR3, Dynix, Irix. */
@@ -165,7 +171,7 @@ get_fs_usage (path, disk, fsp)
/* Empirically, the block counts on most SVR3 and SVR3-derived
systems seem to always be in terms of 512-byte blocks,
no matter what value f_bsize has. */
-#define convert_blocks(b) (b)
+#define CONVERT_BLOCKS(b) (b)
#ifndef _SEQUENT_ /* _SEQUENT_ is DYNIX/ptx. */
#ifndef DOLPHIN /* DOLPHIN 3.8.alfa/7.18 has f_bavail */
#define f_bavail f_bfree
@@ -179,14 +185,14 @@ get_fs_usage (path, disk, fsp)
if (statvfs (path, &fsd) < 0)
return -1;
/* f_frsize isn't guaranteed to be supported. */
-#define convert_blocks(b) \
+#define CONVERT_BLOCKS(b) \
adjust_blocks ((b), fsd.f_frsize ? fsd.f_frsize : fsd.f_bsize, 512)
#endif
#if !defined(STAT_STATFS2_FS_DATA) && !defined(STAT_READ) /* !Ultrix && !SVR2. */
- fsp->fsu_blocks = convert_blocks (fsd.f_blocks);
- fsp->fsu_bfree = convert_blocks (fsd.f_bfree);
- fsp->fsu_bavail = convert_blocks (fsd.f_bavail);
+ fsp->fsu_blocks = CONVERT_BLOCKS (fsd.f_blocks);
+ fsp->fsu_bfree = CONVERT_BLOCKS (fsd.f_bfree);
+ fsp->fsu_bavail = CONVERT_BLOCKS (fsd.f_bavail);
fsp->fsu_files = fsd.f_files;
fsp->fsu_ffree = fsd.f_ffree;
#endif
diff --git a/lib/full-write.c b/lib/full-write.c
index cce5f0f035..6e2e446830 100644
--- a/lib/full-write.c
+++ b/lib/full-write.c
@@ -1,5 +1,5 @@
/* full-write.c -- an interface to write that retries after interrupts
- Copyright (C) 1993 Free Software Foundation, Inc.
+ Copyright (C) 1993, 1994 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/lib/modechange.c b/lib/modechange.c
index 448ea7b005..e1212e90a3 100644
--- a/lib/modechange.c
+++ b/lib/modechange.c
@@ -112,6 +112,9 @@ mode_compile (mode_string, masked_ops)
umask (umask_value); /* Restore the old value. */
head = NULL;
+#ifdef lint
+ change = NULL;
+#endif
--mode_string;
/* One loop iteration for each "ugoa...=+-rwxXstugo...[=+-rwxXstugo...]". */
diff --git a/lib/safe-read.c b/lib/safe-read.c
index 2303ea111a..2e131e1f2c 100644
--- a/lib/safe-read.c
+++ b/lib/safe-read.c
@@ -14,6 +14,7 @@
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
#ifdef HAVE_CONFIG_H
#if defined (CONFIG_BROKETS)
diff --git a/lib/userspec.c b/lib/userspec.c
index 37b7980b9f..75000e8fd3 100644
--- a/lib/userspec.c
+++ b/lib/userspec.c
@@ -28,6 +28,20 @@
#endif
#endif
+#ifdef __GNUC__
+#define alloca __builtin_alloca
+#else
+#ifdef HAVE_ALLOCA_H
+#include <alloca.h>
+#else
+#ifdef _AIX
+ #pragma alloca
+#else
+char *alloca ();
+#endif
+#endif
+#endif
+
#include <stdio.h>
#include <sys/types.h>
#include <pwd.h>
@@ -44,8 +58,6 @@
#ifdef STDC_HEADERS
#include <stdlib.h>
-#else
-char *malloc ();
#endif
#ifdef HAVE_UNISTD_H
@@ -63,10 +75,34 @@ struct group *getgrgid ();
#define endgrent()
#endif
+/* Perform the equivalent of the statement `dest = strdup (src);',
+ but obtaining storage via alloca instead of from the heap. */
+
+#define V_STRDUP(dest, src) \
+ do \
+ { \
+ int _len = strlen ((src)); \
+ (dest) = (char *) alloca (_len + 1); \
+ strcpy (dest, src); \
+ } \
+ while (0)
+
#define isdigit(c) ((c) >= '0' && (c) <= '9')
char *strdup ();
-static int isnumber ();
+
+/* Return nonzero if STR represents an unsigned decimal integer,
+ otherwise return 0. */
+
+static int
+isnumber (str)
+ const char *str;
+{
+ for (; *str; str++)
+ if (!isdigit (*str))
+ return 0;
+ return 1;
+}
/* Extract from NAME, which has the form "[user][:.][group]",
a USERNAME, UID U, GROUPNAME, and GID G.
@@ -77,115 +113,172 @@ static int isnumber ();
USERNAME and GROUPNAME will be in newly malloc'd memory.
Either one might be NULL instead, indicating that it was not
given and the corresponding numeric ID was left unchanged.
- Might write NULs into NAME.
Return NULL if successful, a static error message string if not. */
-char *
-parse_user_spec (name, uid, gid, username, groupname)
- char *name;
+const char *
+parse_user_spec (spec_arg, uid, gid, username_arg, groupname_arg)
+ const char *spec_arg;
uid_t *uid;
gid_t *gid;
- char **username, **groupname;
+ char **username_arg, **groupname_arg;
{
- static char *tired = "virtual memory exhausted";
+ static const char *tired = "virtual memory exhausted";
+ const char *error_msg;
+ char *spec; /* A copy we can write on. */
struct passwd *pwd;
struct group *grp;
- char *cp;
- int use_login_group = 0;
+ char *g, *u, *separator;
+ char *groupname;
+
+ error_msg = NULL;
+ *username_arg = *groupname_arg = NULL;
+ groupname = NULL;
+
+ V_STRDUP (spec, spec_arg);
- *username = *groupname = NULL;
+ /* Find the separator if there is one. */
+ separator = index (spec, ':');
+ if (separator == NULL)
+ separator = index (spec, '.');
- /* Check whether a group is given. */
- cp = index (name, ':');
- if (cp == NULL)
- cp = index (name, '.');
- if (cp != NULL)
+ /* Replace separator with a NUL. */
+ if (separator != NULL)
+ *separator = '\0';
+
+ /* Set U and G to non-zero length strings corresponding to user and
+ group specifiers or to NULL. */
+ u = (*spec == '\0' ? NULL : spec);
+
+ g = (separator == NULL || *(separator + 1) == '\0'
+ ? NULL
+ : separator + 1);
+
+ if (u == NULL && g == NULL)
+ return "can not omit both user and group";
+
+ if (u != NULL)
{
- *cp++ = '\0';
- if (*cp == '\0')
+ pwd = getpwnam (u);
+ if (pwd == NULL)
{
- if (cp == name + 1)
- /* Neither user nor group given, just "." or ":". */
- return "can not omit both user and group";
+
+ if (!isnumber (u))
+ error_msg = "invalid user";
else
- /* "user.". */
- use_login_group = 1;
+ {
+ int use_login_group;
+ use_login_group = (separator != NULL && g == NULL);
+ if (use_login_group)
+ error_msg = "cannot get the login group of a numeric UID";
+ else
+ *uid = atoi (u);
+ }
}
else
{
- /* Explicit group. */
- *groupname = strdup (cp);
- if (*groupname == NULL)
- return tired;
- grp = getgrnam (cp);
- if (grp == NULL)
+ *uid = pwd->pw_uid;
+ if (g == NULL && separator != NULL)
{
- if (!isnumber (cp))
- return "invalid group";
- *gid = atoi (cp);
+ /* A separator was given, but a group was not specified,
+ so get the login group. */
+ *gid = pwd->pw_gid;
+ grp = getgrgid (pwd->pw_gid);
+ if (grp == NULL)
+ {
+ /* This is enough room to hold the unsigned decimal
+ representation of any 32-bit quantity and the trailing
+ zero byte. */
+ char uint_buf[21];
+ sprintf (uint_buf, "%u", (unsigned) (pwd->pw_gid));
+ V_STRDUP (groupname, uint_buf);
+ }
+ else
+ {
+ V_STRDUP (groupname, grp->gr_name);
+ }
+ endgrent ();
}
- else
- *gid = grp->gr_gid;
- endgrent (); /* Save a file descriptor. */
}
+ endpwent ();
}
- /* Parse the user name, now that any group has been removed. */
-
- if (name[0] == '\0')
- /* No user name was given, just a group. */
- return NULL;
-
- *username = strdup (name);
- if (*username == NULL)
- return tired;
-
- pwd = getpwnam (name);
- if (pwd == NULL)
+ if (g != NULL && error_msg == NULL)
{
- if (!isnumber (name))
- return "invalid user";
- if (use_login_group)
- return "cannot get the login group of a numeric UID";
- *uid = atoi (name);
+ /* Explicit group. */
+ grp = getgrnam (g);
+ if (grp == NULL)
+ {
+ if (!isnumber (g))
+ error_msg = "invalid group";
+ else
+ *gid = atoi (g);
+ }
+ else
+ *gid = grp->gr_gid;
+ endgrent (); /* Save a file descriptor. */
+
+ if (error_msg == NULL)
+ V_STRDUP (groupname, g);
}
- else
+
+ if (error_msg == NULL)
{
- *uid = pwd->pw_uid;
- if (use_login_group)
+ if (u != NULL)
{
- *gid = pwd->pw_gid;
- grp = getgrgid (pwd->pw_gid);
- if (grp == NULL)
- {
- *groupname = malloc (15);
- if (*groupname == NULL)
- return tired;
- sprintf (*groupname, "%u", (unsigned) (pwd->pw_gid));
- }
- else
+ *username_arg = strdup (u);
+ if (*username_arg == NULL)
+ error_msg = tired;
+ }
+
+ if (groupname != NULL && error_msg == NULL)
+ {
+ *groupname_arg = strdup (groupname);
+ if (*groupname_arg == NULL)
{
- *groupname = strdup (grp->gr_name);
- if (*groupname == NULL)
- return tired;
+ if (*username_arg != NULL)
+ {
+ free (*username_arg);
+ *username_arg = NULL;
+ }
+ error_msg = tired;
}
- endgrent ();
}
}
- endpwent ();
- return NULL;
+
+ return error_msg;
}
-/* Return nonzero if STR represents an unsigned decimal integer,
- otherwise return 0. */
+#ifdef TEST
-static int
-isnumber (str)
- char *str;
+#define NULL_CHECK(s) ((s) == NULL ? "(null)" : (s))
+
+int
+main (int argc, char **argv)
{
- for (; *str; str++)
- if (!isdigit (*str))
- return 0;
- return 1;
+ int i;
+
+ for (i = 1; i < argc; i++)
+ {
+ const char *e;
+ char *username, *groupname;
+ uid_t uid;
+ gid_t gid;
+ char *tmp;
+
+ tmp = strdup (argv[i]);
+ e = parse_user_spec (tmp, &uid, &gid, &username, &groupname);
+ free (tmp);
+ printf ("%s: %u %u %s %s %s\n",
+ argv[i],
+ (unsigned int) uid,
+ (unsigned int) gid,
+ NULL_CHECK (username),
+ NULL_CHECK (groupname),
+ NULL_CHECK (e));
+ }
+
+ exit (0);
}
+
+#endif