toybox/toys/posix/chmod.c
<<
>>
Prefs
   1/* chmod.c - Change file mode bits
   2 *
   3 * Copyright 2012 Rob Landley <rob@landley.net>
   4 *
   5 * See http://opengroup.org/onlinepubs/9699919799/utilities/chmod.html
   6
   7USE_CHMOD(NEWTOY(chmod, "<2?vfR[-vf]", TOYFLAG_BIN))
   8
   9config CHMOD
  10  bool "chmod"
  11  default y
  12  help
  13    usage: chmod [-R] MODE FILE...
  14
  15    Change mode of listed file[s] (recursively with -R).
  16
  17    MODE can be (comma-separated) stanzas: [ugoa][+-=][rwxstXugo]
  18
  19    Stanzas are applied in order: For each category (u = user,
  20    g = group, o = other, a = all three, if none specified default is a),
  21    set (+), clear (-), or copy (=), r = read, w = write, x = execute.
  22    s = u+s = suid, g+s = sgid, +t = sticky. (o+s ignored so a+s doesn't set +t)
  23    suid/sgid: execute as the user/group who owns the file.
  24    sticky: can't delete files you don't own out of this directory
  25    X = x for directories or if any category already has x set.
  26
  27    Or MODE can be an octal value up to 7777    ug uuugggooo    top +
  28    bit 1 = o+x, bit 1<<8 = u+w, 1<<11 = g+1    sstrwxrwxrwx    bottom
  29
  30    Examples:
  31    chmod u+w file - allow owner of "file" to write to it.
  32    chmod 744 file - user can read/write/execute, everyone else read only
  33*/
  34
  35#define FOR_chmod
  36#include "toys.h"
  37
  38GLOBALS(
  39  char *mode;
  40)
  41
  42static int do_chmod(struct dirtree *try)
  43{
  44  mode_t mode;
  45
  46  if (!dirtree_notdotdot(try)) return 0;
  47
  48  if (FLAG(R) && try->parent && S_ISLNK(try->st.st_mode)) {
  49    // Ignore symlinks found during recursion. We'll only try to modify
  50    // symlinks mentioned directly as arguments. We'll fail, of course,
  51    // but that's what you asked for in that case.
  52  } else {
  53    mode = string_to_mode(TT.mode, try->st.st_mode) & ~S_IFMT;
  54    if (FLAG(v)) {
  55      char *s = dirtree_path(try, 0);
  56
  57      printf("chmod '%s' to %s\n", s, TT.mode);
  58      free(s);
  59    }
  60    wfchmodat(dirtree_parentfd(try), try->name, mode);
  61  }
  62
  63  return FLAG(R)*DIRTREE_RECURSE;
  64}
  65
  66void chmod_main(void)
  67{
  68  TT.mode = *toys.optargs;
  69  char **file;
  70
  71  for (file = toys.optargs+1; *file; file++) dirtree_read(*file, do_chmod);
  72}
  73