Add session configuration save feature to session daemon
[lttng-tools.git] / src / common / utils.c
index 3a4f850ba66b22f19d78bdbd9dd52e1257d8ba75..31596ddd36c3a3314daa2de1db6db19690b7800a 100644 (file)
@@ -1,6 +1,7 @@
 /*
  * Copyright (C) 2012 - David Goulet <dgoulet@efficios.com>
  * Copyright (C) 2013 - Raphaël Beamonte <raphael.beamonte@gmail.com>
+ * Copyright (C) 2013 - Jérémie Galarneau <jeremie.galarneau@efficios.com>
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License, version 2 only, as
@@ -29,6 +30,7 @@
 #include <inttypes.h>
 #include <regex.h>
 #include <grp.h>
+#include <pwd.h>
 
 #include <common/common.h>
 #include <common/runas.h>
@@ -178,6 +180,8 @@ LTTNG_HIDDEN
 char *utils_expand_path(const char *path)
 {
        char *next, *previous, *slash, *start_path, *absolute_path = NULL;
+       char *last_token;
+       int is_dot, is_dotdot;
 
        /* Safety net */
        if (path == NULL) {
@@ -198,7 +202,7 @@ char *utils_expand_path(const char *path)
        if (*path != '/' && strncmp(path, "./", 2) != 0 &&
                        strncmp(path, "../", 3) != 0) {
                snprintf(absolute_path, PATH_MAX, "./%s", path);
-               /* Else, we just copy the path */
+       /* Else, we just copy the path */
        } else {
                strncpy(absolute_path, path, PATH_MAX);
        }
@@ -241,6 +245,31 @@ char *utils_expand_path(const char *path)
                                absolute_path, PATH_MAX);
        }
 
+       /* Identify the last token */
+       last_token = strrchr(absolute_path, '/');
+
+       /* Verify that this token is not a relative path */
+       is_dotdot = (strcmp(last_token, "/..") == 0);
+       is_dot = (strcmp(last_token, "/.") == 0);
+
+       /* If it is, take action */
+       if (is_dot || is_dotdot) {
+               /* For both, remove this token */
+               *last_token = '\0';
+
+               /* If it was a reference to parent directory, go back one more time */
+               if (is_dotdot) {
+                       last_token = strrchr(absolute_path, '/');
+
+                       /* If there was only one level left, we keep the first '/' */
+                       if (last_token == absolute_path) {
+                               last_token++;
+                       }
+
+                       *last_token = '\0';
+               }
+       }
+
        return absolute_path;
 
 error:
@@ -826,6 +855,46 @@ char *utils_get_home_dir(void)
        return getenv(DEFAULT_LTTNG_FALLBACK_HOME_ENV_VAR);
 }
 
+/**
+ * Get user's home directory. Dynamically allocated, must be freed
+ * by the caller.
+ */
+LTTNG_HIDDEN
+char *utils_get_user_home_dir(uid_t uid)
+{
+       struct passwd pwd;
+       struct passwd *result;
+       char *home_dir = NULL;
+       char *buf = NULL;
+       long buflen;
+       int ret;
+
+       buflen = sysconf(_SC_GETPW_R_SIZE_MAX);
+       if (buflen == -1) {
+               goto end;
+       }
+retry:
+       buf = zmalloc(buflen);
+       if (!buf) {
+               goto end;
+       }
+
+       ret = getpwuid_r(uid, &pwd, buf, buflen, &result);
+       if (ret || !result) {
+               if (ret == ERANGE) {
+                       free(buf);
+                       buflen *= 2;
+                       goto retry;
+               }
+               goto end;
+       }
+
+       home_dir = strdup(pwd.pw_dir);
+end:
+       free(buf);
+       return home_dir;
+}
+
 /*
  * With the given format, fill dst with the time of len maximum siz.
  *
@@ -873,3 +942,46 @@ gid_t utils_get_group_id(const char *name)
        }
        return grp->gr_gid;
 }
+
+/*
+ * Return a newly allocated option string. This string is to be used as the
+ * optstring argument of getopt_long(), see GETOPT(3). opt_count is the number
+ * of elements in the long_options array. Returns NULL if the string's
+ * allocation fails.
+ */
+LTTNG_HIDDEN
+char *utils_generate_optstring(const struct option *long_options,
+               size_t opt_count)
+{
+       int i;
+       size_t string_len = opt_count, str_pos = 0;
+       char *optstring;
+
+       /*
+        * Compute the necessary string length. One letter per option, two when an
+        * argument is necessary, and a trailing NULL.
+        */
+       for (i = 0; i < opt_count; i++) {
+               string_len += long_options[i].has_arg ? 1 : 0;
+       }
+
+       optstring = zmalloc(string_len);
+       if (!optstring) {
+               goto end;
+       }
+
+       for (i = 0; i < opt_count; i++) {
+               if (!long_options[i].name) {
+                       /* Got to the trailing NULL element */
+                       break;
+               }
+
+               optstring[str_pos++] = (char)long_options[i].val;
+               if (long_options[i].has_arg) {
+                       optstring[str_pos++] = ':';
+               }
+       }
+
+end:
+       return optstring;
+}
This page took 0.025017 seconds and 4 git commands to generate.