*/
#define _GNU_SOURCE
+#define _LGPL_SOURCE
#include <assert.h>
#include <ctype.h>
#include <fcntl.h>
#include <grp.h>
#include <pwd.h>
#include <sys/file.h>
+#include <dirent.h>
#include <common/common.h>
#include <common/runas.h>
+#include <common/compat/getenv.h>
#include "utils.h"
#include "defaults.h"
/* Cut the part we will be trying to resolve */
cut_path = strndup(path, next - path);
+ if (cut_path == NULL) {
+ PERROR("strndup");
+ goto error;
+ }
/* Try to resolve this part */
try_path = realpath((char *)cut_path, NULL);
* path are pointers for the same memory space
*/
cut_path = strdup(prev);
+ if (cut_path == NULL) {
+ PERROR("strdup");
+ goto error;
+ }
/* Concatenate the strings */
snprintf(resolved_path, size, "%s%s", try_path_prev, cut_path);
/* We prepare the start_path not containing it */
start_path = strndup(absolute_path, next - absolute_path);
-
+ if (!start_path) {
+ PERROR("strndup");
+ goto error;
+ }
/* And we concatenate it with the part after this string */
snprintf(absolute_path, PATH_MAX, "%s%s", start_path, next + 2);
/* Then we prepare the start_path not containing it */
start_path = strndup(absolute_path, previous - absolute_path);
+ if (!start_path) {
+ PERROR("strndup");
+ goto error;
+ }
/* And we concatenate it with the part after the '/../' */
snprintf(absolute_path, PATH_MAX, "%s%s", start_path, next + 4);
ret = fprintf(fp, "%d\n", pid);
if (ret < 0) {
PERROR("fprintf pid file");
+ goto error;
}
- fclose(fp);
+ if (fclose(fp)) {
+ PERROR("fclose");
+ }
DBG("Pid %d written in file %s", pid, filepath);
+ ret = 0;
error:
return ret;
}
*/
ret = flock(fd, LOCK_EX | LOCK_NB);
if (ret) {
- WARN("Could not get lock file %s, another instance is running.",
+ ERR("Could not get lock file %s, another instance is running.",
filepath);
- close(fd);
+ if (close(fd)) {
+ PERROR("close lock file");
+ }
fd = ret;
goto error;
}
char *val = NULL;
struct passwd *pwd;
- val = getenv(DEFAULT_LTTNG_HOME_ENV_VAR);
+ val = lttng_secure_getenv(DEFAULT_LTTNG_HOME_ENV_VAR);
if (val != NULL) {
goto end;
}
- val = getenv(DEFAULT_LTTNG_FALLBACK_HOME_ENV_VAR);
+ val = lttng_secure_getenv(DEFAULT_LTTNG_FALLBACK_HOME_ENV_VAR);
if (val != NULL) {
goto end;
}
LTTNG_HIDDEN
char *utils_get_kmod_probes_list(void)
{
- return getenv(DEFAULT_LTTNG_KMOD_PROBES);
+ return lttng_secure_getenv(DEFAULT_LTTNG_KMOD_PROBES);
}
/*
LTTNG_HIDDEN
char *utils_get_extra_kmod_probes_list(void)
{
- return getenv(DEFAULT_LTTNG_EXTRA_KMOD_PROBES);
+ return lttng_secure_getenv(DEFAULT_LTTNG_EXTRA_KMOD_PROBES);
}
/*
break;
}
- optstring[str_pos++] = (char)long_options[i].val;
- if (long_options[i].has_arg) {
- optstring[str_pos++] = ':';
+ if (long_options[i].val != '\0') {
+ optstring[str_pos++] = (char) long_options[i].val;
+ if (long_options[i].has_arg) {
+ optstring[str_pos++] = ':';
+ }
}
}
end:
return optstring;
}
+
+/*
+ * Try to remove a hierarchy of empty directories, recursively. Don't unlink
+ * any file. Try to rmdir any empty directory within the hierarchy.
+ */
+LTTNG_HIDDEN
+int utils_recursive_rmdir(const char *path)
+{
+ DIR *dir;
+ int dir_fd, ret = 0, closeret, is_empty = 1;
+ struct dirent *entry;
+
+ /* Open directory */
+ dir = opendir(path);
+ if (!dir) {
+ PERROR("Cannot open '%s' path", path);
+ return -1;
+ }
+ dir_fd = dirfd(dir);
+ if (dir_fd < 0) {
+ PERROR("dirfd");
+ return -1;
+ }
+
+ while ((entry = readdir(dir))) {
+ if (!strcmp(entry->d_name, ".")
+ || !strcmp(entry->d_name, ".."))
+ continue;
+ switch (entry->d_type) {
+ case DT_DIR:
+ {
+ char subpath[PATH_MAX];
+
+ strncpy(subpath, path, PATH_MAX);
+ subpath[PATH_MAX - 1] = '\0';
+ strncat(subpath, "/",
+ PATH_MAX - strlen(subpath) - 1);
+ strncat(subpath, entry->d_name,
+ PATH_MAX - strlen(subpath) - 1);
+ if (utils_recursive_rmdir(subpath)) {
+ is_empty = 0;
+ }
+ break;
+ }
+ case DT_REG:
+ is_empty = 0;
+ break;
+ default:
+ ret = -EINVAL;
+ goto end;
+ }
+ }
+end:
+ closeret = closedir(dir);
+ if (closeret) {
+ PERROR("closedir");
+ }
+ if (is_empty) {
+ DBG3("Attempting rmdir %s", path);
+ ret = rmdir(path);
+ }
+ return ret;
+}