-/* Return a positive integer containing the value of the ASCII
- octal number S. If S is not an octal number, return -1. */
+/* All the mode bits that can be affected by chmod. */
+#define CHMOD_MODE_BITS \
+ (S_ISUID | S_ISGID | S_ISVTX | S_IRWXU | S_IRWXG | S_IRWXO)
/* Create a mode_change entry with the specified `=ddd'-style
mode change operation, where NEW_MODE is `ddd'. Return the
new entry, or NULL upon failure. */
static struct mode_change *
/* Create a mode_change entry with the specified `=ddd'-style
mode change operation, where NEW_MODE is `ddd'. Return the
new entry, or NULL upon failure. */
static struct mode_change *
{
struct mode_change *head; /* First element of the linked list. */
struct mode_change *tail; /* An element of the linked list. */
{
struct mode_change *head; /* First element of the linked list. */
struct mode_change *tail; /* An element of the linked list. */
- int i; /* General purpose temporary. */
- int umask_value; /* The umask value (surprise). */
+ uintmax_t mode_value; /* The mode value, if octal. */
+ char *string_end; /* Pointer to end of parsed value. */
+ mode_t umask_value; /* The umask value (surprise). */
if (p == NULL)
return MODE_MEMORY_EXHAUSTED;
mode_append_entry (&head, &tail, p);
if (p == NULL)
return MODE_MEMORY_EXHAUSTED;
mode_append_entry (&head, &tail, p);
change affects it even if no execute bits were set in OLDMODE.
The returned value has the S_IFMT bits cleared. */
change affects it even if no execute bits were set in OLDMODE.
The returned value has the S_IFMT bits cleared. */
- unsigned short newmode; /* The adjusted mode and one operand. */
- unsigned short value; /* The other operand. */
+ mode_t newmode; /* The adjusted mode and one operand. */
+ mode_t value; /* The other operand. */
- value |= (value >> 3) | (value >> 6);
- else if (changes->value & 00070)
+ value |= ((value & S_IRUSR ? S_IRGRP | S_IROTH : 0)
+ | (value & S_IWUSR ? S_IWGRP | S_IROTH : 0)
+ | (value & S_IXUSR ? S_IXGRP | S_IXOTH : 0));
+ else if (changes->value & S_IRWXG)
/* In order to change only `u', `g', or `o' permissions,
or some combination thereof, clear unselected bits.
/* In order to change only `u', `g', or `o' permissions,
or some combination thereof, clear unselected bits.
- && (newmode & 00111) == 0)
- value &= ~00111; /* Clear the execute bits. */
+ && (newmode & (S_IXUSR | S_IXGRP | S_IXOTH)) == 0)
+ /* Clear the execute bits. */
+ value &= ~ (S_IXUSR | S_IXGRP | S_IXOTH);