chiark / gitweb /
bus-proxy: ECONNRESET/ENOTCONN can hit us on every step, hence handle it on every...
[elogind.git] / src / udev / collect / collect.c
index 882564a5f52bb58310933fb37b21c64d934ff873..4bb6edbef11da04c35b3099b2a664e6e8f3fb4a3 100644 (file)
 
 #include "libudev.h"
 #include "libudev-private.h"
+#include "macro.h"
 
-#define BUFSIZE                        16
-#define UDEV_ALARM_TIMEOUT        180
+#define BUFSIZE 16
+#define UDEV_ALARM_TIMEOUT 180
 
 enum collect_state {
         STATE_NONE,
@@ -55,31 +56,31 @@ static int debug;
 /* This can increase dynamically */
 static size_t bufsize = BUFSIZE;
 
-static struct _mate *node_to_mate(struct udev_list_node *node)
+static inline struct _mate *node_to_mate(struct udev_list_node *node)
 {
-        char *mate;
-
-        mate = (char *)node;
-        mate -= offsetof(struct _mate, node);
-        return (struct _mate *)mate;
+        return container_of(node, struct _mate, node);
 }
 
-static void sig_alrm(int signo)
+noreturn static void sig_alrm(int signo)
 {
         exit(4);
 }
 
 static void usage(void)
 {
-        printf("usage: collect [--add|--remove] [--debug] <checkpoint> <id> <idlist>\n"
-               "\n"
+        printf("%s [options] <checkpoint> <id> <idlist>\n\n"
+               "Collect variables across events.\n\n"
+               "  -h --help        Print this message\n"
+               "  -a --add         Add ID <id> to the list <idlist>\n"
+               "  -r --remove      Remove ID <id> from the list <idlist>\n"
+               "  -d --debug       Debug to stderr\n\n"
                "  Adds ID <id> to the list governed by <checkpoint>.\n"
                "  <id> must be part of the list <idlist>.\n"
                "  If all IDs given by <idlist> are listed (ie collect has been\n"
                "  invoked for each ID in <idlist>) collect returns 0, the\n"
                "  number of missing IDs otherwise.\n"
-               "  On error a negative number is returned.\n"
-               "\n");
+               "  On error a negative number is returned.\n\n"
+               , program_invocation_short_name);
 }
 
 /*
@@ -89,18 +90,18 @@ static void usage(void)
  */
 static int prepare(char *dir, char *filename)
 {
-        struct stat statbuf;
         char buf[512];
-        int fd;
+        int r, fd;
 
-        if (stat(dir, &statbuf) < 0)
-                mkdir(dir, 0700);
+        r = mkdir(dir, 0700);
+        if (r < 0 && errno != EEXIST)
+                return -errno;
 
-        sprintf(buf, "%s/%s", dir, filename);
+        snprintf(buf, sizeof(buf), "%s/%s", dir, filename);
 
-        fd = open(buf,O_RDWR|O_CREAT, S_IRUSR|S_IWUSR);
+        fd = open(buf,O_RDWR|O_CREAT|O_CLOEXEC, S_IRUSR|S_IWUSR);
         if (fd < 0)
-                fprintf(stderr, "Cannot open %s: %s\n", buf, strerror(errno));
+                fprintf(stderr, "Cannot open %s: %m\n", buf);
 
         if (lockf(fd,F_TLOCK,0) < 0) {
                 if (debug)
@@ -112,7 +113,7 @@ static int prepare(char *dir, char *filename)
                                 fprintf(stderr, "Acquired lock on %s\n", buf);
                 } else {
                         if (debug)
-                                fprintf(stderr, "Could not get lock on %s: %s\n", buf, strerror(errno));
+                                fprintf(stderr, "Could not get lock on %s: %m\n", buf);
                 }
         }
 
@@ -142,12 +143,12 @@ static int checkout(int fd)
 
  restart:
         len = bufsize >> 1;
-        buf = calloc(1,bufsize + 1);
-        if (!buf) {
-                fprintf(stderr, "Out of memory\n");
-                return -1;
-        }
+        buf = malloc(bufsize + 1);
+        if (!buf)
+                return log_oom();
         memset(buf, ' ', bufsize);
+        buf[bufsize] = '\0';
+
         ptr = buf + len;
         while ((read(fd, buf + len, len)) > 0) {
                 while (ptr && *ptr) {
@@ -156,7 +157,7 @@ static int checkout(int fd)
                         if (!ptr && word < (buf + len)) {
                                 bufsize = bufsize << 1;
                                 if (debug)
-                                        fprintf(stderr, "ID overflow, restarting with size %zi\n", bufsize);
+                                        fprintf(stderr, "ID overflow, restarting with size %zu\n", bufsize);
                                 free(buf);
                                 lseek(fd, 0, SEEK_SET);
                                 goto restart;
@@ -170,7 +171,16 @@ static int checkout(int fd)
                                 if (debug)
                                         fprintf(stderr, "Found word %s\n", word);
                                 him = malloc(sizeof (struct _mate));
+                                if (!him) {
+                                        free(buf);
+                                        return log_oom();
+                                }
                                 him->name = strdup(word);
+                                if (!him->name) {
+                                        free(buf);
+                                        free(him);
+                                        return log_oom();
+                                }
                                 him->state = STATE_OLD;
                                 udev_list_node_append(&him->node, &bunch);
                                 word = NULL;
@@ -207,7 +217,7 @@ static void invite(char *us)
         udev_list_node_foreach(him_node, &bunch) {
                 struct _mate *him = node_to_mate(him_node);
 
-                if (!strcmp(him->name, us)) {
+                if (streq(him->name, us)) {
                         him->state = STATE_CONFIRMED;
                         who = him;
                 }
@@ -235,7 +245,7 @@ static void reject(char *us)
         udev_list_node_foreach(him_node, &bunch) {
                 struct _mate *him = node_to_mate(him_node);
 
-                if (!strcmp(him->name, us)) {
+                if (streq(him->name, us)) {
                         him->state = STATE_NONE;
                         who = him;
                 }
@@ -248,7 +258,7 @@ static void reject(char *us)
  * kickout
  *
  * Remove all IDs in the internal list which are not part
- * of the list passed via the commandline.
+ * of the list passed via the command line.
  */
 static void kickout(void)
 {
@@ -279,7 +289,7 @@ static int missing(int fd)
 
         buf = malloc(bufsize);
         if (!buf)
-                return -1;
+                return log_oom();
 
         udev_list_node_foreach(him_node, &bunch) {
                 struct _mate *him = node_to_mate(him_node);
@@ -294,12 +304,15 @@ static int missing(int fd)
                                 tmpbuf = realloc(buf, bufsize);
                                 if (!tmpbuf) {
                                         free(buf);
-                                        return -1;
+                                        return log_oom();
                                 }
                                 buf = tmpbuf;
                         }
                         snprintf(buf, strlen(him->name)+2, "%s ", him->name);
-                        write(fd, buf, strlen(buf));
+                        if (write(fd, buf, strlen(buf)) < 0) {
+                                free(buf);
+                                return -1;
+                        }
                 }
         }
 
@@ -395,7 +408,7 @@ int main(int argc, char **argv)
         us = argv[argi++];
 
         if (signal(SIGALRM, sig_alrm) == SIG_ERR) {
-                fprintf(stderr, "Cannot set SIGALRM: %s\n", strerror(errno));
+                fprintf(stderr, "Cannot set SIGALRM: %m\n");
                 ret = 2;
                 goto exit;
         }
@@ -405,7 +418,7 @@ int main(int argc, char **argv)
         if (debug)
                 fprintf(stderr, "Using checkpoint '%s'\n", checkpoint);
 
-        util_strscpyl(tmpdir, sizeof(tmpdir), "/run/udev/collect", NULL);
+        strscpyl(tmpdir, sizeof(tmpdir), "/run/udev/collect", NULL);
         fd = prepare(tmpdir, checkpoint);
         if (fd < 0) {
                 ret = 3;
@@ -425,7 +438,7 @@ int main(int argc, char **argv)
                 udev_list_node_foreach(him_node, &bunch) {
                         struct _mate *him = node_to_mate(him_node);
 
-                        if (!strcmp(him->name, argv[i]))
+                        if (streq(him->name, argv[i]))
                                 who = him;
                 }
                 if (!who) {
@@ -433,9 +446,19 @@ int main(int argc, char **argv)
 
                         if (debug)
                                 fprintf(stderr, "ID %s: not in database\n", argv[i]);
-                        him = malloc(sizeof (struct _mate));
-                        him->name = malloc(strlen(argv[i]) + 1);
-                        strcpy(him->name, argv[i]);
+                        him = new(struct _mate, 1);
+                        if (!him) {
+                                ret = ENOMEM;
+                                goto out;
+                        }
+
+                        him->name = strdup(argv[i]);
+                        if (!him->name) {
+                                free(him);
+                                ret = ENOMEM;
+                                goto out;
+                        }
+
                         him->state = STATE_NONE;
                         udev_list_node_append(&him->node, &bunch);
                 } else {