mirror of
git://git.code.sf.net/p/cdesktopenv/code
synced 2025-03-09 15:50:02 +00:00
The chown
builtin should fail with the same error consistently (#378)
This bug was first reported at <https://www.illumos.org/issues/3782>. The chown builtin when used on illumos can fail with different error messages after running the same command twice: $ touch /tmp/x $ /opt/ast/bin/chown -h 433:434 /tmp/px chown: /tmp/x: cannot change owner and group [Not owner] $ /opt/ast/bin/chown -h 433:434 /tmp/px chown: /tmp/x: cannot change owner and group [Invalid argument] The error messages differ because the libast struid and strgid functions will return -2 if the same nonexistent ID is used twice. The fix for this bug has been ported from here:4162633a7c
src/lib/libcmd/chgrp.c: - Remove NOID macro and check for a < 0 error status instead. This is different from the Illumos fix at <4162633a7c
> which added another macro. src/lib/libast/man/{strgid,struid}.3: - Correct errors in the strgid and struid documentation. - Document that the strgid and struid functions will return -2 if the same invalid name is used twice. Co-authored-by: Martijn Dekker <martijn@inlv.org>
This commit is contained in:
parent
c0354a869f
commit
61fa1b68bf
4 changed files with 38 additions and 25 deletions
5
NEWS
5
NEWS
|
@ -8,6 +8,11 @@ Any uppercase BUG_* names are modernish shell bug IDs.
|
|||
- Fixed a bug introduced on 2020-08-09 that prevented '.' and '..' from
|
||||
being completed when using file name tab completion.
|
||||
|
||||
- Fixed a bug on illumos that caused the chown builtin to fail with 'Invalid
|
||||
argument' after failing to change the ownership of a file twice using an ID
|
||||
that doesn't exist in /etc/passwd. (Note that the chown builtin is not
|
||||
enabled by default.)
|
||||
|
||||
2021-12-11:
|
||||
|
||||
- Fixed two more crashing bugs that occurred if ksh received a signal (such
|
||||
|
|
|
@ -38,16 +38,21 @@
|
|||
..
|
||||
.TH STRGID 3
|
||||
.SH NAME
|
||||
strgid \- return group name given group number
|
||||
strgid \- return group ID number for given group name
|
||||
.SH SYNOPSIS
|
||||
.L "char* strgid(int gid)"
|
||||
.L "int strgid(const char* name)"
|
||||
.SH DESCRIPTION
|
||||
.I strgid
|
||||
returns the group id name string given the group number
|
||||
.IR gid .
|
||||
returns the group ID number for the given group name.
|
||||
.I strgid
|
||||
maintains an internal cache to avoid repeated password database scans
|
||||
by the low level
|
||||
.IR getgrgid (3).
|
||||
On the first error for a given name,
|
||||
.I strgid
|
||||
returns -1.
|
||||
Subsequent errors for the same name will result in
|
||||
.I strgid
|
||||
returning -2 instead.
|
||||
.SH "SEE ALSO"
|
||||
getgrent(3)
|
||||
|
|
|
@ -38,16 +38,21 @@
|
|||
..
|
||||
.TH STRUID 3
|
||||
.SH NAME
|
||||
struid \- return user name given user number
|
||||
struid \- return user ID number for given user name
|
||||
.SH SYNOPSIS
|
||||
.L "char* struid(int uid)"
|
||||
.L "int struid(const char* name)"
|
||||
.SH DESCRIPTION
|
||||
.I struid
|
||||
returns the user id name string given the user number
|
||||
.IR uid .
|
||||
returns the user ID number for the given user name.
|
||||
.I struid
|
||||
maintains an internal cache to avoid repeated password database scans
|
||||
by the low level
|
||||
.IR getpwuid (3).
|
||||
On the first error for a given name,
|
||||
.I struid
|
||||
returns -1.
|
||||
Subsequent errors for the same name will result in
|
||||
.I struid
|
||||
returning -2 instead.
|
||||
.SH "SEE ALSO"
|
||||
getpwent(3)
|
||||
|
|
|
@ -131,8 +131,6 @@ typedef struct Map_s /* uid/gid map */
|
|||
Key_t to; /* map to these */
|
||||
} Map_t;
|
||||
|
||||
#define NOID (-1)
|
||||
|
||||
#define OPT_CHOWN 0x0001 /* chown */
|
||||
#define OPT_FORCE 0x0002 /* ignore errors */
|
||||
#define OPT_GID 0x0004 /* have gid */
|
||||
|
@ -159,7 +157,7 @@ getids(register char* s, char** e, Key_t* key, int options)
|
|||
char* z;
|
||||
char buf[64];
|
||||
|
||||
key->uid = key->gid = NOID;
|
||||
key->uid = key->gid = -1;
|
||||
while (isspace(*s))
|
||||
s++;
|
||||
for (t = s; (n = *t) && n != ':' && n != '.' && !isspace(n); t++);
|
||||
|
@ -177,7 +175,7 @@ getids(register char* s, char** e, Key_t* key, int options)
|
|||
n = (int)strtol(s, &z, 0);
|
||||
if (*z || !(options & OPT_NUMERIC))
|
||||
{
|
||||
if ((m = struid(s)) != NOID)
|
||||
if ((m = struid(s)) >= 0)
|
||||
n = m;
|
||||
else if (*z)
|
||||
{
|
||||
|
@ -200,7 +198,7 @@ getids(register char* s, char** e, Key_t* key, int options)
|
|||
n = (int)strtol(s, &z, 0);
|
||||
if (*z || !(options & OPT_NUMERIC))
|
||||
{
|
||||
if ((m = strgid(s)) != NOID)
|
||||
if ((m = strgid(s)) >= 0)
|
||||
n = m;
|
||||
else if (*z)
|
||||
{
|
||||
|
@ -387,21 +385,21 @@ b_chgrp(int argc, char** argv, Shbltin_t* context)
|
|||
UNREACHABLE();
|
||||
}
|
||||
m->key = key;
|
||||
m->to.uid = m->to.gid = NOID;
|
||||
m->to.uid = m->to.gid = -1;
|
||||
dtinsert(map, m);
|
||||
}
|
||||
getids(t, NiL, &m->to, options);
|
||||
}
|
||||
if (sp != sfstdin)
|
||||
sfclose(sp);
|
||||
keys[1].gid = keys[2].uid = NOID;
|
||||
keys[1].gid = keys[2].uid = -1;
|
||||
}
|
||||
else if (!(options & (OPT_UID|OPT_GID)))
|
||||
{
|
||||
getids(s, NiL, &key, options);
|
||||
if ((uid = key.uid) != NOID)
|
||||
if ((uid = key.uid) >= 0)
|
||||
options |= OPT_UID;
|
||||
if ((gid = key.gid) != NOID)
|
||||
if ((gid = key.gid) >= 0)
|
||||
options |= OPT_GID;
|
||||
}
|
||||
switch (options & (OPT_UID|OPT_GID))
|
||||
|
@ -455,7 +453,7 @@ b_chgrp(int argc, char** argv, Shbltin_t* context)
|
|||
if (map)
|
||||
{
|
||||
options &= ~(OPT_UID|OPT_GID);
|
||||
uid = gid = NOID;
|
||||
uid = gid = -1;
|
||||
keys[0].uid = keys[1].uid = ent->fts_statp->st_uid;
|
||||
keys[0].gid = keys[2].gid = ent->fts_statp->st_gid;
|
||||
i = 0;
|
||||
|
@ -463,18 +461,18 @@ b_chgrp(int argc, char** argv, Shbltin_t* context)
|
|||
{
|
||||
if (m = (Map_t*)dtmatch(map, &keys[i]))
|
||||
{
|
||||
if (uid == NOID && m->to.uid != NOID)
|
||||
if (uid < 0 && m->to.uid >= 0)
|
||||
{
|
||||
uid = m->to.uid;
|
||||
options |= OPT_UID;
|
||||
}
|
||||
if (gid == NOID && m->to.gid != NOID)
|
||||
if (gid < 0 && m->to.gid >= 0)
|
||||
{
|
||||
gid = m->to.gid;
|
||||
options |= OPT_GID;
|
||||
}
|
||||
}
|
||||
} while (++i < elementsof(keys) && (uid == NOID || gid == NOID));
|
||||
} while (++i < elementsof(keys) && (uid < 0 || gid < 0));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -483,16 +481,16 @@ b_chgrp(int argc, char** argv, Shbltin_t* context)
|
|||
if (!(options & OPT_GID))
|
||||
gid = ent->fts_statp->st_gid;
|
||||
}
|
||||
if ((options & OPT_UNMAPPED) && (uid == NOID || gid == NOID))
|
||||
if ((options & OPT_UNMAPPED) && (uid < 0 || gid < 0))
|
||||
{
|
||||
if (uid == NOID && gid == NOID)
|
||||
if (uid < 0 && gid < 0)
|
||||
error(ERROR_warn(0), "%s: uid and gid not mapped", ent->fts_path);
|
||||
else if (uid == NOID)
|
||||
else if (uid < 0)
|
||||
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 (uid != ent->fts_statp->st_uid && uid >= 0 || gid != ent->fts_statp->st_gid && gid >= 0)
|
||||
{
|
||||
if (options & (OPT_SHOW|OPT_VERBOSE))
|
||||
{
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue