/* modechange.c -- file mode manipulation
- Copyright (C) 1989, 1990, 1997, 1998, 1999 Free Software Foundation, Inc.
+
+ Copyright (C) 1989, 1990, 1997, 1998, 1999, 2001, 2003, 2004 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
#include "modechange.h"
#include <sys/stat.h>
#include "xstrtol.h"
-
-#if STDC_HEADERS
-# include <stdlib.h>
-#else
-char *malloc ();
-#endif
-
-#ifndef NULL
-# define NULL 0
-#endif
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdlib.h>
#if STAT_MACROS_BROKEN
# undef S_ISDIR
# define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
#endif
+/* The traditional octal values corresponding to each mode bit. */
+#define SUID 04000
+#define SGID 02000
+#define SVTX 01000
+#define RUSR 00400
+#define WUSR 00200
+#define XUSR 00100
+#define RGRP 00040
+#define WGRP 00020
+#define XGRP 00010
+#define ROTH 00004
+#define WOTH 00002
+#define XOTH 00001
+#define ALLM 07777 /* all octal mode bits */
+
#ifndef S_ISUID
-# define S_ISUID 04000
+# define S_ISUID SUID
#endif
#ifndef S_ISGID
-# define S_ISGID 04000
+# define S_ISGID SGID
#endif
#ifndef S_ISVTX
-# define S_ISVTX 01000
+# define S_ISVTX SVTX
#endif
#ifndef S_IRUSR
-# define S_IRUSR 0400
+# define S_IRUSR RUSR
#endif
#ifndef S_IWUSR
-# define S_IWUSR 0200
+# define S_IWUSR WUSR
#endif
#ifndef S_IXUSR
-# define S_IXUSR 0100
+# define S_IXUSR XUSR
#endif
#ifndef S_IRGRP
-# define S_IRGRP 0040
+# define S_IRGRP RGRP
#endif
#ifndef S_IWGRP
-# define S_IWGRP 0020
+# define S_IWGRP WGRP
#endif
#ifndef S_IXGRP
-# define S_IXGRP 0010
+# define S_IXGRP XGRP
#endif
#ifndef S_IROTH
-# define S_IROTH 0004
+# define S_IROTH ROTH
#endif
#ifndef S_IWOTH
-# define S_IWOTH 0002
+# define S_IWOTH WOTH
#endif
#ifndef S_IXOTH
-# define S_IXOTH 0001
+# define S_IXOTH XOTH
#endif
#ifndef S_IRWXU
-# define S_IRWXU 0700
+# define S_IRWXU (S_IRUSR | S_IWUSR | S_IXUSR)
#endif
#ifndef S_IRWXG
-# define S_IRWXG 0070
+# define S_IRWXG (S_IRGRP | S_IWGRP | S_IXGRP)
#endif
#ifndef S_IRWXO
-# define S_IRWXO 0007
+# define S_IRWXO (S_IROTH | S_IWOTH | S_IXOTH)
#endif
/* All the mode bits that can be affected by chmod. */
{
struct mode_change *head; /* First element of the linked list. */
struct mode_change *tail; /* An element of the linked list. */
- unsigned long mode_value; /* The mode value, if octal. */
- char *string_end; /* Pointer to end of parsed value. */
+ unsigned long octal_value; /* The mode value, if octal. */
mode_t umask_value; /* The umask value (surprise). */
head = NULL;
tail = NULL;
#endif
- if (xstrtoul (mode_string, &string_end, 8, &mode_value, "") == LONGINT_OK)
+ if (xstrtoul (mode_string, NULL, 8, &octal_value, "") == LONGINT_OK)
{
struct mode_change *p;
- if (mode_value > CHMOD_MODE_BITS)
+ mode_t mode;
+ if (octal_value != (octal_value & ALLM))
return MODE_INVALID;
- p = make_node_op_equals ((mode_t) mode_value);
+
+ /* Help the compiler optimize the usual case where mode_t uses
+ the traditional octal representation. */
+ mode = ((S_ISUID == SUID && S_ISGID == SGID && S_ISVTX == SVTX
+ && S_IRUSR == RUSR && S_IWUSR == WUSR && S_IXUSR == XUSR
+ && S_IRGRP == RGRP && S_IWGRP == WGRP && S_IXGRP == XGRP
+ && S_IROTH == ROTH && S_IWOTH == WOTH && S_IXOTH == XOTH)
+ ? octal_value
+ : (mode_t) ((octal_value & SUID ? S_ISUID : 0)
+ | (octal_value & SGID ? S_ISGID : 0)
+ | (octal_value & SVTX ? S_ISVTX : 0)
+ | (octal_value & RUSR ? S_IRUSR : 0)
+ | (octal_value & WUSR ? S_IWUSR : 0)
+ | (octal_value & XUSR ? S_IXUSR : 0)
+ | (octal_value & RGRP ? S_IRGRP : 0)
+ | (octal_value & WGRP ? S_IWGRP : 0)
+ | (octal_value & XGRP ? S_IXGRP : 0)
+ | (octal_value & ROTH ? S_IROTH : 0)
+ | (octal_value & WOTH ? S_IWOTH : 0)
+ | (octal_value & XOTH ? S_IXOTH : 0)));
+
+ p = make_node_op_equals (mode);
if (p == NULL)
return MODE_MEMORY_EXHAUSTED;
mode_append_entry (&head, &tail, p);
/* `affected_bits' modified by umask. */
mode_t affected_masked;
/* Operators to actually use umask on. */
- unsigned ops_to_mask = 0;
+ unsigned int ops_to_mask = 0;
- int who_specified_p;
+ bool who_specified_p;
- affected_bits = 0;
- ops_to_mask = 0;
/* Turn on all the bits in `affected_bits' for each group given. */
for (++mode_string;; ++mode_string)
switch (*mode_string)
/* If none specified, affect all bits, except perhaps those
set in the umask. */
if (affected_bits)
- who_specified_p = 1;
+ who_specified_p = true;
else
{
- who_specified_p = 0;
+ who_specified_p = false;
affected_bits = CHMOD_MODE_BITS;
ops_to_mask = masked_ops;
}
if (changes->value & S_IRWXU)
/* Copy `u' permissions onto `g' and `o'. */
- value |= ((value & S_IRUSR ? S_IRGRP | S_IROTH : 0)
- | (value & S_IWUSR ? S_IWGRP | S_IROTH : 0)
+ value |= ( (value & S_IRUSR ? S_IRGRP | S_IROTH : 0)
+ | (value & S_IWUSR ? S_IWGRP | S_IWOTH : 0)
| (value & S_IXUSR ? S_IXGRP | S_IXOTH : 0));
else if (changes->value & S_IRWXG)
/* Copy `g' permissions onto `u' and `o'. */
- value |= ((value & S_IRGRP ? S_IRUSR | S_IROTH : 0)
- | (value & S_IWGRP ? S_IWUSR | S_IROTH : 0)
+ value |= ( (value & S_IRGRP ? S_IRUSR | S_IROTH : 0)
+ | (value & S_IWGRP ? S_IWUSR | S_IWOTH : 0)
| (value & S_IXGRP ? S_IXUSR | S_IXOTH : 0));
else
/* Copy `o' permissions onto `u' and `g'. */
- value |= ((value & S_IROTH ? S_IRUSR | S_IRGRP : 0)
- | (value & S_IWOTH ? S_IWUSR | S_IRGRP : 0)
+ value |= ( (value & S_IROTH ? S_IRUSR | S_IRGRP : 0)
+ | (value & S_IWOTH ? S_IWUSR | S_IWGRP : 0)
| (value & S_IXOTH ? S_IXUSR | S_IXGRP : 0));
/* In order to change only `u', `g', or `o' permissions,
or some combination thereof, clear unselected bits.
- This can not be done in mode_compile because the value
+ This cannot be done in mode_compile because the value
to which the `changes->affected' mask is applied depends
on the old mode of each file. */
value &= changes->affected;