[ovs-dev] [PATCH 2/4] util: New functions get_cwd(), abs_file_name().

Ben Pfaff blp at nicira.com
Tue Mar 16 22:24:37 UTC 2010


These will be used further in an upcoming commit.
---
 lib/daemon.c         |    6 ++--
 lib/unixctl.c        |   12 +--------
 lib/util.c           |   62 ++++++++++++++++++++++++++++++++++++++++++++++++++
 lib/util.h           |    2 +
 lib/vlog-modules.def |    1 +
 5 files changed, 70 insertions(+), 13 deletions(-)

diff --git a/lib/daemon.c b/lib/daemon.c
index 46c9a88..081912b 100644
--- a/lib/daemon.c
+++ b/lib/daemon.c
@@ -58,9 +58,9 @@ static bool monitor;
 char *
 make_pidfile_name(const char *name) 
 {
-    return (!name ? xasprintf("%s/%s.pid", ovs_rundir, program_name)
-            : *name == '/' ? xstrdup(name)
-            : xasprintf("%s/%s", ovs_rundir, name));
+    return (!name
+            ? xasprintf("%s/%s.pid", ovs_rundir, program_name)
+            : abs_file_name(ovs_rundir, name));
 }
 
 /* Sets up a following call to daemonize() to create a pidfile named 'name'.
diff --git a/lib/unixctl.c b/lib/unixctl.c
index f710ffd..88fe603 100644
--- a/lib/unixctl.c
+++ b/lib/unixctl.c
@@ -186,11 +186,7 @@ unixctl_server_create(const char *path, struct unixctl_server **serverp)
     list_init(&server->conns);
 
     if (path) {
-        if (path[0] == '/') {
-            server->path = xstrdup(path);
-        } else {
-            server->path = xasprintf("%s/%s", ovs_rundir, path);
-        }
+        server->path = abs_file_name(ovs_rundir, path);
     } else {
         server->path = xasprintf("%s/%s.%ld.ctl", ovs_rundir,
                                  program_name, (long int) getpid());
@@ -461,11 +457,7 @@ unixctl_client_create(const char *path, struct unixctl_client **clientp)
 
     /* Determine location. */
     client = xmalloc(sizeof *client);
-    if (path[0] == '/') {
-        client->connect_path = xstrdup(path);
-    } else {
-        client->connect_path = xasprintf("%s/%s", ovs_rundir, path);
-    }
+    client->connect_path = abs_file_name(ovs_rundir, path);
     client->bind_path = xasprintf("/tmp/vlog.%ld.%d",
                                   (long int) getpid(), counter++);
 
diff --git a/lib/util.c b/lib/util.c
index 8f1892e..19f13dd 100644
--- a/lib/util.c
+++ b/lib/util.c
@@ -21,8 +21,12 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <unistd.h>
 #include "coverage.h"
 
+#define THIS_MODULE VLM_util
+#include "vlog.h"
+
 const char *program_name;
 
 void
@@ -358,6 +362,37 @@ hexit_value(int c)
     NOT_REACHED();
 }
 
+/* Returns the current working directory as a malloc()'d string, or a null
+ * pointer if the current working directory cannot be determined. */
+char *
+get_cwd(void)
+{
+    long int path_max;
+    size_t size;
+
+    /* Get maximum path length or at least a reasonable estimate. */
+    path_max = pathconf(".", _PC_PATH_MAX);
+    size = (path_max < 0 ? 1024
+            : path_max > 10240 ? 10240
+            : path_max);
+
+    /* Get current working directory. */
+    for (;;) {
+        char *buf = xmalloc(size);
+        if (getcwd(buf, size)) {
+            return xrealloc(buf, strlen(buf) + 1);
+        } else {
+            int error = errno;
+            free(buf);
+            if (error != ERANGE) {
+                VLOG_WARN("getcwd failed (%s)", strerror(error));
+                return NULL;
+            }
+            size *= 2;
+        }
+    }
+}
+
 /* Returns the directory name portion of 'file_name' as a malloc()'d string,
  * similar to the POSIX dirname() function but thread-safe. */
 char *
@@ -384,6 +419,33 @@ dir_name(const char *file_name)
     }
 }
 
+/* If 'file_name' starts with '/', returns a copy of 'file_name'.  Otherwise,
+ * returns an absolute path to 'file_name' considering it relative to 'dir',
+ * which itself must be absolute.  'dir' may be null or the empty string, in
+ * which case the current working directory is used.
+ *
+ * Returns a null pointer if 'dir' is null and getcwd() fails. */
+char *
+abs_file_name(const char *dir, const char *file_name)
+{
+    if (file_name[0] == '/') {
+        return xstrdup(file_name);
+    } else if (dir && dir[0]) {
+        char *separator = dir[strlen(dir) - 1] == '/' ? "" : "/";
+        return xasprintf("%s%s%s", dir, separator, file_name);
+    } else {
+        char *cwd = get_cwd();
+        if (cwd) {
+            char *abs_name = xasprintf("%s/%s", cwd, file_name);
+            free(cwd);
+            return abs_name;
+        } else {
+            return NULL;
+        }
+    }
+}
+
+
 /* Pass a value to this function if it is marked with
  * __attribute__((warn_unused_result)) and you genuinely want to ignore 
  * its return value.  (Note that every scalar type can be implicitly 
diff --git a/lib/util.h b/lib/util.h
index a9d5048..9df6db5 100644
--- a/lib/util.h
+++ b/lib/util.h
@@ -123,7 +123,9 @@ bool str_to_double(const char *, double *);
 
 int hexit_value(int c);
 
+char *get_cwd(void);
 char *dir_name(const char *file_name);
+char *abs_file_name(const char *dir, const char *file_name);
 
 void ignore(bool x OVS_UNUSED);
 
diff --git a/lib/vlog-modules.def b/lib/vlog-modules.def
index f012e10..b8a001c 100644
--- a/lib/vlog-modules.def
+++ b/lib/vlog-modules.def
@@ -83,6 +83,7 @@ VLOG_MODULE(tty)
 VLOG_MODULE(socket_util)
 VLOG_MODULE(switchui)
 VLOG_MODULE(unixctl)
+VLOG_MODULE(util)
 VLOG_MODULE(vconn_tcp)
 VLOG_MODULE(vconn_ssl)
 VLOG_MODULE(vconn_stream)
-- 
1.6.6.1





More information about the dev mailing list