chiark / gitweb /
path: avoid an allocation in path_spec_watch
authorMichal Schmidt <mschmidt@redhat.com>
Wed, 6 Mar 2013 18:28:55 +0000 (19:28 +0100)
committerMichal Schmidt <mschmidt@redhat.com>
Fri, 8 Mar 2013 09:58:51 +0000 (10:58 +0100)
No need for strdup. We can slice the path in place if we always undo it
afterwards.

src/core/path.c

index 01a2b08..295e5cd 100644 (file)
@@ -53,7 +53,6 @@ int path_spec_watch(PathSpec *s, Unit *u) {
         };
 
         bool exists = false;
-        char _cleanup_free_ *path = NULL;
         char *slash, *oldslash = NULL;
         int r;
 
@@ -62,10 +61,6 @@ int path_spec_watch(PathSpec *s, Unit *u) {
 
         path_spec_unwatch(s, u);
 
-        path = strdup(s->path);
-        if (!path)
-                return -ENOMEM;
-
         s->inotify_fd = inotify_init1(IN_NONBLOCK|IN_CLOEXEC);
         if (s->inotify_fd < 0) {
                 r = -errno;
@@ -78,25 +73,32 @@ int path_spec_watch(PathSpec *s, Unit *u) {
 
         /* This assumes the path was passed through path_kill_slashes()! */
 
-        for(slash = strchr(path, '/'); ; slash = strchr(slash+1, '/')) {
+        for (slash = strchr(s->path, '/'); ; slash = strchr(slash+1, '/')) {
+                char *cut = NULL;
                 int flags;
                 char tmp;
 
                 if (slash) {
-                        tmp = slash[slash == path];
-                        slash[slash == path] = '\0';
+                        cut = slash + (slash == s->path);
+                        tmp = *cut;
+                        *cut = '\0';
+
                         flags = IN_MOVE_SELF | IN_DELETE_SELF | IN_ATTRIB | IN_CREATE | IN_MOVED_TO;
-                } else {
+                } else
                         flags = flags_table[s->type];
-                }
 
-                r = inotify_add_watch(s->inotify_fd, path, flags);
+                r = inotify_add_watch(s->inotify_fd, s->path, flags);
                 if (r < 0) {
-                        if (errno == EACCES || errno == ENOENT)
+                        if (errno == EACCES || errno == ENOENT) {
+                                if (cut)
+                                        *cut = tmp;
                                 break;
+                        }
 
-                        log_warning("Failed to add watch on %s: %m", path);
+                        log_warning("Failed to add watch on %s: %m", s->path);
                         r = -errno;
+                        if (cut)
+                                *cut = tmp;
                         goto fail;
                 } else {
                         exists = true;
@@ -104,29 +106,30 @@ int path_spec_watch(PathSpec *s, Unit *u) {
                         /* Path exists, we don't need to watch parent
                            too closely. */
                         if (oldslash) {
-                                char tmp2 = oldslash[oldslash == path];
-                                oldslash[oldslash == path] = '\0';
+                                char *cut2 = oldslash + (oldslash == s->path);
+                                char tmp2 = *cut2;
+                                *cut2 = '\0';
 
-                                inotify_add_watch(s->inotify_fd, path, IN_MOVE_SELF);
+                                inotify_add_watch(s->inotify_fd, s->path, IN_MOVE_SELF);
                                 /* Error is ignored, the worst can happen is
                                    we get spurious events. */
 
-                                oldslash[oldslash == path] = tmp2;
+                                *cut2 = tmp2;
                         }
                 }
 
-                if (slash) {
-                        slash[slash == path] = tmp;
+                if (cut)
+                        *cut = tmp;
+
+                if (slash)
                         oldslash = slash;
-                else {
+                else {
                         /* whole path has been iterated over */
                         s->primary_wd = r;
                         break;
                 }
         }
 
-        assert(errno == EACCES || errno == ENOENT || streq(path, s->path));
-
         if (!exists) {
                 log_error("Failed to add watch on any of the components of %s: %m",
                           s->path);