toybox/toys/posix/chgrp.c
<<
>>
Prefs
   1/* chgrp.c - Change user and group ownership
   2 *
   3 * Copyright 2012 Georgi Chorbadzhiyski <georgi@unixsol.org>
   4 *
   5 * See http://opengroup.org/onlinepubs/9699919799/utilities/chown.html
   6 * See http://opengroup.org/onlinepubs/9699919799/utilities/chgrp.html
   7
   8USE_CHGRP(NEWTOY(chgrp, "<2hPLHRfv[-HLP]", TOYFLAG_BIN))
   9USE_CHOWN(OLDTOY(chown, chgrp, TOYFLAG_BIN))
  10
  11config CHGRP
  12  bool "chgrp"
  13  default y
  14  help
  15    usage: chgrp/chown [-RHLP] [-fvh] group file...
  16
  17    Change group of one or more files.
  18
  19    -f  suppress most error messages.
  20    -h  change symlinks instead of what they point to
  21    -R  recurse into subdirectories (implies -h)
  22    -H  with -R change target of symlink, follow command line symlinks
  23    -L  with -R change target of symlink, follow all symlinks
  24    -P  with -R change symlink, do not follow symlinks (default)
  25    -v  verbose output
  26
  27config CHOWN
  28  bool "chown"
  29  default y
  30  help
  31    see: chgrp
  32*/
  33
  34#define FOR_chgrp
  35#define FORCE_FLAGS
  36#include "toys.h"
  37
  38GLOBALS(
  39  uid_t owner;
  40  gid_t group;
  41  char *owner_name, *group_name;
  42  int symfollow;
  43)
  44
  45static int do_chgrp(struct dirtree *node)
  46{
  47  int fd, ret, flags = toys.optflags;
  48
  49  // Depth first search
  50  if (!dirtree_notdotdot(node)) return 0;
  51  if ((flags & FLAG_R) && !node->again && S_ISDIR(node->st.st_mode))
  52    return DIRTREE_COMEAGAIN|(DIRTREE_SYMFOLLOW*!!(flags&FLAG_L));
  53
  54  fd = dirtree_parentfd(node);
  55  ret = fchownat(fd, node->name, TT.owner, TT.group,
  56    AT_SYMLINK_NOFOLLOW*(!(flags&(FLAG_L|FLAG_H)) && (flags&(FLAG_h|FLAG_R))));
  57
  58  if (ret || (flags & FLAG_v)) {
  59    char *path = dirtree_path(node, 0);
  60    if (flags & FLAG_v)
  61      xprintf("%s %s%s%s %s\n", toys.which->name,
  62        TT.owner_name ? TT.owner_name : "",
  63        toys.which->name[2]=='o' && TT.group_name ? ":" : "",
  64        TT.group_name ? TT.group_name : "", path);
  65    if (ret == -1 && !(toys.optflags & FLAG_f))
  66      perror_msg("'%s' to '%s:%s'", path, TT.owner_name, TT.group_name);
  67    free(path);
  68  }
  69  toys.exitval |= ret;
  70
  71  return 0;
  72}
  73
  74void chgrp_main(void)
  75{
  76  int ischown = toys.which->name[2] == 'o';
  77  char **s, *own;
  78
  79  TT.owner = TT.group = -1;
  80
  81  // Distinguish chown from chgrp
  82  if (ischown) {
  83    char *grp;
  84
  85    own = xstrdup(*toys.optargs);
  86    if ((grp = strchr(own, ':')) || (grp = strchr(own, '.'))) {
  87      *(grp++) = 0;
  88      TT.group_name = grp;
  89    }
  90    if (*own) TT.owner = xgetuid(TT.owner_name = own);
  91  } else TT.group_name = *toys.optargs;
  92
  93  if (TT.group_name && *TT.group_name)
  94    TT.group = xgetgid(TT.group_name);
  95
  96  for (s=toys.optargs+1; *s; s++)
  97    dirtree_flagread(*s, DIRTREE_SYMFOLLOW*!!(toys.optflags&(FLAG_H|FLAG_L)),
  98      do_chgrp);
  99
 100  if (CFG_TOYBOX_FREE && ischown) free(own);
 101}
 102
 103void chown_main()
 104{
 105  chgrp_main();
 106}
 107