]> git.cameronkatri.com Git - pw-darwin.git/blobdiff - libutil/gr_util.c
Add O_CLOEXEC to flopen
[pw-darwin.git] / libutil / gr_util.c
index 8d0490be7057072829e3b5cc9e5af2fe70c960d2..4583257d360f9a053b67f00a54ec10cc003f4497 100644 (file)
@@ -44,11 +44,6 @@ __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];
@@ -106,10 +101,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,14 +311,10 @@ gr_copy(int ffd, int tfd, const struct group *gr, struct group *old_gr)
 int
 gr_mkdb(void)
 {
-       int ret;
-
-       ret = rename(tempname, group_file);
-
-       if (ret == 0)
-               chmod(group_file, 0644);
+       if (chmod(tempname, 0644) != 0)
+               return (-1);
 
-       return (ret);
+       return (rename(tempname, group_file));
 }
 
 /*
@@ -440,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)
@@ -458,30 +447,73 @@ 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 + sizeof(struct group);
+       else
+               newgr->gr_mem = NULL;
+       /* point dst after the end of all the gr_mem pointers in newgr */
+       dst = (char *)newgr + sizeof(struct group) +
+           (num_mem + 1) * sizeof(*gr->gr_mem);
        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;
        }
        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;
        }
-       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) {
+               errno = ENOMEM;
+               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);
+       if (newgr == NULL)
+               errno = ENOMEM;
+       free(members);
+       return (newgr);
 }
 
 /*