summaryrefslogtreecommitdiff
path: root/toys/posix/chmod.c
blob: 429243991c85dd4d08094eccd88d644e4836d44d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
/* chmod.c - Change file mode bits
 *
 * Copyright 2012 Rob Landley <rob@landley.net>
 *
 * See http://opengroup.org/onlinepubs/9699919799/utilities/chmod.html

USE_CHMOD(NEWTOY(chmod, "<2?vRf[-vf]", TOYFLAG_BIN))

config CHMOD
  bool "chmod"
  default y
  help
    usage: chmod [-R] MODE FILE...

    Change mode of listed file[s] (recursively with -R).

    MODE can be (comma-separated) stanzas: [ugoa][+-=][rwxstXugo]

    Stanzas are applied in order: For each category (u = user,
    g = group, o = other, a = all three, if none specified default is a),
    set (+), clear (-), or copy (=), r = read, w = write, x = execute.
    s = u+s = suid, g+s = sgid, o+s = sticky. (+t is an alias for o+s).
    suid/sgid: execute as the user/group who owns the file.
    sticky: can't delete files you don't own out of this directory
    X = x for directories or if any category already has x set.

    Or MODE can be an octal value up to 7777	ug uuugggooo	top +
    bit 1 = o+x, bit 1<<8 = u+w, 1<<11 = g+1	sstrwxrwxrwx	bottom

    Examples:
    chmod u+w file - allow owner of "file" to write to it.
    chmod 744 file - user can read/write/execute, everyone else read only
*/

#define FOR_chmod
#include "toys.h"

GLOBALS(
  char *mode;
)

static int do_chmod(struct dirtree *try)
{
  mode_t mode;

  if (!dirtree_notdotdot(try)) return 0;

  mode = string_to_mode(TT.mode, try->st.st_mode);
  if (toys.optflags & FLAG_v) {
    char *s = dirtree_path(try, 0);
    printf("chmod '%s' to %04o\n", s, mode);
    free(s);
  }
  wfchmodat(dirtree_parentfd(try), try->name, mode);

  return (toys.optflags & FLAG_R) ? DIRTREE_RECURSE : 0;
}

void chmod_main(void)
{
  TT.mode = *toys.optargs;
  char **file;

  for (file = toys.optargs+1; *file; file++) dirtree_read(*file, do_chmod);
}