util: New functions get_cwd(), abs_file_name().
authorBen Pfaff <blp@nicira.com>
Tue, 16 Mar 2010 22:06:11 +0000 (15:06 -0700)
committerBen Pfaff <blp@nicira.com>
Thu, 18 Mar 2010 18:23:50 +0000 (11:23 -0700)
These will be used further in an upcoming commit.

lib/daemon.c
lib/unixctl.c
lib/util.c
lib/util.h
lib/vlog-modules.def

index 46c9a88e750bc554cda1c92393a6412bd7eba633..081912b128c230c59550608059ea4cdc9a8b25a0 100644 (file)
@@ -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'.
index f710ffd60fb363b8837fec387b372ad987f2409a..88fe60352453dc4b9531302b13628e5a14f6e9a0 100644 (file)
@@ -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++);
 
index 8f1892ed2c4e0566075a05afa27de5382a2b6e5f..19f13dddc1f3f902b9964354e49381cd2221b8ef 100644 (file)
 #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 
index a9d5048a09b439d2cb15386e80cb79ef761bde65..9df6db5836833522dfeb955fa98e19354f232fda 100644 (file)
@@ -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);
 
index e3a0ebd23de15deabe0cbecf6230d18afdf98a6e..dac8162580cda8e3305251b89d957c992a4e8503 100644 (file)
@@ -84,6 +84,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)