On Fri, Oct 05, 2012 at 11:52:23PM -0300, Marcelo Cerri wrote: > This patch updates virGetUserID and virGetGroupID to be able to parse a > user or group name in a similar way to coreutils' chown. This means that > a numeric value with a leading plus sign is always parsed as an ID, > otherwise the functions try to parse the input first as a user or group > name and if this fails they try to parse it as an ID. > --- > src/util/util.c | 87 ++++++++++++++++++++++++++++++++++++++++++++++++--------- > 1 file changed, 74 insertions(+), 13 deletions(-) > > diff --git a/src/util/util.c b/src/util/util.c > index 43fdaf1..694ed3d 100644 > --- a/src/util/util.c > +++ b/src/util/util.c > @@ -2495,9 +2495,11 @@ char *virGetGroupName(gid_t gid) > return virGetGroupEnt(gid); > } > > - > -int virGetUserID(const char *name, > - uid_t *uid) > +/* Search in the password database for a user id that matches the user name > + * `name`. Returns 0 on success, -1 on a critical failure or 1 if name cannot > + * be parsed. > + */ > +static int virGetUserIDByName(const char *name, uid_t *uid) > { > char *strbuf; > struct passwd pwbuf; > @@ -2530,11 +2532,10 @@ int virGetUserID(const char *name, > } > } > if (rc != 0 || pw == NULL) { > - virReportSystemError(rc, > - _("Failed to find user record for name '%s'"), > - name); > + VIR_DEBUG("Failed to find user record for user '%s' (error = %d)", > + name, rc); > VIR_FREE(strbuf); > - return -1; > + return 1; > } > > *uid = pw->pw_uid; > @@ -2544,9 +2545,41 @@ int virGetUserID(const char *name, > return 0; > } > > +/* Try to match a user id based on `user`. The default behavior is to parse > + * `user` first as a user name and then as a user id. However if `user` > + * contains a leading '+', the rest of the string is always parsed as a uid. > + * > + * Returns 0 on success and -1 otherwise. > + */ > +int virGetUserID(const char *user, uid_t *uid) > +{ > + unsigned int uint_uid; > > -int virGetGroupID(const char *name, > - gid_t *gid) > + if (*user == '+') { > + user++; > + } else { > + int rc = virGetUserIDByName(user, uid); > + if (rc <= 0) > + return rc; > + } > + > + if (virStrToLong_ui(user, NULL, 10, &uint_uid) < 0 || > + ((uid_t) uint_uid) != uint_uid) { > + virReportError(VIR_ERR_INVALID_ARG, _("Failed to parse user '%s'"), > + user); > + return -1; > + } > + > + *uid = uint_uid; > + > + return 0; > +} > + > +/* Search in the group database for a group id that matches the group name > + * `name`. Returns 0 on success, -1 on a critical failure or 1 if name cannot > + * be parsed. > + */ > +static int virGetGroupIDByName(const char *name, gid_t *gid) > { > char *strbuf; > struct group grbuf; > @@ -2579,11 +2612,10 @@ int virGetGroupID(const char *name, > } > } > if (rc != 0 || gr == NULL) { > - virReportSystemError(rc, > - _("Failed to find group record for name '%s'"), > - name); > + VIR_DEBUG("Failed to find group record for group '%s' (error = %d)", > + name, rc); > VIR_FREE(strbuf); > - return -1; > + return 1; > } > > *gid = gr->gr_gid; > @@ -2593,6 +2625,35 @@ int virGetGroupID(const char *name, > return 0; > } > > +/* Try to match a group id based on `group`. The default behavior is to parse > + * `group` first as a group name and then as a group id. However if `group` > + * contains a leading '+', the rest of the string is always parsed as a guid. > + * > + * Returns 0 on success and -1 otherwise. > + */ > +int virGetGroupID(const char *group, gid_t *gid) > +{ > + unsigned int uint_gid; > + > + if (*group == '+') { > + group++; > + } else { > + int rc = virGetGroupIDByName(group, gid); > + if (rc <= 0) > + return rc; > + } > + > + if (virStrToLong_ui(group, NULL, 10, &uint_gid) < 0 || > + ((gid_t) uint_gid) != uint_gid) { > + virReportError(VIR_ERR_INVALID_ARG, _("Failed to parse user '%s'"), Hmmm.. There's a copy-and-paste problem here. It should be 'group' instead of 'user'. I will wait to check if any other fixes will be needed and include it in a next version of this series. > + group); > + return -1; > + } > + > + *gid = uint_gid; > + > + return 0; > +} > > /* Set the real and effective uid and gid to the given values, and call > * initgroups so that the process has all the assumed group membership of > -- > 1.7.12 > -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list