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
|
- Fixed a bug introduced on 2020-08-09 that prevented '.' and '..' from
|
||||||
being completed when using file name tab completion.
|
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:
|
2021-12-11:
|
||||||
|
|
||||||
- Fixed two more crashing bugs that occurred if ksh received a signal (such
|
- Fixed two more crashing bugs that occurred if ksh received a signal (such
|
||||||
|
|
|
@ -38,16 +38,21 @@
|
||||||
..
|
..
|
||||||
.TH STRGID 3
|
.TH STRGID 3
|
||||||
.SH NAME
|
.SH NAME
|
||||||
strgid \- return group name given group number
|
strgid \- return group ID number for given group name
|
||||||
.SH SYNOPSIS
|
.SH SYNOPSIS
|
||||||
.L "char* strgid(int gid)"
|
.L "int strgid(const char* name)"
|
||||||
.SH DESCRIPTION
|
.SH DESCRIPTION
|
||||||
.I strgid
|
.I strgid
|
||||||
returns the group id name string given the group number
|
returns the group ID number for the given group name.
|
||||||
.IR gid .
|
|
||||||
.I strgid
|
.I strgid
|
||||||
maintains an internal cache to avoid repeated password database scans
|
maintains an internal cache to avoid repeated password database scans
|
||||||
by the low level
|
by the low level
|
||||||
.IR getgrgid (3).
|
.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"
|
.SH "SEE ALSO"
|
||||||
getgrent(3)
|
getgrent(3)
|
||||||
|
|
|
@ -38,16 +38,21 @@
|
||||||
..
|
..
|
||||||
.TH STRUID 3
|
.TH STRUID 3
|
||||||
.SH NAME
|
.SH NAME
|
||||||
struid \- return user name given user number
|
struid \- return user ID number for given user name
|
||||||
.SH SYNOPSIS
|
.SH SYNOPSIS
|
||||||
.L "char* struid(int uid)"
|
.L "int struid(const char* name)"
|
||||||
.SH DESCRIPTION
|
.SH DESCRIPTION
|
||||||
.I struid
|
.I struid
|
||||||
returns the user id name string given the user number
|
returns the user ID number for the given user name.
|
||||||
.IR uid .
|
|
||||||
.I struid
|
.I struid
|
||||||
maintains an internal cache to avoid repeated password database scans
|
maintains an internal cache to avoid repeated password database scans
|
||||||
by the low level
|
by the low level
|
||||||
.IR getpwuid (3).
|
.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"
|
.SH "SEE ALSO"
|
||||||
getpwent(3)
|
getpwent(3)
|
||||||
|
|
|
@ -131,8 +131,6 @@ typedef struct Map_s /* uid/gid map */
|
||||||
Key_t to; /* map to these */
|
Key_t to; /* map to these */
|
||||||
} Map_t;
|
} Map_t;
|
||||||
|
|
||||||
#define NOID (-1)
|
|
||||||
|
|
||||||
#define OPT_CHOWN 0x0001 /* chown */
|
#define OPT_CHOWN 0x0001 /* chown */
|
||||||
#define OPT_FORCE 0x0002 /* ignore errors */
|
#define OPT_FORCE 0x0002 /* ignore errors */
|
||||||
#define OPT_GID 0x0004 /* have gid */
|
#define OPT_GID 0x0004 /* have gid */
|
||||||
|
@ -159,7 +157,7 @@ getids(register char* s, char** e, Key_t* key, int options)
|
||||||
char* z;
|
char* z;
|
||||||
char buf[64];
|
char buf[64];
|
||||||
|
|
||||||
key->uid = key->gid = NOID;
|
key->uid = key->gid = -1;
|
||||||
while (isspace(*s))
|
while (isspace(*s))
|
||||||
s++;
|
s++;
|
||||||
for (t = s; (n = *t) && n != ':' && n != '.' && !isspace(n); t++);
|
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);
|
n = (int)strtol(s, &z, 0);
|
||||||
if (*z || !(options & OPT_NUMERIC))
|
if (*z || !(options & OPT_NUMERIC))
|
||||||
{
|
{
|
||||||
if ((m = struid(s)) != NOID)
|
if ((m = struid(s)) >= 0)
|
||||||
n = m;
|
n = m;
|
||||||
else if (*z)
|
else if (*z)
|
||||||
{
|
{
|
||||||
|
@ -200,7 +198,7 @@ getids(register char* s, char** e, Key_t* key, int options)
|
||||||
n = (int)strtol(s, &z, 0);
|
n = (int)strtol(s, &z, 0);
|
||||||
if (*z || !(options & OPT_NUMERIC))
|
if (*z || !(options & OPT_NUMERIC))
|
||||||
{
|
{
|
||||||
if ((m = strgid(s)) != NOID)
|
if ((m = strgid(s)) >= 0)
|
||||||
n = m;
|
n = m;
|
||||||
else if (*z)
|
else if (*z)
|
||||||
{
|
{
|
||||||
|
@ -387,21 +385,21 @@ b_chgrp(int argc, char** argv, Shbltin_t* context)
|
||||||
UNREACHABLE();
|
UNREACHABLE();
|
||||||
}
|
}
|
||||||
m->key = key;
|
m->key = key;
|
||||||
m->to.uid = m->to.gid = NOID;
|
m->to.uid = m->to.gid = -1;
|
||||||
dtinsert(map, m);
|
dtinsert(map, m);
|
||||||
}
|
}
|
||||||
getids(t, NiL, &m->to, options);
|
getids(t, NiL, &m->to, options);
|
||||||
}
|
}
|
||||||
if (sp != sfstdin)
|
if (sp != sfstdin)
|
||||||
sfclose(sp);
|
sfclose(sp);
|
||||||
keys[1].gid = keys[2].uid = NOID;
|
keys[1].gid = keys[2].uid = -1;
|
||||||
}
|
}
|
||||||
else if (!(options & (OPT_UID|OPT_GID)))
|
else if (!(options & (OPT_UID|OPT_GID)))
|
||||||
{
|
{
|
||||||
getids(s, NiL, &key, options);
|
getids(s, NiL, &key, options);
|
||||||
if ((uid = key.uid) != NOID)
|
if ((uid = key.uid) >= 0)
|
||||||
options |= OPT_UID;
|
options |= OPT_UID;
|
||||||
if ((gid = key.gid) != NOID)
|
if ((gid = key.gid) >= 0)
|
||||||
options |= OPT_GID;
|
options |= OPT_GID;
|
||||||
}
|
}
|
||||||
switch (options & (OPT_UID|OPT_GID))
|
switch (options & (OPT_UID|OPT_GID))
|
||||||
|
@ -455,7 +453,7 @@ b_chgrp(int argc, char** argv, Shbltin_t* context)
|
||||||
if (map)
|
if (map)
|
||||||
{
|
{
|
||||||
options &= ~(OPT_UID|OPT_GID);
|
options &= ~(OPT_UID|OPT_GID);
|
||||||
uid = gid = NOID;
|
uid = gid = -1;
|
||||||
keys[0].uid = keys[1].uid = ent->fts_statp->st_uid;
|
keys[0].uid = keys[1].uid = ent->fts_statp->st_uid;
|
||||||
keys[0].gid = keys[2].gid = ent->fts_statp->st_gid;
|
keys[0].gid = keys[2].gid = ent->fts_statp->st_gid;
|
||||||
i = 0;
|
i = 0;
|
||||||
|
@ -463,18 +461,18 @@ b_chgrp(int argc, char** argv, Shbltin_t* context)
|
||||||
{
|
{
|
||||||
if (m = (Map_t*)dtmatch(map, &keys[i]))
|
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;
|
uid = m->to.uid;
|
||||||
options |= OPT_UID;
|
options |= OPT_UID;
|
||||||
}
|
}
|
||||||
if (gid == NOID && m->to.gid != NOID)
|
if (gid < 0 && m->to.gid >= 0)
|
||||||
{
|
{
|
||||||
gid = m->to.gid;
|
gid = m->to.gid;
|
||||||
options |= OPT_GID;
|
options |= OPT_GID;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} while (++i < elementsof(keys) && (uid == NOID || gid == NOID));
|
} while (++i < elementsof(keys) && (uid < 0 || gid < 0));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -483,16 +481,16 @@ b_chgrp(int argc, char** argv, Shbltin_t* context)
|
||||||
if (!(options & OPT_GID))
|
if (!(options & OPT_GID))
|
||||||
gid = ent->fts_statp->st_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);
|
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);
|
error(ERROR_warn(0), "%s: uid not mapped", ent->fts_path);
|
||||||
else
|
else
|
||||||
error(ERROR_warn(0), "%s: gid not mapped", ent->fts_path);
|
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))
|
if (options & (OPT_SHOW|OPT_VERBOSE))
|
||||||
{
|
{
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue