static void fileaction_setowngrp(char *filename, int fileref)
{
int uid, gid;
- uid = bb_xgetpwnam(rpm_getstr(TAG_FILEUSERNAME, fileref));
- gid = bb_xgetgrnam(rpm_getstr(TAG_FILEGROUPNAME, fileref));
+ uid = xuname2uid(rpm_getstr(TAG_FILEUSERNAME, fileref));
+ gid = xgroup2gid(rpm_getstr(TAG_FILEGROUPNAME, fileref));
chown(filename, uid, gid);
}
int chown_main(int argc, char **argv)
{
- int retval = EXIT_SUCCESS;
char *groupName;
+ int retval = EXIT_SUCCESS;
opt_complementary = "-2";
getopt32(argc, argv, OPT_STR);
+ argv += optind;
if (OPT_NODEREF) chown_func = lchown;
- argv += optind;
-
/* First, check if there is a group name here */
- groupName = strchr(*argv, '.');
+ groupName = strchr(*argv, '.'); /* deprecated? */
if (!groupName) {
groupName = strchr(*argv, ':');
}
- /* Check for the username and groupname */
- if (groupName) {
- *groupName++ = '\0';
- gid = get_ug_id(groupName, bb_xgetgrnam);
+ /* First, try parsing "user[:[group]]" */
+ if (!groupName) { /* "user" */
+ uid = get_ug_id(*argv, xuname2uid);
+ } else if (groupName == *argv) { /* ":group" */
+ gid = get_ug_id(groupName + 1, xgroup2gid);
+ } else {
+ struct bb_uidgid_t ugid;
+ if (!groupName[1]) /* "user:" */
+ *groupName = '\0';
+ if (!get_uidgid(&ugid, *argv, 1))
+ bb_error_msg_and_die("unknown user/group %s", *argv);
+ uid = ugid.uid;
+ gid = ugid.gid;
}
- if (--groupName != *argv)
- uid = get_ug_id(*argv, bb_xgetpwnam);
- ++argv;
/* Ok, ready to do the deed now */
+ argv++;
do {
if (!recursive_action(*argv,
OPT_RECURSE, // recurse
if (argv[optind]) {
p = getpwnam(argv[optind]);
- /* bb_xgetpwnam is needed because it exits on failure */
- uid = bb_xgetpwnam(argv[optind]);
+ /* xuname2uid is needed because it exits on failure */
+ uid = xuname2uid(argv[optind]);
gid = p->pw_gid;
/* in this case PRINT_REAL is the same */
}
#include <libgen.h>
#include <getopt.h> /* struct option */
-#define INSTALL_OPT_CMD 1
-#define INSTALL_OPT_DIRECTORY 2
-#define INSTALL_OPT_PRESERVE_TIME 4
-#define INSTALL_OPT_STRIP 8
-#define INSTALL_OPT_GROUP 16
-#define INSTALL_OPT_MODE 32
-#define INSTALL_OPT_OWNER 64
-
#if ENABLE_FEATURE_INSTALL_LONG_OPTIONS
static const struct option install_long_options[] = {
- { "directory", 0, NULL, 'd' },
- { "preserve-timestamps", 0, NULL, 'p' },
- { "strip", 0, NULL, 's' },
- { "group", 0, NULL, 'g' },
- { "mode", 0, NULL, 'm' },
- { "owner", 0, NULL, 'o' },
- { 0, 0, 0, 0 }
+ { "directory", 0, NULL, 'd' },
+ { "preserve-timestamps", 0, NULL, 'p' },
+ { "strip", 0, NULL, 's' },
+ { "group", 0, NULL, 'g' },
+ { "mode", 0, NULL, 'm' },
+ { "owner", 0, NULL, 'o' },
+ { 0, 0, 0, 0 }
};
#endif
int install_main(int argc, char **argv)
{
+ struct stat statbuf;
mode_t mode;
uid_t uid;
gid_t gid;
- char *gid_str = "-1";
- char *uid_str = "-1";
- char *mode_str = "0755";
+ const char *gid_str;
+ const char *uid_str;
+ const char *mode_str;
int copy_flags = FILEUTILS_DEREFERENCE | FILEUTILS_FORCE;
int ret = EXIT_SUCCESS, flags, i, isdir;
+ enum {
+ OPT_CMD = 0x1,
+ OPT_DIRECTORY = 0x2,
+ OPT_PRESERVE_TIME = 0x4,
+ OPT_STRIP = 0x8,
+ OPT_GROUP = 0x10,
+ OPT_MODE = 0x20,
+ OPT_OWNER = 0x40,
+ };
+
#if ENABLE_FEATURE_INSTALL_LONG_OPTIONS
applet_long_options = install_long_options;
#endif
opt_complementary = "?:s--d:d--s";
/* -c exists for backwards compatibility, its needed */
- flags = getopt32(argc, argv, "cdpsg:m:o:", &gid_str, &mode_str, &uid_str); /* 'a' must be 2nd */
+ flags = getopt32(argc, argv, "cdpsg:m:o:", &gid_str, &mode_str, &uid_str);
/* preserve access and modification time, this is GNU behaviour, BSD only preserves modification time */
- if (flags & INSTALL_OPT_PRESERVE_TIME) {
+ if (flags & OPT_PRESERVE_TIME) {
copy_flags |= FILEUTILS_PRESERVE_STATUS;
}
- bb_parse_mode(mode_str, &mode);
- gid = get_ug_id(gid_str, bb_xgetgrnam);
- uid = get_ug_id(uid_str, bb_xgetpwnam);
- umask(0);
+ mode = 0666;
+ if (flags & OPT_MODE) bb_parse_mode(mode_str, &mode);
+ uid = (flags & OPT_OWNER) ? get_ug_id(uid_str, xuname2uid) : getuid();
+ gid = (flags & OPT_GROUP) ? get_ug_id(gid_str, xgroup2gid) : getgid();
+ if (flags & (OPT_OWNER|OPT_GROUP)) umask(0);
/* Create directories
* don't use bb_make_directory() as it can't change uid or gid
* perhaps bb_make_directory() should be improved.
*/
- if (flags & INSTALL_OPT_DIRECTORY) {
+ if (flags & OPT_DIRECTORY) {
for (argv += optind; *argv; argv++) {
char *old_argv_ptr = *argv + 1;
char *argv_ptr;
*argv_ptr = '\0';
old_argv_ptr++;
}
- if (mkdir(*argv, mode) == -1) {
+ if (mkdir(*argv, mode | 0111) == -1) {
if (errno != EEXIST) {
bb_perror_msg("cannot create %s", *argv);
ret = EXIT_FAILURE;
break;
}
}
- else if (lchown(*argv, uid, gid) == -1) {
+ if ((flags & (OPT_OWNER|OPT_GROUP))
+ && lchown(*argv, uid, gid) == -1
+ ) {
bb_perror_msg("cannot change ownership of %s", *argv);
ret = EXIT_FAILURE;
break;
return ret;
}
- {
- struct stat statbuf;
- isdir = lstat(argv[argc - 1], &statbuf)<0
- ? 0 : S_ISDIR(statbuf.st_mode);
- }
+ isdir = lstat(argv[argc - 1], &statbuf) < 0 ? 0 : S_ISDIR(statbuf.st_mode);
+
for (i = optind; i < argc - 1; i++) {
char *dest;
dest = argv[argc - 1];
- if (isdir) dest = concat_path_file(argv[argc - 1], basename(argv[i]));
+ if (isdir)
+ dest = concat_path_file(argv[argc - 1], basename(argv[i]));
ret |= copy_file(argv[i], dest, copy_flags);
/* Set the file mode */
- if (chmod(dest, mode) == -1) {
+ if ((flags & OPT_MODE) && chmod(dest, mode) == -1) {
bb_perror_msg("cannot change permissions of %s", dest);
ret = EXIT_FAILURE;
}
/* Set the user and group id */
- if (lchown(dest, uid, gid) == -1) {
+ if ((flags & (OPT_OWNER|OPT_GROUP))
+ && lchown(dest, uid, gid) == -1
+ ) {
bb_perror_msg("cannot change ownership of %s", dest);
ret = EXIT_FAILURE;
}
- if (flags & INSTALL_OPT_STRIP) {
+ if (flags & OPT_STRIP) {
if (execlp("strip", "strip", dest, NULL) == -1) {
- bb_error_msg("strip failed");
+ bb_perror_msg("strip");
ret = EXIT_FAILURE;
}
}
- if(ENABLE_FEATURE_CLEAN_UP && isdir) free(dest);
+ if (ENABLE_FEATURE_CLEAN_UP && isdir) free(dest);
}
return ret;
if (userspec) {
user_id = bb_strtou(userspec, NULL, 10);
if (errno)
- user_id = bb_xgetpwnam(userspec);
+ user_id = xuname2uid(userspec);
}
if (opt & CTX_STOP) {
if (chuid) {
user_id = bb_strtou(chuid, NULL, 10);
if (errno)
- user_id = bb_xgetpwnam(chuid);
+ user_id = xuname2uid(chuid);
xsetuid(user_id);
}
#if ENABLE_FEATURE_START_STOP_DAEMON_FANCY
case 'g':
resgid = bb_strtoul(optarg, NULL, 10);
if (errno)
- resgid = bb_xgetgrnam(optarg);
+ resgid = xgroup2gid(optarg);
g_flag = 1;
open_flag = EXT2_FLAG_RW;
break;
case 'u':
resuid = bb_strtoul(optarg, NULL, 10);
if (errno)
- resuid = bb_xgetpwnam(optarg);
+ resuid = xuname2uid(optarg);
u_flag = 1;
open_flag = EXT2_FLAG_RW;
break;
/* These parse entries in /etc/passwd and /etc/group. This is desirable
* for BusyBox since we want to avoid using the glibc NSS stuff, which
* increases target size and is often not needed on embedded systems. */
-extern long bb_xgetpwnam(const char *name);
-extern long bb_xgetgrnam(const char *name);
-/*extern char *bb_getug(char *buffer, char *idname, long id, int bufsize, char prefix);*/
-extern char *bb_getpwuid(char *name, long uid, int bufsize);
-extern char *bb_getgrgid(char *group, long gid, int bufsize);
-/* from chpst */
+extern long xuname2uid(const char *name);
+extern long xgroup2gid(const char *name);
+/* wrapper: allows string to contain numeric uid or gid */
+extern unsigned long get_ug_id(const char *s, long (*xname2id)(const char *));
+/* from chpst. Does not die, returns 0 on failure */
struct bb_uidgid_t {
uid_t uid;
gid_t gid;
};
-extern unsigned uidgid_get(struct bb_uidgid_t*, const char* /*, unsigned*/);
+extern int get_uidgid(struct bb_uidgid_t*, const char*, int numeric_ok);
+/* what is this? */
+/*extern char *bb_getug(char *buffer, char *idname, long id, int bufsize, char prefix);*/
+extern char *bb_getpwuid(char *name, long uid, int bufsize);
+extern char *bb_getgrgid(char *group, long gid, int bufsize);
enum { BB_GETOPT_ERROR = 0x80000000 };
int argc, char **argv, char *foreground_opt);
#endif
extern int get_terminal_width_height(int fd, int *width, int *height);
-extern unsigned long get_ug_id(const char *s, long (*__bb_getxxnam)(const char *));
int is_in_ino_dev_hashtable(const struct stat *statbuf, char **name);
void add_to_ino_dev_hashtable(const struct stat *statbuf, const char *name);
* Licensed under the GPL v2 or later, see the file LICENSE in this tarball.
*/
-#include <stdio.h>
-#include <string.h>
-#include <assert.h>
#include "libbb.h"
- /*
- * if bufsize is > 0 char *buffer cannot be set to NULL.
- * If idname is not NULL it is written on the static
- * allocated buffer (and a pointer to it is returned).
- * if idname is NULL, id as string is written to the static
- * allocated buffer and NULL is returned.
- * if bufsize is = 0 char *buffer can be set to NULL.
- * If idname exists a pointer to it is returned,
- * else NULL is returned.
- * if bufsize is < 0 char *buffer can be set to NULL.
- * If idname exists a pointer to it is returned,
- * else an error message is printed and the program exits.
- */
+#define assert(x) ((void)0)
+
+/*
+ * if bufsize is > 0 char *buffer cannot be set to NULL.
+ * If idname is not NULL it is written on the static
+ * allocated buffer (and a pointer to it is returned).
+ * if idname is NULL, id as string is written to the static
+ * allocated buffer and NULL is returned.
+ * if bufsize is = 0 char *buffer can be set to NULL.
+ * If idname exists a pointer to it is returned,
+ * else NULL is returned.
+ * if bufsize is < 0 char *buffer can be set to NULL.
+ * If idname exists a pointer to it is returned,
+ * else an error message is printed and the program exits.
+ */
/* internal function for bb_getpwuid and bb_getgrgid */
-static char * bb_getug(char *buffer, char *idname, long id, int bufsize, char prefix)
+static char* bb_getug(char *buffer, char *idname, long id, int bufsize, char prefix)
{
if (bufsize > 0 ) {
- assert(buffer!=NULL);
- if(idname) {
+ assert(buffer != NULL);
+ if (idname) {
return safe_strncpy(buffer, idname, bufsize);
}
snprintf(buffer, bufsize, "%ld", id);
return idname;
}
- /* Hacked by Tito Ragusa (c) 2004 <farmatito@tiscali.it> to make it more
- * flexible :
- *
- * if bufsize is > 0 char *group cannot be set to NULL.
- * On success groupname is written on static allocated buffer
- * group (and a pointer to it is returned).
- * On failure gid as string is written to static allocated
- * buffer group and NULL is returned.
- * if bufsize is = 0 char *group can be set to NULL.
- * On success groupname is returned.
- * On failure NULL is returned.
- * if bufsize is < 0 char *group can be set to NULL.
- * On success groupname is returned.
- * On failure an error message is printed and
- * the program exits.
- */
+/* Hacked by Tito Ragusa (c) 2004 <farmatito@tiscali.it> to make it more
+ * flexible :
+ *
+ * if bufsize is > 0 char *group cannot be set to NULL.
+ * On success groupname is written on static allocated buffer
+ * group (and a pointer to it is returned).
+ * On failure gid as string is written to static allocated
+ * buffer group and NULL is returned.
+ * if bufsize is = 0 char *group can be set to NULL.
+ * On success groupname is returned.
+ * On failure NULL is returned.
+ * if bufsize is < 0 char *group can be set to NULL.
+ * On success groupname is returned.
+ * On failure an error message is printed and
+ * the program exits.
+ */
/* gets a groupname given a gid */
-char * bb_getgrgid(char *group, long gid, int bufsize)
+char* bb_getgrgid(char *group, long gid, int bufsize)
{
struct group *mygroup = getgrgid(gid);
- return bb_getug(group, (mygroup) ?
- mygroup->gr_name : (char *)mygroup, gid, bufsize, 'g');
+ return bb_getug(group,
+ mygroup ? mygroup->gr_name : (char *)mygroup,
+ gid, bufsize, 'g');
}
/* returns a gid given a group name */
-long bb_xgetgrnam(const char *name)
+long xgroup2gid(const char *name)
{
struct group *mygroup;
- mygroup = getgrnam(name);
- if (mygroup==NULL)
+ mygroup = getgrnam(name);
+ if (mygroup == NULL)
bb_error_msg_and_die("unknown group name: %s", name);
return mygroup->gr_gid;
}
/* returns a uid given a username */
-long bb_xgetpwnam(const char *name)
+long xuname2uid(const char *name)
{
struct passwd *myuser;
- myuser = getpwnam(name);
- if (myuser==NULL)
+ myuser = getpwnam(name);
+ if (myuser == NULL)
bb_error_msg_and_die("unknown user name: %s", name);
return myuser->pw_uid;
}
- /* Hacked by Tito Ragusa (c) 2004 <farmatito@tiscali.it> to make it more
- * flexible :
- *
- * if bufsize is > 0 char *name cannot be set to NULL.
- * On success username is written on the static allocated
- * buffer name (and a pointer to it is returned).
- * On failure uid as string is written to the static
- * allocated buffer name and NULL is returned.
- * if bufsize is = 0 char *name can be set to NULL.
- * On success username is returned.
- * On failure NULL is returned.
- * if bufsize is < 0 char *name can be set to NULL
- * On success username is returned.
- * On failure an error message is printed and
- * the program exits.
- */
+/* Hacked by Tito Ragusa (c) 2004 <farmatito@tiscali.it> to make it more
+ * flexible :
+ *
+ * if bufsize is > 0 char *name cannot be set to NULL.
+ * On success username is written on the static allocated
+ * buffer name (and a pointer to it is returned).
+ * On failure uid as string is written to the static
+ * allocated buffer name and NULL is returned.
+ * if bufsize is = 0 char *name can be set to NULL.
+ * On success username is returned.
+ * On failure NULL is returned.
+ * if bufsize is < 0 char *name can be set to NULL
+ * On success username is returned.
+ * On failure an error message is printed and
+ * the program exits.
+ */
/* gets a username given a uid */
-char * bb_getpwuid(char *name, long uid, int bufsize)
+char* bb_getpwuid(char *name, long uid, int bufsize)
{
struct passwd *myuser = getpwuid(uid);
}
unsigned long get_ug_id(const char *s,
- long (*__bb_getxxnam)(const char *))
+ long (*xname2id)(const char *))
{
unsigned long r;
r = bb_strtoul(s, NULL, 10);
if (errno)
- r = __bb_getxxnam(s);
-
+ return xname2id(s);
return r;
}
#include "busybox.h"
-unsigned uidgid_get(struct bb_uidgid_t *u, const char *ug /*, unsigned dogrp */)
+int get_uidgid(struct bb_uidgid_t *u, const char *ug, int numeric_ok)
{
struct passwd *pwd;
struct group *gr;
- const char *g;
+ char *user, *group;
+ unsigned n;
- /* g = 0; if (dogrp) g = strchr(ug, ':'); */
- g = strchr(ug, ':');
- if (g) {
- int sz = (++g) - ug;
- char buf[sz];
- safe_strncpy(buf, ug, sz);
- pwd = getpwnam(buf);
- } else
- pwd = getpwnam(ug);
+ user = (char*)ug;
+ group = strchr(ug, ':');
+ if (group) {
+ int sz = (++group) - ug;
+ user = alloca(sz);
+ /* copies sz-1 bytes, stores terminating '\0' */
+ safe_strncpy(user, ug, sz);
+ }
+ if (numeric_ok) {
+ n = bb_strtou(user, NULL, 10);
+ if (!errno) {
+ u->uid = n;
+ pwd = getpwuid(n);
+ /* If we have e.g. "500" string without user */
+ /* with uid 500 in /etc/passwd, we set gid == uid */
+ u->gid = pwd ? pwd->pw_gid : n;
+ goto skip;
+ }
+ }
+ pwd = getpwnam(user);
if (!pwd)
return 0;
u->uid = pwd->pw_uid;
u->gid = pwd->pw_gid;
- if (g) {
- gr = getgrnam(g);
+
+ skip:
+ if (group) {
+ if (numeric_ok) {
+ n = bb_strtou(group, NULL, 10);
+ if (!errno) {
+ u->gid = n;
+ return 1;
+ }
+ }
+ gr = getgrnam(group);
if (!gr) return 0;
u->gid = gr->gr_gid;
}
{
unsigned u;
struct bb_uidgid_t ug;
- u = uidgid_get(&ug, "apache");
+ u = get_uidgid(&ug, "apache", 0);
printf("%u = %u:%u\n", u, ug.uid, ug.gid);
ug.uid = ug.gid = 1111;
- u = uidgid_get(&ug, "apache");
+ u = get_uidgid(&ug, "apache", 0);
printf("%u = %u:%u\n", u, ug.uid, ug.gid);
ug.uid = ug.gid = 1111;
- u = uidgid_get(&ug, "apache:users");
+ u = get_uidgid(&ug, "apache:users", 0);
printf("%u = %u:%u\n", u, ug.uid, ug.gid);
ug.uid = ug.gid = 1111;
- u = uidgid_get(&ug, "apache:users");
+ u = get_uidgid(&ug, "apache:users", 0);
printf("%u = %u:%u\n", u, ug.uid, ug.gid);
return 0;
}
* gecos
*
* can be customized via command-line parameters.
- * ________________________________________________________________________ */
+ */
int adduser_main(int argc, char **argv)
{
struct passwd pw;
pw.pw_name = argv[optind];
pw.pw_passwd = "x";
pw.pw_uid = 0;
- pw.pw_gid = (usegroup) ? bb_xgetgrnam(usegroup) : 0; /* exits on failure */
+ pw.pw_gid = usegroup ? xgroup2gid(usegroup) : 0; /* exits on failure */
/* grand finale */
return adduser(&pw, flags);
continue;
}
- gid = (*group) ? get_ug_id(group, bb_xgetgrnam) : getgid();
- uid = (*user) ? get_ug_id(user, bb_xgetpwnam) : getuid();
+ gid = (*group) ? get_ug_id(group, xgroup2gid) : getgid();
+ uid = (*user) ? get_ug_id(user, xuname2uid) : getuid();
full_name = concat_path_file(rootdir, name);
if (type == 'd') {
{
struct bb_uidgid_t ugid;
- if (!uidgid_get(&ugid, user)) {
+ if (!get_uidgid(&ugid, user, 1)) {
bb_error_msg_and_die("unknown user/group: %s", user);
}
if (setgroups(1, &ugid.gid) == -1)
{
struct bb_uidgid_t ugid;
- if (!uidgid_get(&ugid, user)) {
+ if (!get_uidgid(&ugid, user, 1)) {
bb_error_msg_and_die("unknown user/group: %s", user);
}
xsetenv("GID", utoa(ugid.gid));