- if (ops_to_mask & (*mode_string == '=' ? MODE_MASK_EQUALS
- : *mode_string == '+' ? MODE_MASK_PLUS
- : MODE_MASK_MINUS))
- affected_masked &= ~umask_value;
- change->affected = affected_masked;
- change->value = 0;
- change->flags = 0;
-
- /* Add the element to the tail of the list, so the operations
- are performed in the correct order. */
- mode_append_entry (&head, &tail, change);
-
- /* Set `value' according to the bits set in `affected_masked'. */
- for (++mode_string;; ++mode_string)
- switch (*mode_string)
- {
- case 'r':
- change->value |= ((S_IRUSR | S_IRGRP | S_IROTH)
- & affected_masked);
- break;
- case 'w':
- change->value |= ((S_IWUSR | S_IWGRP | S_IWOTH)
- & affected_masked);
- break;
- case 'X':
- change->flags |= MODE_X_IF_ANY_X;
- /* Fall through. */
- case 'x':
- change->value |= ((S_IXUSR | S_IXGRP | S_IXOTH)
- & affected_masked);
- break;
- case 's':
- /* Set the setuid/gid bits if `u' or `g' is selected. */
- change->value |= (S_ISUID | S_ISGID) & affected_masked;
- break;
- case 't':
- /* Set the "save text image" bit if `o' is selected. */
- change->value |= S_ISVTX & affected_masked;
- break;
- case 'u':
- /* Set the affected bits to the value of the `u' bits
- on the same file. */
- if (change->value)
- goto invalid;
- change->value = S_IRWXU;
- change->flags |= MODE_COPY_EXISTING;
- break;
- case 'g':
- /* Set the affected bits to the value of the `g' bits
- on the same file. */
- if (change->value)
- goto invalid;
- change->value = S_IRWXG;
- change->flags |= MODE_COPY_EXISTING;
- break;
- case 'o':
- /* Set the affected bits to the value of the `o' bits
- on the same file. */
- if (change->value)
- goto invalid;
- change->value = S_IRWXO;
- change->flags |= MODE_COPY_EXISTING;
- break;
- default:
- goto no_more_values;
- }
- no_more_values:;
- }
- } while (*mode_string == ',');