Loading toolbox/Android.mk +12 −4 Original line number Diff line number Diff line Loading @@ -80,15 +80,23 @@ ALL_TOOLS += \ grep LOCAL_SRC_FILES := \ cp/cp.c \ cp/utils.c \ dynarray.c \ toolbox.c \ grep/fastgrep.c \ grep/file.c \ grep/grep.c \ grep/queue.c \ grep/util.c \ $(patsubst %,%.c,$(TOOLS)) \ cp/cp.c cp/utils.c \ grep/grep.c grep/fastgrep.c grep/file.c grep/queue.c grep/util.c toolbox.c \ uid_from_user.c \ LOCAL_C_INCLUDES := bionic/libc/bionic LOCAL_CFLAGS += -Wno-unused-parameter LOCAL_CFLAGS += \ -Wno-unused-parameter \ -DSUPPORT_DOT \ LOCAL_SHARED_LIBRARIES := \ libcutils \ Loading toolbox/chown.c +294 −65 Original line number Diff line number Diff line #include <stdio.h> #include <stdlib.h> #include <string.h> /* $NetBSD: chown.c,v 1.8 2012/10/24 01:12:51 enami Exp $ */ /* * Copyright (c) 1988, 1993, 1994, 2003 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include <sys/cdefs.h> #ifndef lint __COPYRIGHT("@(#) Copyright (c) 1988, 1993, 1994, 2003\ The Regents of the University of California. All rights reserved."); #endif /* not lint */ #ifndef lint #if 0 static char sccsid[] = "@(#)chown.c 8.8 (Berkeley) 4/4/94"; #else __RCSID("$NetBSD: chown.c,v 1.8 2012/10/24 01:12:51 enami Exp $"); #endif #endif /* not lint */ #include <sys/types.h> #include <sys/stat.h> #include <ctype.h> #include <dirent.h> #include <err.h> #include <errno.h> #include <pwd.h> #include <locale.h> #include <fts.h> #include <grp.h> #include <pwd.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <time.h> #include <getopt.h> static void a_gid(const char *); static void a_uid(const char *); static id_t id(const char *, const char *); __dead static void usage(void); int chown_main(int argc, char **argv) static uid_t uid; static gid_t gid; static int ischown; static const char *myname; struct option chown_longopts[] = { { "reference", required_argument, 0, 1 }, { NULL, 0, 0, 0 }, }; int chown_main(int argc, char **argv) { int i; FTS *ftsp; FTSENT *p; int Hflag, Lflag, Rflag, ch, fflag, fts_options, hflag, rval, vflag; char *cp, *reference; int (*change_owner)(const char *, uid_t, gid_t); if (argc < 3) { fprintf(stderr, "Usage: chown <USER>[:GROUP] <FILE1> [FILE2] ...\n"); return 10; } setprogname(*argv); (void)setlocale(LC_ALL, ""); myname = getprogname(); ischown = (myname[2] == 'o'); reference = NULL; // Copy argv[1] to 'user' so we can truncate it at the period // if a group id specified. char user[32]; char *group = NULL; strncpy(user, argv[1], sizeof(user)); if ((group = strchr(user, ':')) != NULL) { *group++ = '\0'; } else if ((group = strchr(user, '.')) != NULL) { *group++ = '\0'; Hflag = Lflag = Rflag = fflag = hflag = vflag = 0; while ((ch = getopt_long(argc, argv, "HLPRfhv", chown_longopts, NULL)) != -1) switch (ch) { case 1: reference = optarg; break; case 'H': Hflag = 1; Lflag = 0; break; case 'L': Lflag = 1; Hflag = 0; break; case 'P': Hflag = Lflag = 0; break; case 'R': Rflag = 1; break; case 'f': fflag = 1; break; case 'h': /* * In System V the -h option causes chown/chgrp to * change the owner/group of the symbolic link. * 4.4BSD's symbolic links didn't have owners/groups, * so it was an undocumented noop. * In NetBSD 1.3, lchown(2) is introduced. */ hflag = 1; break; case 'v': vflag = 1; break; case '?': default: usage(); } argv += optind; argc -= optind; // Lookup uid (and gid if specified) struct passwd *pw; struct group *grp = NULL; uid_t uid; gid_t gid = -1; // passing -1 to chown preserves current group if (argc == 0 || (argc == 1 && reference == NULL)) usage(); pw = getpwnam(user); if (pw != NULL) { uid = pw->pw_uid; fts_options = FTS_PHYSICAL; if (Rflag) { if (Hflag) fts_options |= FTS_COMFOLLOW; if (Lflag) { if (hflag) errx(EXIT_FAILURE, "the -L and -h options " "may not be specified together."); fts_options &= ~FTS_PHYSICAL; fts_options |= FTS_LOGICAL; } } else if (!hflag) fts_options |= FTS_COMFOLLOW; uid = (uid_t)-1; gid = (gid_t)-1; if (reference == NULL) { if (ischown) { if ((cp = strchr(*argv, ':')) != NULL) { *cp++ = '\0'; a_gid(cp); } #ifdef SUPPORT_DOT else if ((cp = strrchr(*argv, '.')) != NULL) { if (uid_from_user(*argv, &uid) == -1) { *cp++ = '\0'; a_gid(cp); } } #endif a_uid(*argv); } else a_gid(*argv); argv++; } else { char* endptr; uid = (int) strtoul(user, &endptr, 0); if (endptr == user) { // no conversion fprintf(stderr, "No such user '%s'\n", user); return 10; struct stat st; if (stat(reference, &st) == -1) err(EXIT_FAILURE, "Cannot stat `%s'", reference); if (ischown) uid = st.st_uid; gid = st.st_gid; } if ((ftsp = fts_open(argv, fts_options, NULL)) == NULL) err(EXIT_FAILURE, "fts_open"); for (rval = EXIT_SUCCESS; (p = fts_read(ftsp)) != NULL;) { change_owner = chown; switch (p->fts_info) { case FTS_D: if (!Rflag) /* Change it at FTS_DP. */ fts_set(ftsp, p, FTS_SKIP); continue; case FTS_DNR: /* Warn, chown, continue. */ warnx("%s: %s", p->fts_path, strerror(p->fts_errno)); rval = EXIT_FAILURE; break; case FTS_ERR: /* Warn, continue. */ case FTS_NS: warnx("%s: %s", p->fts_path, strerror(p->fts_errno)); rval = EXIT_FAILURE; continue; case FTS_SL: /* Ignore unless -h. */ /* * All symlinks we found while doing a physical * walk end up here. */ if (!hflag) continue; /* * Note that if we follow a symlink, fts_info is * not FTS_SL but FTS_F or whatever. And we should * use lchown only for FTS_SL and should use chown * for others. */ change_owner = lchown; break; case FTS_SLNONE: /* Ignore. */ /* * The only symlinks that end up here are ones that * don't point to anything. Note that if we are * doing a phisycal walk, we never reach here unless * we asked to follow explicitly. */ continue; default: break; } if (group != NULL) { grp = getgrnam(group); if (grp != NULL) { gid = grp->gr_gid; if ((*change_owner)(p->fts_accpath, uid, gid) && !fflag) { warn("%s", p->fts_path); rval = EXIT_FAILURE; } else { char* endptr; gid = (int) strtoul(group, &endptr, 0); if (endptr == group) { // no conversion fprintf(stderr, "No such group '%s'\n", group); return 10; if (vflag) printf("%s\n", p->fts_path); } } if (errno) err(EXIT_FAILURE, "fts_read"); exit(rval); /* NOTREACHED */ } for (i = 2; i < argc; i++) { if (chown(argv[i], uid, gid) < 0) { fprintf(stderr, "Unable to chown %s: %s\n", argv[i], strerror(errno)); return 10; static void a_gid(const char *s) { struct group *gr; if (*s == '\0') /* Argument was "uid[:.]". */ return; gr = *s == '#' ? NULL : getgrnam(s); if (gr == NULL) gid = id(s, "group"); else gid = gr->gr_gid; return; } static void a_uid(const char *s) { if (*s == '\0') /* Argument was "[:.]gid". */ return; if (*s == '#' || uid_from_user(s, &uid) == -1) { uid = id(s, "user"); } return; } return 0; static id_t id(const char *name, const char *type) { id_t val; char *ep; errno = 0; if (*name == '#') name++; val = (id_t)strtoul(name, &ep, 10); if (errno) err(EXIT_FAILURE, "%s", name); if (*ep != '\0') errx(EXIT_FAILURE, "%s: invalid %s name", name, type); return (val); } static void usage(void) { (void)fprintf(stderr, "Usage: %s [-R [-H | -L | -P]] [-fhv] %s file ...\n" "\t%s [-R [-H | -L | -P]] [-fhv] --reference=rfile file ...\n", myname, ischown ? "owner:group|owner|:group" : "group", myname); exit(EXIT_FAILURE); } toolbox/uid_from_user.c 0 → 100644 +48 −0 Original line number Diff line number Diff line /* * Copyright (C) 2014, The Android Open Source Project * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include <limits.h> #include <pwd.h> #include <stdlib.h> #include <sys/types.h> int uid_from_user(const char* name, uid_t* uid) { struct passwd* pw = getpwnam(name); if (pw != NULL) { *uid = pw->pw_uid; return 0; } // Try to parse as an integer. char* end_ptr; unsigned long number = strtoul(name, &end_ptr, 0); if (end_ptr == name || *end_ptr != '\0' || number > INT_MAX) { return -1; } *uid = (int) number; return 0; } Loading
toolbox/Android.mk +12 −4 Original line number Diff line number Diff line Loading @@ -80,15 +80,23 @@ ALL_TOOLS += \ grep LOCAL_SRC_FILES := \ cp/cp.c \ cp/utils.c \ dynarray.c \ toolbox.c \ grep/fastgrep.c \ grep/file.c \ grep/grep.c \ grep/queue.c \ grep/util.c \ $(patsubst %,%.c,$(TOOLS)) \ cp/cp.c cp/utils.c \ grep/grep.c grep/fastgrep.c grep/file.c grep/queue.c grep/util.c toolbox.c \ uid_from_user.c \ LOCAL_C_INCLUDES := bionic/libc/bionic LOCAL_CFLAGS += -Wno-unused-parameter LOCAL_CFLAGS += \ -Wno-unused-parameter \ -DSUPPORT_DOT \ LOCAL_SHARED_LIBRARIES := \ libcutils \ Loading
toolbox/chown.c +294 −65 Original line number Diff line number Diff line #include <stdio.h> #include <stdlib.h> #include <string.h> /* $NetBSD: chown.c,v 1.8 2012/10/24 01:12:51 enami Exp $ */ /* * Copyright (c) 1988, 1993, 1994, 2003 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include <sys/cdefs.h> #ifndef lint __COPYRIGHT("@(#) Copyright (c) 1988, 1993, 1994, 2003\ The Regents of the University of California. All rights reserved."); #endif /* not lint */ #ifndef lint #if 0 static char sccsid[] = "@(#)chown.c 8.8 (Berkeley) 4/4/94"; #else __RCSID("$NetBSD: chown.c,v 1.8 2012/10/24 01:12:51 enami Exp $"); #endif #endif /* not lint */ #include <sys/types.h> #include <sys/stat.h> #include <ctype.h> #include <dirent.h> #include <err.h> #include <errno.h> #include <pwd.h> #include <locale.h> #include <fts.h> #include <grp.h> #include <pwd.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <time.h> #include <getopt.h> static void a_gid(const char *); static void a_uid(const char *); static id_t id(const char *, const char *); __dead static void usage(void); int chown_main(int argc, char **argv) static uid_t uid; static gid_t gid; static int ischown; static const char *myname; struct option chown_longopts[] = { { "reference", required_argument, 0, 1 }, { NULL, 0, 0, 0 }, }; int chown_main(int argc, char **argv) { int i; FTS *ftsp; FTSENT *p; int Hflag, Lflag, Rflag, ch, fflag, fts_options, hflag, rval, vflag; char *cp, *reference; int (*change_owner)(const char *, uid_t, gid_t); if (argc < 3) { fprintf(stderr, "Usage: chown <USER>[:GROUP] <FILE1> [FILE2] ...\n"); return 10; } setprogname(*argv); (void)setlocale(LC_ALL, ""); myname = getprogname(); ischown = (myname[2] == 'o'); reference = NULL; // Copy argv[1] to 'user' so we can truncate it at the period // if a group id specified. char user[32]; char *group = NULL; strncpy(user, argv[1], sizeof(user)); if ((group = strchr(user, ':')) != NULL) { *group++ = '\0'; } else if ((group = strchr(user, '.')) != NULL) { *group++ = '\0'; Hflag = Lflag = Rflag = fflag = hflag = vflag = 0; while ((ch = getopt_long(argc, argv, "HLPRfhv", chown_longopts, NULL)) != -1) switch (ch) { case 1: reference = optarg; break; case 'H': Hflag = 1; Lflag = 0; break; case 'L': Lflag = 1; Hflag = 0; break; case 'P': Hflag = Lflag = 0; break; case 'R': Rflag = 1; break; case 'f': fflag = 1; break; case 'h': /* * In System V the -h option causes chown/chgrp to * change the owner/group of the symbolic link. * 4.4BSD's symbolic links didn't have owners/groups, * so it was an undocumented noop. * In NetBSD 1.3, lchown(2) is introduced. */ hflag = 1; break; case 'v': vflag = 1; break; case '?': default: usage(); } argv += optind; argc -= optind; // Lookup uid (and gid if specified) struct passwd *pw; struct group *grp = NULL; uid_t uid; gid_t gid = -1; // passing -1 to chown preserves current group if (argc == 0 || (argc == 1 && reference == NULL)) usage(); pw = getpwnam(user); if (pw != NULL) { uid = pw->pw_uid; fts_options = FTS_PHYSICAL; if (Rflag) { if (Hflag) fts_options |= FTS_COMFOLLOW; if (Lflag) { if (hflag) errx(EXIT_FAILURE, "the -L and -h options " "may not be specified together."); fts_options &= ~FTS_PHYSICAL; fts_options |= FTS_LOGICAL; } } else if (!hflag) fts_options |= FTS_COMFOLLOW; uid = (uid_t)-1; gid = (gid_t)-1; if (reference == NULL) { if (ischown) { if ((cp = strchr(*argv, ':')) != NULL) { *cp++ = '\0'; a_gid(cp); } #ifdef SUPPORT_DOT else if ((cp = strrchr(*argv, '.')) != NULL) { if (uid_from_user(*argv, &uid) == -1) { *cp++ = '\0'; a_gid(cp); } } #endif a_uid(*argv); } else a_gid(*argv); argv++; } else { char* endptr; uid = (int) strtoul(user, &endptr, 0); if (endptr == user) { // no conversion fprintf(stderr, "No such user '%s'\n", user); return 10; struct stat st; if (stat(reference, &st) == -1) err(EXIT_FAILURE, "Cannot stat `%s'", reference); if (ischown) uid = st.st_uid; gid = st.st_gid; } if ((ftsp = fts_open(argv, fts_options, NULL)) == NULL) err(EXIT_FAILURE, "fts_open"); for (rval = EXIT_SUCCESS; (p = fts_read(ftsp)) != NULL;) { change_owner = chown; switch (p->fts_info) { case FTS_D: if (!Rflag) /* Change it at FTS_DP. */ fts_set(ftsp, p, FTS_SKIP); continue; case FTS_DNR: /* Warn, chown, continue. */ warnx("%s: %s", p->fts_path, strerror(p->fts_errno)); rval = EXIT_FAILURE; break; case FTS_ERR: /* Warn, continue. */ case FTS_NS: warnx("%s: %s", p->fts_path, strerror(p->fts_errno)); rval = EXIT_FAILURE; continue; case FTS_SL: /* Ignore unless -h. */ /* * All symlinks we found while doing a physical * walk end up here. */ if (!hflag) continue; /* * Note that if we follow a symlink, fts_info is * not FTS_SL but FTS_F or whatever. And we should * use lchown only for FTS_SL and should use chown * for others. */ change_owner = lchown; break; case FTS_SLNONE: /* Ignore. */ /* * The only symlinks that end up here are ones that * don't point to anything. Note that if we are * doing a phisycal walk, we never reach here unless * we asked to follow explicitly. */ continue; default: break; } if (group != NULL) { grp = getgrnam(group); if (grp != NULL) { gid = grp->gr_gid; if ((*change_owner)(p->fts_accpath, uid, gid) && !fflag) { warn("%s", p->fts_path); rval = EXIT_FAILURE; } else { char* endptr; gid = (int) strtoul(group, &endptr, 0); if (endptr == group) { // no conversion fprintf(stderr, "No such group '%s'\n", group); return 10; if (vflag) printf("%s\n", p->fts_path); } } if (errno) err(EXIT_FAILURE, "fts_read"); exit(rval); /* NOTREACHED */ } for (i = 2; i < argc; i++) { if (chown(argv[i], uid, gid) < 0) { fprintf(stderr, "Unable to chown %s: %s\n", argv[i], strerror(errno)); return 10; static void a_gid(const char *s) { struct group *gr; if (*s == '\0') /* Argument was "uid[:.]". */ return; gr = *s == '#' ? NULL : getgrnam(s); if (gr == NULL) gid = id(s, "group"); else gid = gr->gr_gid; return; } static void a_uid(const char *s) { if (*s == '\0') /* Argument was "[:.]gid". */ return; if (*s == '#' || uid_from_user(s, &uid) == -1) { uid = id(s, "user"); } return; } return 0; static id_t id(const char *name, const char *type) { id_t val; char *ep; errno = 0; if (*name == '#') name++; val = (id_t)strtoul(name, &ep, 10); if (errno) err(EXIT_FAILURE, "%s", name); if (*ep != '\0') errx(EXIT_FAILURE, "%s: invalid %s name", name, type); return (val); } static void usage(void) { (void)fprintf(stderr, "Usage: %s [-R [-H | -L | -P]] [-fhv] %s file ...\n" "\t%s [-R [-H | -L | -P]] [-fhv] --reference=rfile file ...\n", myname, ischown ? "owner:group|owner|:group" : "group", myname); exit(EXIT_FAILURE); }
toolbox/uid_from_user.c 0 → 100644 +48 −0 Original line number Diff line number Diff line /* * Copyright (C) 2014, The Android Open Source Project * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include <limits.h> #include <pwd.h> #include <stdlib.h> #include <sys/types.h> int uid_from_user(const char* name, uid_t* uid) { struct passwd* pw = getpwnam(name); if (pw != NULL) { *uid = pw->pw_uid; return 0; } // Try to parse as an integer. char* end_ptr; unsigned long number = strtoul(name, &end_ptr, 0); if (end_ptr == name || *end_ptr != '\0' || number > INT_MAX) { return -1; } *uid = (int) number; return 0; }