X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=src%2Fcommon%2Futils.c;h=1c2b95d3e7d5d3e427bc4c20f59ba4483062dea9;hb=be96a7d15e24cd8742c404cf3a76d14c75b00f06;hp=2f114934fd78c654a43a9b5563f6929bc7422ec6;hpb=35f90c40cf023393851ac47ad526a0e9e1184503;p=lttng-tools.git diff --git a/src/common/utils.c b/src/common/utils.c index 2f114934f..1c2b95d3e 100644 --- a/src/common/utils.c +++ b/src/common/utils.c @@ -22,8 +22,13 @@ #include #include #include +#include +#include +#include +#include #include +#include #include "utils.h" @@ -33,7 +38,7 @@ * /tmp/test1 does, the real path is returned. In normal time, realpath(3) * fails if the end point directory does not exist. */ -__attribute__((visibility("hidden"))) +LTTNG_HIDDEN char *utils_expand_path(const char *path) { const char *end_path = path; @@ -86,7 +91,7 @@ error: /* * Create a pipe in dst. */ -__attribute__((visibility("hidden"))) +LTTNG_HIDDEN int utils_create_pipe(int *dst) { int ret; @@ -109,7 +114,7 @@ int utils_create_pipe(int *dst) * Make sure the pipe opened by this function are closed at some point. Use * utils_close_pipe(). */ -__attribute__((visibility("hidden"))) +LTTNG_HIDDEN int utils_create_pipe_cloexec(int *dst) { int ret, i; @@ -138,7 +143,7 @@ error: /* * Close both read and write side of the pipe. */ -__attribute__((visibility("hidden"))) +LTTNG_HIDDEN void utils_close_pipe(int *src) { int i, ret; @@ -163,7 +168,7 @@ void utils_close_pipe(int *src) /* * Create a new string using two strings range. */ -__attribute__((visibility("hidden"))) +LTTNG_HIDDEN char *utils_strdupdelim(const char *begin, const char *end) { char *str; @@ -184,7 +189,7 @@ error: /* * Set CLOEXEC flag to the give file descriptor. */ -__attribute__((visibility("hidden"))) +LTTNG_HIDDEN int utils_set_fd_cloexec(int fd) { int ret; @@ -207,7 +212,7 @@ end: /* * Create pid file to the given path and filename. */ -__attribute__((visibility("hidden"))) +LTTNG_HIDDEN int utils_create_pid_file(pid_t pid, const char *filepath) { int ret; @@ -232,3 +237,160 @@ int utils_create_pid_file(pid_t pid, const char *filepath) error: return ret; } + +/* + * Recursively create directory using the given path and mode. + * + * On success, return 0 else a negative error code. + */ +LTTNG_HIDDEN +int utils_mkdir_recursive(const char *path, mode_t mode) +{ + char *p, tmp[PATH_MAX]; + struct stat statbuf; + size_t len; + int ret; + + assert(path); + + ret = snprintf(tmp, sizeof(tmp), "%s", path); + if (ret < 0) { + PERROR("snprintf mkdir"); + goto error; + } + + len = ret; + if (tmp[len - 1] == '/') { + tmp[len - 1] = 0; + } + + for (p = tmp + 1; *p; p++) { + if (*p == '/') { + *p = 0; + if (tmp[strlen(tmp) - 1] == '.' && + tmp[strlen(tmp) - 2] == '.' && + tmp[strlen(tmp) - 3] == '/') { + ERR("Using '/../' is not permitted in the trace path (%s)", + tmp); + ret = -1; + goto error; + } + ret = stat(tmp, &statbuf); + if (ret < 0) { + ret = mkdir(tmp, mode); + if (ret < 0) { + if (errno != EEXIST) { + PERROR("mkdir recursive"); + ret = -errno; + goto error; + } + } + } + *p = '/'; + } + } + + ret = mkdir(tmp, mode); + if (ret < 0) { + if (errno != EEXIST) { + PERROR("mkdir recursive last piece"); + ret = -errno; + } else { + ret = 0; + } + } + +error: + return ret; +} + +/* + * Create the stream tracefile on disk. + * + * Return 0 on success or else a negative value. + */ +LTTNG_HIDDEN +int utils_create_stream_file(char *path_name, char *file_name, uint64_t size, + uint64_t count, int uid, int gid) +{ + int ret, out_fd, flags, mode; + char full_path[PATH_MAX], *path_name_id = NULL, *path; + + assert(path_name); + assert(file_name); + + ret = snprintf(full_path, sizeof(full_path), "%s/%s", + path_name, file_name); + if (ret < 0) { + PERROR("snprintf create output file"); + goto error; + } + + /* + * If we split the trace in multiple files, we have to add the count at the + * end of the tracefile name + */ + if (size > 0) { + ret = asprintf(&path_name_id, "%s_%" PRIu64, full_path, count); + if (ret < 0) { + PERROR("Allocating path name ID"); + goto error; + } + path = path_name_id; + } else { + path = full_path; + } + + flags = O_WRONLY | O_CREAT | O_TRUNC; + /* Open with 660 mode */ + mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP; + + if (uid < 0 || gid < 0) { + out_fd = open(path, flags, mode); + } else { + out_fd = run_as_open(path, flags, mode, uid, gid); + } + if (out_fd < 0) { + PERROR("open stream path %s", path); + goto error_open; + } + ret = out_fd; + +error_open: + free(path_name_id); +error: + return ret; +} + +/* + * Change the output tracefile according to the given size and count The + * new_count pointer is set during this operation. + * + * From the consumer, the stream lock MUST be held before calling this function + * because we are modifying the stream status. + * + * Return 0 on success or else a negative value. + */ +LTTNG_HIDDEN +int utils_rotate_stream_file(char *path_name, char *file_name, uint64_t size, + uint64_t count, int uid, int gid, int out_fd, uint64_t *new_count) +{ + int ret; + + ret = close(out_fd); + if (ret < 0) { + PERROR("Closing tracefile"); + goto error; + } + + if (count > 0) { + *new_count = (*new_count + 1) % count; + } else { + (*new_count)++; + } + + return utils_create_stream_file(path_name, file_name, size, *new_count, + uid, gid); +error: + return ret; +}