chgrp.c 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  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. USE_CHGRP(NEWTOY(chgrp, "<2h(no-dereference)PLHRfv[-HLP]", TOYFLAG_BIN))
  8. USE_CHOWN(OLDTOY(chown, chgrp, TOYFLAG_BIN))
  9. config CHGRP
  10. bool "chgrp"
  11. default y
  12. help
  13. usage: chgrp/chown [-RHLP] [-fvh] GROUP FILE...
  14. Change group of one or more files.
  15. -f Suppress most error messages
  16. -h Change symlinks instead of what they point to
  17. -R Recurse into subdirectories (implies -h)
  18. -H With -R change target of symlink, follow command line symlinks
  19. -L With -R change target of symlink, follow all symlinks
  20. -P With -R change symlink, do not follow symlinks (default)
  21. -v Verbose
  22. config CHOWN
  23. bool "chown"
  24. default y
  25. help
  26. see: chgrp
  27. */
  28. #define FOR_chgrp
  29. #define FORCE_FLAGS
  30. #include "toys.h"
  31. GLOBALS(
  32. uid_t owner;
  33. gid_t group;
  34. char *owner_name, *group_name;
  35. int symfollow;
  36. )
  37. static int do_chgrp(struct dirtree *node)
  38. {
  39. int fd, ret, flags = toys.optflags;
  40. // Depth first search
  41. if (!dirtree_notdotdot(node)) return 0;
  42. if ((flags & FLAG_R) && !node->again && S_ISDIR(node->st.st_mode))
  43. return DIRTREE_COMEAGAIN|(DIRTREE_SYMFOLLOW*!!(flags&FLAG_L));
  44. fd = dirtree_parentfd(node);
  45. ret = fchownat(fd, node->name, TT.owner, TT.group,
  46. AT_SYMLINK_NOFOLLOW*(!(flags&(FLAG_L|FLAG_H)) && (flags&(FLAG_h|FLAG_R))));
  47. if (ret || (flags & FLAG_v)) {
  48. char *path = dirtree_path(node, 0);
  49. if (flags & FLAG_v)
  50. xprintf("%s %s%s%s %s\n", toys.which->name, TT.owner_name,
  51. (toys.which->name[2]=='o' && *TT.group_name) ? ":" : "",
  52. TT.group_name, path);
  53. if (ret == -1 && !(toys.optflags & FLAG_f))
  54. perror_msg("'%s' to '%s:%s'", path, TT.owner_name, TT.group_name);
  55. free(path);
  56. }
  57. toys.exitval |= ret;
  58. return 0;
  59. }
  60. void chgrp_main(void)
  61. {
  62. int ischown = toys.which->name[2] == 'o';
  63. char **s, *own;
  64. TT.owner = TT.group = -1;
  65. TT.owner_name = TT.group_name = "";
  66. // Distinguish chown from chgrp
  67. if (ischown) {
  68. char *grp;
  69. own = xstrdup(*toys.optargs);
  70. if ((grp = strchr(own, ':')) || (grp = strchr(own, '.'))) {
  71. *(grp++) = 0;
  72. TT.group_name = grp;
  73. }
  74. if (*own) TT.owner = xgetuid(TT.owner_name = own);
  75. } else TT.group_name = *toys.optargs;
  76. if (TT.group_name && *TT.group_name)
  77. TT.group = xgetgid(TT.group_name);
  78. for (s=toys.optargs+1; *s; s++)
  79. dirtree_flagread(*s, DIRTREE_SYMFOLLOW*!!(toys.optflags&(FLAG_H|FLAG_L)),
  80. do_chgrp);
  81. if (CFG_TOYBOX_FREE && ischown) free(own);
  82. }