summaryrefslogtreecommitdiff
path: root/usr/src/lib/libcmd/common/chgrp.c
diff options
context:
space:
mode:
authorApril Chin <April.Chin@Sun.COM>2008-12-27 14:59:38 -0800
committerApril Chin <April.Chin@Sun.COM>2008-12-27 14:59:38 -0800
commit7c2fbfb345896881c631598ee3852ce9ce33fb07 (patch)
tree4b173b5657508562dfc0aa05f7d056d1e9add505 /usr/src/lib/libcmd/common/chgrp.c
parent6071ac1de68fed78e1e10052045bbb5f1732a263 (diff)
downloadillumos-joyent-7c2fbfb345896881c631598ee3852ce9ce33fb07.tar.gz
PSARC/2008/094 ksh93 Update 1
PSARC/2008/344 ksh93 Integration Update 1 Amendments 1 PSARC/2008/589 Remove /usr/bin/printf from PSARC case 2008 094 6619428 *ksh93* RFE: Update ksh93 in Solaris to ast-ksh.2008-11-04 6788659 RFE: Update libpp in Solaris to ast-open.2008-07-25 6561901 RFE: Add "shcomp" (shell script compiler) + kernel module to exec binary sh code 6599668 RFE: Move consumers of alias.sh over to ksh93 6595183 *ksh93* RFE: Update ksh93-integration demo code 6775901 *ksh93* no C message catalogs are generated for ksh93 6451262 *sleep* RFE: /usr/bin/sleep should support floating-point values 6687139 *ksh93* command substitution, exec, and stdout redirection cause allocation loop 6703761 *ksh93* crashes in script containing uncommon output redirections 6715496 *ksh93* SEGVs on array reinitialization 6713682 *ksh93* Creating a compound variable in a subshell "bleeds through" to the calling subshell 6672350 *ksh93* causes parent shell to die when child shell is suspended 6745015 *ksh93* VARIABLE=`command substitution` assignment is not reliable on OpenSolaris 6710205 *ksh93* problem with command substitution (within back quotes) containing \$' 6737600 *ksh93* exits debugger when user presses ctrl-c 6748645 *ksh93* fc -l -e - is mis-parsed, outputs wrong error message "-e - requires single argument" 6754020 *ksh93* does weird '[' expansion 6753538 *ksh93* umask modification leaks out of a ksh93 subshell 6766246 *ksh93* bug in pattern matching 6763594 *ksh93* executes command after "command" builtin twice on failure 6762665 *ksh93* Difficult-to-reproduce SIGSEGV in ksh93
Diffstat (limited to 'usr/src/lib/libcmd/common/chgrp.c')
-rw-r--r--usr/src/lib/libcmd/common/chgrp.c184
1 files changed, 101 insertions, 83 deletions
diff --git a/usr/src/lib/libcmd/common/chgrp.c b/usr/src/lib/libcmd/common/chgrp.c
index 5538f5e310..5525157070 100644
--- a/usr/src/lib/libcmd/common/chgrp.c
+++ b/usr/src/lib/libcmd/common/chgrp.c
@@ -1,10 +1,10 @@
/***********************************************************************
* *
* This software is part of the ast package *
-* Copyright (c) 1992-2007 AT&T Knowledge Ventures *
+* Copyright (c) 1992-2008 AT&T Intellectual Property *
* and is licensed under the *
* Common Public License, Version 1.0 *
-* by AT&T Knowledge Ventures *
+* by AT&T Intellectual Property *
* *
* A copy of the License is available at *
* http://www.opensource.org/licenses/cpl1.0.txt *
@@ -28,7 +28,7 @@
*/
static const char usage_1[] =
-"[-?@(#)$Id: chgrp (AT&T Research) 2006-10-11 $\n]"
+"[-?@(#)$Id: chgrp (AT&T Research) 2008-03-28 $\n]"
USAGE_LICENSE
;
@@ -49,24 +49,34 @@ static const char usage_own_1[] =
;
static const char usage_2[] =
+"[b:before?Only change files with \bctime\b before (less than) the "
+ "\bmtime\b of \afile\a.]:[file]"
"[c:changes?Describe only files whose ownership actually changes.]"
"[f:quiet|silent?Do not report files whose ownership fails to change.]"
-"[l|h:symlink?Change the ownership of the symbolic links on systems that"
-" support this.]"
-"[m:map?The first operand is interpreted as a file that contains a map"
-" of \afrom_uid:from_gid to_uid:to_gid\a pairs. Ownership of files"
-" matching the \afrom\a part of any pair is changed to the corresponding"
-" \ato\a part of the pair. The process stops at the first match for"
-" each file. Unmatched files are silently ignored.]"
+"[l|h:symlink?Change the ownership of the symbolic links on systems that "
+ "support this.]"
+"[m:map?The first operand is interpreted as a file that contains a map "
+ "of space separated \afrom_uid:from_gid to_uid:to_gid\a pairs. The "
+ "\auid\a or \agid\a part of each pair may be omitted to mean any \auid\a "
+ "or \agid\a. Ownership of files matching the \afrom\a part of any pair "
+ "is changed to the corresponding \ato\a part of the pair. The matching "
+ "for each file operand is in the order \auid\a:\agid\a, \auid\a:, "
+ ":\agid\a. For a given file, once a \auid\a or \agid\a mapping is "
+ "determined it is not overridden by any subsequent match. Unmatched "
+ "files are silently ignored.]"
"[n:show?Show actions but don't execute.]"
-"[r:reference?Omit the explicit ownership operand and use the ownership of"
-" \afile\a instead.]:[file]"
+"[r:reference?Omit the explicit ownership operand and use the ownership "
+ "of \afile\a instead.]:[file]"
+"[u:unmapped?Print a diagnostic for each file for which either the "
+ "\auid\a or \agid\a or both were not mapped.]"
"[v:verbose?Describe changed permissions of all files.]"
-"[H:metaphysical?Follow symbolic links for command arguments; otherwise don't"
-" follow symbolic links when traversing directories.]"
+"[H:metaphysical?Follow symbolic links for command arguments; otherwise "
+ "don't follow symbolic links when traversing directories.]"
"[L:logical|follow?Follow symbolic links when traversing directories.]"
-"[P:physical|nofollow?Don't follow symbolic links when traversing directories.]"
-"[R:recursive?Recursively change ownership of directories and their contents.]"
+"[P:physical|nofollow?Don't follow symbolic links when traversing "
+ "directories.]"
+"[R:recursive?Recursively change ownership of directories and their "
+ "contents.]"
"[X:test?Canonicalize output for testing.]"
"\n"
@@ -103,12 +113,17 @@ __STDPP__directive pragma pp:nohide lchown
#undef lchown
#endif
-typedef struct /* uid/gid map */
+typedef struct Key_s /* uid/gid key */
+{
+ int uid; /* uid */
+ int gid; /* gid */
+} Key_t;
+
+typedef struct Map_s /* uid/gid map */
{
Dtlink_t link; /* dictionary link */
- int id; /* id */
- int uid; /* id maps to this uid */
- int gid; /* id maps to this gid */
+ Key_t key; /* key */
+ Key_t to; /* map to these */
} Map_t;
#define NOID (-1)
@@ -120,7 +135,8 @@ typedef struct /* uid/gid map */
#define OPT_SHOW (1<<4) /* show but don't do */
#define OPT_TEST (1<<5) /* canonicalize output */
#define OPT_UID (1<<6) /* have uid */
-#define OPT_VERBOSE (1<<7) /* have uid */
+#define OPT_UNMAPPED (1<<7) /* unmapped file diagnostic */
+#define OPT_VERBOSE (1<<8) /* have uid */
extern int lchown(const char*, uid_t, gid_t);
@@ -143,14 +159,14 @@ lchown(const char* path, uid_t uid, gid_t gid)
*/
static void
-getids(register char* s, char** e, int* uid, int* gid, int options)
+getids(register char* s, char** e, Key_t* key, int options)
{
register char* t;
register int n;
char* z;
char buf[64];
- *uid = *gid = NOID;
+ key->uid = key->gid = NOID;
while (isspace(*s))
s++;
for (t = s; (n = *t) && n != ':' && n != '.' && !isspace(n); t++);
@@ -160,8 +176,6 @@ getids(register char* s, char** e, int* uid, int* gid, int options)
if ((n = t++ - s) >= sizeof(buf))
n = sizeof(buf) - 1;
*((s = (char*)memcpy(buf, s, n)) + n) = 0;
- while (isspace(*t))
- t++;
}
if (options & OPT_CHOWN)
{
@@ -173,7 +187,7 @@ getids(register char* s, char** e, int* uid, int* gid, int options)
if (*z)
error(ERROR_exit(1), "%s: unknown user", s);
}
- *uid = n;
+ key->uid = n;
}
for (s = t; (n = *t) && !isspace(n); t++);
if (n)
@@ -191,7 +205,7 @@ getids(register char* s, char** e, int* uid, int* gid, int options)
if (*z)
error(ERROR_exit(1), "%s: unknown group", s);
}
- *gid = n;
+ key->gid = n;
}
if (e)
*e = t;
@@ -205,19 +219,25 @@ b_chgrp(int argc, char** argv, void* context)
register Map_t* m;
register FTS* fts;
register FTSENT*ent;
+ register int i;
Dt_t* map = 0;
int flags;
int uid;
int gid;
char* op;
char* usage;
+ char* t;
Sfio_t* sp;
+ unsigned long before;
Dtdisc_t mapdisc;
+ Key_t keys[3];
+ Key_t key;
struct stat st;
int (*chownf)(const char*, uid_t, gid_t);
cmdinit(argc, argv, context, ERROR_CATALOG, ERROR_NOTIFY);
flags = fts_flags() | FTS_TOP | FTS_NOPOSTORDER | FTS_NOSEEDOTDIR;
+ before = ~0;
if (!(sp = sfstropen()))
error(ERROR_SYSTEM|3, "out of space");
sfputr(sp, usage_1, -1);
@@ -240,6 +260,11 @@ b_chgrp(int argc, char** argv, void* context)
{
switch (optget(argv, usage))
{
+ case 'b':
+ if (stat(opt_info.arg, &st))
+ error(ERROR_exit(1), "%s: cannot stat", opt_info.arg);
+ before = st.st_mtime;
+ continue;
case 'c':
case 'v':
options |= OPT_VERBOSE;
@@ -252,8 +277,8 @@ b_chgrp(int argc, char** argv, void* context)
continue;
case 'm':
memset(&mapdisc, 0, sizeof(mapdisc));
- mapdisc.key = offsetof(Map_t, id);
- mapdisc.size = sizeof(int);
+ mapdisc.key = offsetof(Map_t, key);
+ mapdisc.size = sizeof(Key_t);
if (!(map = dtopen(&mapdisc, Dthash)))
error(ERROR_exit(1), "out of space [id map]");
continue;
@@ -267,6 +292,9 @@ b_chgrp(int argc, char** argv, void* context)
gid = st.st_gid;
options |= OPT_UID|OPT_GID;
continue;
+ case 'u':
+ options |= OPT_UNMAPPED;
+ continue;
case 'H':
flags |= FTS_META|FTS_PHYSICAL;
continue;
@@ -299,60 +327,33 @@ b_chgrp(int argc, char** argv, void* context)
s = *argv;
if (map)
{
- char* t;
- int nuid;
- int ngid;
-
if (streq(s, "-"))
sp = sfstdin;
else if (!(sp = sfopen(NiL, s, "r")))
error(ERROR_exit(1), "%s: cannot read", s);
while (s = sfgetr(sp, '\n', 1))
{
- getids(s, &t, &uid, &gid, options);
- getids(t, NiL, &nuid, &ngid, options);
- if (uid != NOID)
- {
- if (m = (Map_t*)dtmatch(map, &uid))
- {
- m->uid = nuid;
- if (m->gid == NOID)
- m->gid = ngid;
- }
- else if (m = (Map_t*)stakalloc(sizeof(Map_t)))
- {
- m->id = uid;
- m->uid = nuid;
- m->gid = ngid;
- dtinsert(map, m);
- }
- else
- error(ERROR_exit(1), "out of space [id dictionary]");
- }
- if (gid != NOID)
+ getids(s, &t, &key, options);
+ if (!(m = (Map_t*)dtmatch(map, &key)))
{
- if (gid == uid || (m = (Map_t*)dtmatch(map, &gid)))
- m->gid = ngid;
- else if (m = (Map_t*)stakalloc(sizeof(Map_t)))
- {
- m->id = gid;
- m->uid = NOID;
- m->gid = ngid;
- dtinsert(map, m);
- }
- else
+ if (!(m = (Map_t*)stakalloc(sizeof(Map_t))))
error(ERROR_exit(1), "out of space [id dictionary]");
+ m->key = key;
+ m->to.uid = m->to.gid = NOID;
+ dtinsert(map, m);
}
+ getids(t, NiL, &m->to, options);
}
if (sp != sfstdin)
sfclose(sp);
+ keys[1].gid = keys[2].uid = NOID;
}
else if (!(options & (OPT_UID|OPT_GID)))
{
- getids(s, NiL, &uid, &gid, options);
- if (uid != NOID)
+ getids(s, NiL, &key, options);
+ if ((uid = key.uid) != NOID)
options |= OPT_UID;
- if (gid != NOID)
+ if ((gid = key.gid) != NOID)
options |= OPT_GID;
}
switch (options & (OPT_UID|OPT_GID))
@@ -372,7 +373,7 @@ b_chgrp(int argc, char** argv, void* context)
}
if (!(fts = fts_open(argv + 1, flags, NiL)))
error(ERROR_system(1), "%s: not found", argv[1]);
- while (!cmdquit() && (ent = fts_read(fts)))
+ while (!sh_checksig(context) && (ent = fts_read(fts)))
switch (ent->fts_info)
{
case FTS_F:
@@ -380,23 +381,31 @@ b_chgrp(int argc, char** argv, void* context)
case FTS_SL:
case FTS_SLNONE:
anyway:
+ if ((unsigned long)ent->fts_statp->st_ctime >= before)
+ break;
if (map)
{
options &= ~(OPT_UID|OPT_GID);
- uid = ent->fts_statp->st_uid;
- gid = ent->fts_statp->st_gid;
- if ((m = (Map_t*)dtmatch(map, &uid)) && m->uid != NOID)
- {
- uid = m->uid;
- options |= OPT_UID;
- }
- if (gid != uid)
- m = (Map_t*)dtmatch(map, &gid);
- if (m && m->gid != NOID)
+ uid = gid = NOID;
+ keys[0].uid = keys[1].uid = ent->fts_statp->st_uid;
+ keys[0].gid = keys[2].gid = ent->fts_statp->st_gid;
+ i = 0;
+ do
{
- gid = m->gid;
- options |= OPT_GID;
- }
+ if (m = (Map_t*)dtmatch(map, &keys[i]))
+ {
+ if (uid == NOID && m->to.uid != NOID)
+ {
+ uid = m->to.uid;
+ options |= OPT_UID;
+ }
+ if (gid == NOID && m->to.gid != NOID)
+ {
+ gid = m->to.gid;
+ options |= OPT_GID;
+ }
+ }
+ } while (++i < elementsof(keys) && (uid == NOID || gid == NOID));
}
else
{
@@ -405,7 +414,16 @@ b_chgrp(int argc, char** argv, void* context)
if (!(options & OPT_GID))
gid = ent->fts_statp->st_gid;
}
- if (uid != ent->fts_statp->st_uid || gid != ent->fts_statp->st_gid)
+ if ((options & OPT_UNMAPPED) && (uid == NOID || gid == NOID))
+ {
+ if (uid == NOID && gid == NOID)
+ error(ERROR_warn(0), "%s: uid and gid not mapped", ent->fts_path);
+ else if (uid == NOID)
+ error(ERROR_warn(0), "%s: uid not mapped", ent->fts_path);
+ else
+ error(ERROR_warn(0), "%s: gid not mapped", ent->fts_path);
+ }
+ if (uid != ent->fts_statp->st_uid && uid != NOID || gid != ent->fts_statp->st_gid && gid != NOID)
{
if ((ent->fts_info & FTS_SL) && (flags & FTS_PHYSICAL) && (options & OPT_LCHOWN))
{
@@ -424,7 +442,7 @@ b_chgrp(int argc, char** argv, void* context)
ent->fts_statp->st_uid = 0;
ent->fts_statp->st_gid = 0;
}
- 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_accpath);
+ 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);
}
if (!(options & OPT_SHOW) && (*chownf)(ent->fts_accpath, uid, gid) && !(options & OPT_FORCE))
error(ERROR_system(0), "%s: cannot change%s", ent->fts_accpath, s);