diff options
author | David E. O'Brien <obrien@FreeBSD.org> | 2013-02-08 16:10:16 +0000 |
---|---|---|
committer | David E. O'Brien <obrien@FreeBSD.org> | 2013-02-08 16:10:16 +0000 |
commit | d9a447559bc04121f7c6682e64abe67efa154864 (patch) | |
tree | b2f038222ff8a70f687652441df00d2b564c8abe /lib/libutil | |
parent | 3cbf5f97aafc2b249c509ee1162c47c9b28e591e (diff) | |
parent | fbda3d5daeeb730a49d025b614b35a32f0319718 (diff) | |
download | src-d9a447559bc04121f7c6682e64abe67efa154864.tar.gz src-d9a447559bc04121f7c6682e64abe67efa154864.zip |
Sync with HEAD.
Notes
Notes:
svn path=/projects/bmake/; revision=246555
Diffstat (limited to 'lib/libutil')
-rw-r--r-- | lib/libutil/gr_util.c | 120 | ||||
-rw-r--r-- | lib/libutil/libutil.h | 2 | ||||
-rw-r--r-- | lib/libutil/pw_util.c | 7 |
3 files changed, 83 insertions, 46 deletions
diff --git a/lib/libutil/gr_util.c b/lib/libutil/gr_util.c index 6d96d5e9405e..3f7e19901e2a 100644 --- a/lib/libutil/gr_util.c +++ b/lib/libutil/gr_util.c @@ -44,19 +44,12 @@ __FBSDID("$FreeBSD$"); #include <string.h> #include <unistd.h> -struct group_storage { - struct group gr; - char *members[]; -}; - static int lockfd = -1; static char group_dir[PATH_MAX]; static char group_file[PATH_MAX]; static char tempname[PATH_MAX]; static int initialized; -static const char group_line_format[] = "%s:%s:%ju:"; - /* * Initialize statics */ @@ -106,10 +99,8 @@ gr_lock(void) for (;;) { struct stat st; - lockfd = open(group_file, O_RDONLY, 0); - if (lockfd < 0 || fcntl(lockfd, F_SETFD, 1) == -1) - err(1, "%s", group_file); - if (flock(lockfd, LOCK_EX|LOCK_NB) == -1) { + lockfd = flopen(group_file, O_RDONLY|O_NONBLOCK|O_CLOEXEC, 0); + if (lockfd == -1) { if (errno == EWOULDBLOCK) { errx(1, "the group file is busy"); } else { @@ -318,11 +309,14 @@ gr_copy(int ffd, int tfd, const struct group *gr, struct group *old_gr) int gr_mkdb(void) { + if (chmod(tempname, 0644) != 0) + return (-1); + return (rename(tempname, group_file)); } /* - * Clean up. Preserver errno for the caller's convenience. + * Clean up. Preserves errno for the caller's convenience. */ void gr_fini(void) @@ -350,7 +344,6 @@ gr_equal(const struct group *gr1, const struct group *gr2) { int gr1_ndx; int gr2_ndx; - bool found; /* Check that the non-member information is the same. */ if (gr1->gr_name == NULL || gr2->gr_name == NULL) { @@ -371,17 +364,15 @@ gr_equal(const struct group *gr1, const struct group *gr2) if (gr1->gr_mem != gr2->gr_mem) return (false); } else { - for (found = false, gr1_ndx = 0; gr1->gr_mem[gr1_ndx] != NULL; - gr1_ndx++) { - for (gr2_ndx = 0; gr2->gr_mem[gr2_ndx] != NULL; - gr2_ndx++) + for (gr1_ndx = 0; gr1->gr_mem[gr1_ndx] != NULL; gr1_ndx++) { + for (gr2_ndx = 0;; gr2_ndx++) { + if (gr2->gr_mem[gr2_ndx] == NULL) + return (false); if (strcmp(gr1->gr_mem[gr1_ndx], gr2->gr_mem[gr2_ndx]) == 0) { - found = true; break; } - if (!found) - return (false); + } } /* Check that group2 does not have more members than group1. */ @@ -398,7 +389,10 @@ gr_equal(const struct group *gr1, const struct group *gr2) char * gr_make(const struct group *gr) { + const char *group_line_format = "%s:%s:%ju:"; + const char *sep; char *line; + char *p; size_t line_size; int ndx; @@ -413,16 +407,18 @@ gr_make(const struct group *gr) } /* Create the group line and fill it. */ - if ((line = malloc(line_size)) == NULL) + if ((line = p = malloc(line_size)) == NULL) return (NULL); - snprintf(line, line_size, group_line_format, gr->gr_name, gr->gr_passwd, + p += sprintf(p, group_line_format, gr->gr_name, gr->gr_passwd, (uintmax_t)gr->gr_gid); - if (gr->gr_mem != NULL) + if (gr->gr_mem != NULL) { + sep = ""; for (ndx = 0; gr->gr_mem[ndx] != NULL; ndx++) { - strcat(line, gr->gr_mem[ndx]); - if (gr->gr_mem[ndx + 1] != NULL) - strcat(line, ","); + p = stpcpy(p, sep); + p = stpcpy(p, gr->gr_mem[ndx]); + sep = ","; } + } return (line); } @@ -433,14 +429,14 @@ gr_make(const struct group *gr) struct group * gr_dup(const struct group *gr) { + struct group *newgr; char *dst; size_t len; - struct group_storage *gs; int ndx; int num_mem; /* Calculate size of the group. */ - len = sizeof(*gs); + len = sizeof(*newgr); if (gr->gr_name != NULL) len += strlen(gr->gr_name) + 1; if (gr->gr_passwd != NULL) @@ -451,30 +447,72 @@ gr_dup(const struct group *gr) len += (num_mem + 1) * sizeof(*gr->gr_mem); } else num_mem = -1; - /* Create new group and copy old group into it. */ - if ((gs = calloc(1, len)) == NULL) + if ((newgr = malloc(len)) == NULL) return (NULL); - dst = (char *)&gs->members[num_mem + 1]; + /* point new gr_mem to end of struct + 1 */ + if (gr->gr_mem != NULL) + newgr->gr_mem = (char **)(newgr + 1); + else + newgr->gr_mem = NULL; + /* point dst after the end of all the gr_mem pointers in newgr */ + dst = (char *)&newgr->gr_mem[num_mem + 1]; if (gr->gr_name != NULL) { - gs->gr.gr_name = dst; - dst = stpcpy(gs->gr.gr_name, gr->gr_name) + 1; + newgr->gr_name = dst; + dst = stpcpy(dst, gr->gr_name) + 1; + } else { + newgr->gr_name = NULL; } if (gr->gr_passwd != NULL) { - gs->gr.gr_passwd = dst; - dst = stpcpy(gs->gr.gr_passwd, gr->gr_passwd) + 1; + newgr->gr_passwd = dst; + dst = stpcpy(dst, gr->gr_passwd) + 1; + } else { + newgr->gr_passwd = NULL; } - gs->gr.gr_gid = gr->gr_gid; + newgr->gr_gid = gr->gr_gid; if (gr->gr_mem != NULL) { - gs->gr.gr_mem = gs->members; for (ndx = 0; ndx < num_mem; ndx++) { - gs->gr.gr_mem[ndx] = dst; - dst = stpcpy(gs->gr.gr_mem[ndx], gr->gr_mem[ndx]) + 1; + newgr->gr_mem[ndx] = dst; + dst = stpcpy(dst, gr->gr_mem[ndx]) + 1; } - gs->gr.gr_mem[ndx] = NULL; + newgr->gr_mem[ndx] = NULL; } + return (newgr); +} + +/* + * Add a new member name to a struct group. + */ +struct group * +gr_add(struct group *gr, char *newmember) +{ + size_t mlen; + int num_mem=0; + char **members; + struct group *newgr; - return (&gs->gr); + if (newmember == NULL) + return(gr_dup(gr)); + + if (gr->gr_mem != NULL) { + for (num_mem = 0; gr->gr_mem[num_mem] != NULL; num_mem++) { + if (strcmp(gr->gr_mem[num_mem], newmember) == 0) { + errno = EEXIST; + return (NULL); + } + } + } + /* Allocate enough for current pointers + 1 more and NULL marker */ + mlen = (num_mem + 2) * sizeof(*gr->gr_mem); + if ((members = malloc(mlen)) == NULL) + return (NULL); + memcpy(members, gr->gr_mem, num_mem * sizeof(*gr->gr_mem)); + members[num_mem++] = newmember; + members[num_mem] = NULL; + gr->gr_mem = members; + newgr = gr_dup(gr); + free(members); + return (newgr); } /* diff --git a/lib/libutil/libutil.h b/lib/libutil/libutil.h index bf42766a128c..b1b2405fb272 100644 --- a/lib/libutil/libutil.h +++ b/lib/libutil/libutil.h @@ -166,6 +166,8 @@ int gr_copy(int __ffd, int _tfd, const struct group *_gr, struct group *_old_gr); struct group * gr_dup(const struct group *_gr); +struct group * + gr_add(struct group *_gr, char *_newmember); int gr_equal(const struct group *_gr1, const struct group *_gr2); void gr_fini(void); int gr_init(const char *_dir, const char *_master); diff --git a/lib/libutil/pw_util.c b/lib/libutil/pw_util.c index 4bf3001ffe79..befd1fb02d70 100644 --- a/lib/libutil/pw_util.c +++ b/lib/libutil/pw_util.c @@ -179,11 +179,8 @@ pw_lock(void) for (;;) { struct stat st; - lockfd = open(masterpasswd, O_RDONLY, 0); - if (lockfd < 0 || fcntl(lockfd, F_SETFD, 1) == -1) - err(1, "%s", masterpasswd); - /* XXX vulnerable to race conditions */ - if (flock(lockfd, LOCK_EX|LOCK_NB) == -1) { + lockfd = flopen(masterpasswd, O_RDONLY|O_NONBLOCK|O_CLOEXEC, 0); + if (lockfd == -1) { if (errno == EWOULDBLOCK) { errx(1, "the password db file is busy"); } else { |