xref: /third_party/toybox/toys/posix/chgrp.c (revision 0f66f451)
10f66f451Sopenharmony_ci/* chgrp.c - Change user and group ownership
20f66f451Sopenharmony_ci *
30f66f451Sopenharmony_ci * Copyright 2012 Georgi Chorbadzhiyski <georgi@unixsol.org>
40f66f451Sopenharmony_ci *
50f66f451Sopenharmony_ci * See http://opengroup.org/onlinepubs/9699919799/utilities/chown.html
60f66f451Sopenharmony_ci * See http://opengroup.org/onlinepubs/9699919799/utilities/chgrp.html
70f66f451Sopenharmony_ci
80f66f451Sopenharmony_ciUSE_CHGRP(NEWTOY(chgrp, "<2hPLHRfv[-HLP]", TOYFLAG_BIN))
90f66f451Sopenharmony_ciUSE_CHOWN(OLDTOY(chown, chgrp, TOYFLAG_BIN))
100f66f451Sopenharmony_ci
110f66f451Sopenharmony_ciconfig CHGRP
120f66f451Sopenharmony_ci  bool "chgrp"
130f66f451Sopenharmony_ci  default y
140f66f451Sopenharmony_ci  help
150f66f451Sopenharmony_ci    usage: chgrp/chown [-RHLP] [-fvh] group file...
160f66f451Sopenharmony_ci
170f66f451Sopenharmony_ci    Change group of one or more files.
180f66f451Sopenharmony_ci
190f66f451Sopenharmony_ci    -f	Suppress most error messages
200f66f451Sopenharmony_ci    -h	Change symlinks instead of what they point to
210f66f451Sopenharmony_ci    -R	Recurse into subdirectories (implies -h)
220f66f451Sopenharmony_ci    -H	With -R change target of symlink, follow command line symlinks
230f66f451Sopenharmony_ci    -L	With -R change target of symlink, follow all symlinks
240f66f451Sopenharmony_ci    -P	With -R change symlink, do not follow symlinks (default)
250f66f451Sopenharmony_ci    -v	Verbose
260f66f451Sopenharmony_ci
270f66f451Sopenharmony_ciconfig CHOWN
280f66f451Sopenharmony_ci  bool "chown"
290f66f451Sopenharmony_ci  default y
300f66f451Sopenharmony_ci  help
310f66f451Sopenharmony_ci    see: chgrp
320f66f451Sopenharmony_ci*/
330f66f451Sopenharmony_ci
340f66f451Sopenharmony_ci#define FOR_chgrp
350f66f451Sopenharmony_ci#define FORCE_FLAGS
360f66f451Sopenharmony_ci#include "toys.h"
370f66f451Sopenharmony_ci
380f66f451Sopenharmony_ciGLOBALS(
390f66f451Sopenharmony_ci  uid_t owner;
400f66f451Sopenharmony_ci  gid_t group;
410f66f451Sopenharmony_ci  char *owner_name, *group_name;
420f66f451Sopenharmony_ci  int symfollow;
430f66f451Sopenharmony_ci)
440f66f451Sopenharmony_ci
450f66f451Sopenharmony_cistatic int do_chgrp(struct dirtree *node)
460f66f451Sopenharmony_ci{
470f66f451Sopenharmony_ci  int fd, ret, flags = toys.optflags;
480f66f451Sopenharmony_ci
490f66f451Sopenharmony_ci  // Depth first search
500f66f451Sopenharmony_ci  if (!dirtree_notdotdot(node)) return 0;
510f66f451Sopenharmony_ci  if ((flags & FLAG_R) && !node->again && S_ISDIR(node->st.st_mode))
520f66f451Sopenharmony_ci    return DIRTREE_COMEAGAIN|(DIRTREE_SYMFOLLOW*!!(flags&FLAG_L));
530f66f451Sopenharmony_ci
540f66f451Sopenharmony_ci  fd = dirtree_parentfd(node);
550f66f451Sopenharmony_ci  ret = fchownat(fd, node->name, TT.owner, TT.group,
560f66f451Sopenharmony_ci    AT_SYMLINK_NOFOLLOW*(!(flags&(FLAG_L|FLAG_H)) && (flags&(FLAG_h|FLAG_R))));
570f66f451Sopenharmony_ci
580f66f451Sopenharmony_ci  if (ret || (flags & FLAG_v)) {
590f66f451Sopenharmony_ci    char *path = dirtree_path(node, 0);
600f66f451Sopenharmony_ci    if (flags & FLAG_v)
610f66f451Sopenharmony_ci      xprintf("%s %s%s%s %s\n", toys.which->name, TT.owner_name,
620f66f451Sopenharmony_ci        (toys.which->name[2]=='o' && *TT.group_name) ? ":" : "",
630f66f451Sopenharmony_ci        TT.group_name, path);
640f66f451Sopenharmony_ci    if (ret == -1 && !(toys.optflags & FLAG_f))
650f66f451Sopenharmony_ci      perror_msg("'%s' to '%s:%s'", path, TT.owner_name, TT.group_name);
660f66f451Sopenharmony_ci    free(path);
670f66f451Sopenharmony_ci  }
680f66f451Sopenharmony_ci  toys.exitval |= ret;
690f66f451Sopenharmony_ci
700f66f451Sopenharmony_ci  return 0;
710f66f451Sopenharmony_ci}
720f66f451Sopenharmony_ci
730f66f451Sopenharmony_civoid chgrp_main(void)
740f66f451Sopenharmony_ci{
750f66f451Sopenharmony_ci  int ischown = toys.which->name[2] == 'o';
760f66f451Sopenharmony_ci  char **s, *own;
770f66f451Sopenharmony_ci
780f66f451Sopenharmony_ci  TT.owner = TT.group = -1;
790f66f451Sopenharmony_ci  TT.owner_name = TT.group_name = "";
800f66f451Sopenharmony_ci
810f66f451Sopenharmony_ci  // Distinguish chown from chgrp
820f66f451Sopenharmony_ci  if (ischown) {
830f66f451Sopenharmony_ci    char *grp;
840f66f451Sopenharmony_ci
850f66f451Sopenharmony_ci    own = xstrdup(*toys.optargs);
860f66f451Sopenharmony_ci    if ((grp = strchr(own, ':')) || (grp = strchr(own, '.'))) {
870f66f451Sopenharmony_ci      *(grp++) = 0;
880f66f451Sopenharmony_ci      TT.group_name = grp;
890f66f451Sopenharmony_ci    }
900f66f451Sopenharmony_ci    if (*own) TT.owner = xgetuid(TT.owner_name = own);
910f66f451Sopenharmony_ci  } else TT.group_name = *toys.optargs;
920f66f451Sopenharmony_ci
930f66f451Sopenharmony_ci  if (TT.group_name && *TT.group_name)
940f66f451Sopenharmony_ci    TT.group = xgetgid(TT.group_name);
950f66f451Sopenharmony_ci
960f66f451Sopenharmony_ci  for (s=toys.optargs+1; *s; s++)
970f66f451Sopenharmony_ci    dirtree_flagread(*s, DIRTREE_SYMFOLLOW*!!(toys.optflags&(FLAG_H|FLAG_L)),
980f66f451Sopenharmony_ci      do_chgrp);
990f66f451Sopenharmony_ci
1000f66f451Sopenharmony_ci  if (CFG_TOYBOX_FREE && ischown) free(own);
1010f66f451Sopenharmony_ci}
1020f66f451Sopenharmony_ci
1030f66f451Sopenharmony_civoid chown_main()
1040f66f451Sopenharmony_ci{
1050f66f451Sopenharmony_ci  chgrp_main();
1060f66f451Sopenharmony_ci}
107