da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/***********************************************************************
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* This software is part of the ast package *
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner* Copyright (c) 1992-2010 AT&T Intellectual Property *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* and is licensed under the *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* Common Public License, Version 1.0 *
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin* by AT&T Intellectual Property *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* A copy of the License is available at *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* http://www.opensource.org/licenses/cpl1.0.txt *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* Information and Software Systems Research *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* AT&T Research *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* Florham Park NJ *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* Glenn Fowler <gsf@research.att.com> *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* David Korn <dgk@research.att.com> *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin***********************************************************************/
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#pragma prototyped
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/*
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * David Korn
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * Glenn Fowler
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * AT&T Research
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * chgrp+chown
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstatic const char usage_1[] =
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz"[-?@(#)$Id: chgrp (AT&T Research) 2009-07-02 $\n]"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinUSAGE_LICENSE
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstatic const char usage_grp_1[] =
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin"[+NAME?chgrp - change the group ownership of files]"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin"[+DESCRIPTION?\bchgrp\b changes the group ownership of each file"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin" to \agroup\a, which can be either a group name or a numeric"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin" group id. The user ownership of each file may also be changed to"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin" \auser\a by prepending \auser\a\b:\b to the group name.]"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstatic const char usage_own_1[] =
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin"[+NAME?chown - change the ownership of files]"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin"[+DESCRIPTION?\bchown\b changes the ownership of each file"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin" to \auser\a, which can be either a user name or a numeric"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin" user id. The group ownership of each file may also be changed to"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin" \auser\a by appending \b:\b\agroup\a to the user name.]"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstatic const char usage_2[] =
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin"[b:before?Only change files with \bctime\b before (less than) the "
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin "\bmtime\b of \afile\a.]:[file]"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin"[c:changes?Describe only files whose ownership actually changes.]"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin"[f:quiet|silent?Do not report files whose ownership fails to change.]"
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin"[l|h:symlink?Change the ownership of the symbolic links on systems that "
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin "support this.]"
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin"[m:map?The first operand is interpreted as a file that contains a map "
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin "of space separated \afrom_uid:from_gid to_uid:to_gid\a pairs. The "
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin "\auid\a or \agid\a part of each pair may be omitted to mean any \auid\a "
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin "or \agid\a. Ownership of files matching the \afrom\a part of any pair "
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin "is changed to the corresponding \ato\a part of the pair. The matching "
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin "for each file operand is in the order \auid\a:\agid\a, \auid\a:, "
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin ":\agid\a. For a given file, once a \auid\a or \agid\a mapping is "
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin "determined it is not overridden by any subsequent match. Unmatched "
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin "files are silently ignored.]"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin"[n:show?Show actions but don't execute.]"
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin"[r:reference?Omit the explicit ownership operand and use the ownership "
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin "of \afile\a instead.]:[file]"
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin"[u:unmapped?Print a diagnostic for each file for which either the "
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin "\auid\a or \agid\a or both were not mapped.]"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin"[v:verbose?Describe changed permissions of all files.]"
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin"[H:metaphysical?Follow symbolic links for command arguments; otherwise "
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin "don't follow symbolic links when traversing directories.]"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin"[L:logical|follow?Follow symbolic links when traversing directories.]"
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin"[P:physical|nofollow?Don't follow symbolic links when traversing "
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin "directories.]"
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin"[R:recursive?Recursively change ownership of directories and their "
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin "contents.]"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin"[X:test?Canonicalize output for testing.]"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin"\n"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin"\n"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstatic const char usage_3[] =
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin" file ...\n"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin"\n"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin"[+EXIT STATUS?]{"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin "[+0?All files changed successfully.]"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin "[+>0?Unable to change ownership of one or more files.]"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin"}"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin"[+SEE ALSO?\bchmod\b(1), \btw\b(1), \bgetconf\b(1), \bls\b(1)]"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#if defined(__STDPP__directive) && defined(__STDPP__hide)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin__STDPP__directive pragma pp:hide lchown
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define lchown ______lchown
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#include <cmd.h>
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#include <cdt.h>
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#include <ls.h>
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#include <ctype.h>
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner#include <fts_fix.h>
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#include "FEATURE/symlink"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#if defined(__STDPP__directive) && defined(__STDPP__hide)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin__STDPP__directive pragma pp:nohide lchown
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#undef lchown
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chintypedef struct Key_s /* uid/gid key */
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin{
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin int uid; /* uid */
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin int gid; /* gid */
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin} Key_t;
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chintypedef struct Map_s /* uid/gid map */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin{
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin Dtlink_t link; /* dictionary link */
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin Key_t key; /* key */
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin Key_t to; /* map to these */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin} Map_t;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define NOID (-1)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define OPT_CHOWN (1<<0) /* chown */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define OPT_FORCE (1<<1) /* ignore errors */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define OPT_GID (1<<2) /* have gid */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define OPT_LCHOWN (1<<3) /* lchown */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define OPT_SHOW (1<<4) /* show but don't do */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define OPT_TEST (1<<5) /* canonicalize output */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define OPT_UID (1<<6) /* have uid */
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin#define OPT_UNMAPPED (1<<7) /* unmapped file diagnostic */
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin#define OPT_VERBOSE (1<<8) /* have uid */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinextern int lchown(const char*, uid_t, gid_t);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#if !_lib_lchown
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#ifndef ENOSYS
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define ENOSYS EINVAL
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinint
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinlchown(const char* path, uid_t uid, gid_t gid)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin{
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return ENOSYS;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin}
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif /* _lib_chown */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/*
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * parse uid and gid from s
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstatic void
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chingetids(register char* s, char** e, Key_t* key, int options)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin{
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register char* t;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register int n;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin char* z;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin char buf[64];
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin key->uid = key->gid = NOID;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin while (isspace(*s))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin s++;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin for (t = s; (n = *t) && n != ':' && n != '.' && !isspace(n); t++);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (n)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin options |= OPT_CHOWN;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if ((n = t++ - s) >= sizeof(buf))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin n = sizeof(buf) - 1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin *((s = (char*)memcpy(buf, s, n)) + n) = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (options & OPT_CHOWN)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (*s)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if ((n = struid(s)) == NOID)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin n = (int)strtol(s, &z, 0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (*z)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin error(ERROR_exit(1), "%s: unknown user", s);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin key->uid = n;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin for (s = t; (n = *t) && !isspace(n); t++);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (n)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if ((n = t++ - s) >= sizeof(buf))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin n = sizeof(buf) - 1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin *((s = (char*)memcpy(buf, s, n)) + n) = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (*s)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if ((n = strgid(s)) == NOID)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin n = (int)strtol(s, &z, 0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (*z)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin error(ERROR_exit(1), "%s: unknown group", s);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin key->gid = n;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (e)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin *e = t;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin}
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinint
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinb_chgrp(int argc, char** argv, void* context)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin{
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register int options = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register char* s;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register Map_t* m;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register FTS* fts;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register FTSENT*ent;
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin register int i;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin Dt_t* map = 0;
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz int logical = 1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin int flags;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin int uid;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin int gid;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin char* op;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin char* usage;
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin char* t;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin Sfio_t* sp;
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin unsigned long before;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin Dtdisc_t mapdisc;
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin Key_t keys[3];
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin Key_t key;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin struct stat st;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin int (*chownf)(const char*, uid_t, gid_t);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin cmdinit(argc, argv, context, ERROR_CATALOG, ERROR_NOTIFY);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin flags = fts_flags() | FTS_TOP | FTS_NOPOSTORDER | FTS_NOSEEDOTDIR;
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin before = ~0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (!(sp = sfstropen()))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin error(ERROR_SYSTEM|3, "out of space");
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sfputr(sp, usage_1, -1);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (error_info.id[2] == 'g')
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sfputr(sp, usage_grp_1, -1);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sfputr(sp, usage_own_1, -1);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin options |= OPT_CHOWN;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sfputr(sp, usage_2, -1);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (options & OPT_CHOWN)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sfputr(sp, ERROR_translate(0, 0, 0, "[owner[:group]]"), -1);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sfputr(sp, ERROR_translate(0, 0, 0, "[[owner:]group]"), -1);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sfputr(sp, usage_3, -1);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (!(usage = sfstruse(sp)))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin error(ERROR_SYSTEM|3, "out of space");
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin for (;;)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin switch (optget(argv, usage))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin case 'b':
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin if (stat(opt_info.arg, &st))
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin error(ERROR_exit(1), "%s: cannot stat", opt_info.arg);
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin before = st.st_mtime;
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin continue;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case 'c':
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case 'v':
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin options |= OPT_VERBOSE;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin continue;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case 'f':
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin options |= OPT_FORCE;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin continue;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case 'l':
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin options |= OPT_LCHOWN;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin continue;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case 'm':
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin memset(&mapdisc, 0, sizeof(mapdisc));
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin mapdisc.key = offsetof(Map_t, key);
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin mapdisc.size = sizeof(Key_t);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (!(map = dtopen(&mapdisc, Dthash)))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin error(ERROR_exit(1), "out of space [id map]");
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin continue;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case 'n':
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin options |= OPT_SHOW;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin continue;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case 'r':
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (stat(opt_info.arg, &st))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin error(ERROR_exit(1), "%s: cannot stat", opt_info.arg);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin uid = st.st_uid;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin gid = st.st_gid;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin options |= OPT_UID|OPT_GID;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin continue;
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin case 'u':
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin options |= OPT_UNMAPPED;
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin continue;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case 'H':
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin flags |= FTS_META|FTS_PHYSICAL;
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz logical = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin continue;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case 'L':
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin flags &= ~(FTS_META|FTS_PHYSICAL);
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz logical = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin continue;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case 'P':
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin flags &= ~FTS_META;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin flags |= FTS_PHYSICAL;
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz logical = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin continue;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case 'R':
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin flags &= ~FTS_TOP;
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz logical = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin continue;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case 'X':
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin options |= OPT_TEST;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin continue;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case ':':
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin error(2, "%s", opt_info.arg);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin continue;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case '?':
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin error(ERROR_usage(2), "%s", opt_info.arg);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin argv += opt_info.index;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin argc -= opt_info.index;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (error_info.errors || argc < 2)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin error(ERROR_usage(2), "%s", optusage(NiL));
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin s = *argv;
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz if (logical)
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz flags &= ~(FTS_META|FTS_PHYSICAL);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (map)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (streq(s, "-"))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sp = sfstdin;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if (!(sp = sfopen(NiL, s, "r")))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin error(ERROR_exit(1), "%s: cannot read", s);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin while (s = sfgetr(sp, '\n', 1))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin getids(s, &t, &key, options);
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin if (!(m = (Map_t*)dtmatch(map, &key)))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin if (!(m = (Map_t*)stakalloc(sizeof(Map_t))))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin error(ERROR_exit(1), "out of space [id dictionary]");
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin m->key = key;
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin m->to.uid = m->to.gid = NOID;
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin dtinsert(map, m);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin getids(t, NiL, &m->to, options);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (sp != sfstdin)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sfclose(sp);
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin keys[1].gid = keys[2].uid = NOID;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if (!(options & (OPT_UID|OPT_GID)))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin getids(s, NiL, &key, options);
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin if ((uid = key.uid) != NOID)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin options |= OPT_UID;
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin if ((gid = key.gid) != NOID)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin options |= OPT_GID;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin switch (options & (OPT_UID|OPT_GID))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case OPT_UID:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin s = ERROR_translate(0, 0, 0, " owner");
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case OPT_GID:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin s = ERROR_translate(0, 0, 0, " group");
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case OPT_UID|OPT_GID:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin s = ERROR_translate(0, 0, 0, " owner and group");
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin default:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin s = "";
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (!(fts = fts_open(argv + 1, flags, NiL)))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin error(ERROR_system(1), "%s: not found", argv[1]);
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin while (!sh_checksig(context) && (ent = fts_read(fts)))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin switch (ent->fts_info)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case FTS_F:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case FTS_D:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case FTS_SL:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case FTS_SLNONE:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin anyway:
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin if ((unsigned long)ent->fts_statp->st_ctime >= before)
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (map)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin options &= ~(OPT_UID|OPT_GID);
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin uid = gid = NOID;
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin keys[0].uid = keys[1].uid = ent->fts_statp->st_uid;
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin keys[0].gid = keys[2].gid = ent->fts_statp->st_gid;
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin i = 0;
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin do
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin if (m = (Map_t*)dtmatch(map, &keys[i]))
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin {
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin if (uid == NOID && m->to.uid != NOID)
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin {
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin uid = m->to.uid;
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin options |= OPT_UID;
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin }
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin if (gid == NOID && m->to.gid != NOID)
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin {
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin gid = m->to.gid;
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin options |= OPT_GID;
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin }
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin }
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin } while (++i < elementsof(keys) && (uid == NOID || gid == NOID));
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (!(options & OPT_UID))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin uid = ent->fts_statp->st_uid;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (!(options & OPT_GID))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin gid = ent->fts_statp->st_gid;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin if ((options & OPT_UNMAPPED) && (uid == NOID || gid == NOID))
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin {
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin if (uid == NOID && gid == NOID)
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin error(ERROR_warn(0), "%s: uid and gid not mapped", ent->fts_path);
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin else if (uid == NOID)
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin error(ERROR_warn(0), "%s: uid not mapped", ent->fts_path);
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin else
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin error(ERROR_warn(0), "%s: gid not mapped", ent->fts_path);
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin }
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin if (uid != ent->fts_statp->st_uid && uid != NOID || gid != ent->fts_statp->st_gid && gid != NOID)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if ((ent->fts_info & FTS_SL) && (flags & FTS_PHYSICAL) && (options & OPT_LCHOWN))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin op = "lchown";
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin chownf = lchown;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin op = "chown";
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin chownf = chown;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (options & (OPT_SHOW|OPT_VERBOSE))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (options & OPT_TEST)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin ent->fts_statp->st_uid = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin ent->fts_statp->st_gid = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin sfprintf(sfstdout, "%s uid:%05d->%05d gid:%05d->%05d %s\n", op, ent->fts_statp->st_uid, uid, ent->fts_statp->st_gid, gid, ent->fts_path);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (!(options & OPT_SHOW) && (*chownf)(ent->fts_accpath, uid, gid) && !(options & OPT_FORCE))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin error(ERROR_system(0), "%s: cannot change%s", ent->fts_accpath, s);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case FTS_DC:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (!(options & OPT_FORCE))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin error(ERROR_warn(0), "%s: directory causes cycle", ent->fts_accpath);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case FTS_DNR:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (!(options & OPT_FORCE))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin error(ERROR_system(0), "%s: cannot read directory", ent->fts_accpath);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin goto anyway;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case FTS_DNX:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (!(options & OPT_FORCE))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin error(ERROR_system(0), "%s: cannot search directory", ent->fts_accpath);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin goto anyway;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case FTS_NS:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (!(options & OPT_FORCE))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin error(ERROR_system(0), "%s: not found", ent->fts_accpath);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin fts_close(fts);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (map)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin dtclose(map);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return error_info.errors != 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin}