error:
free(resolved_path);
free(cut_path);
+ free(try_path);
+ if (try_path_prev != try_path) {
+ free(try_path_prev);
+ }
return NULL;
}
S_IRGRP | S_IWGRP);
if (fd < 0) {
PERROR("open lock file %s", filepath);
- ret = -1;
+ fd = -1;
goto error;
}
strncpy(path, path_name_suffix, PATH_MAX - 1);
path[PATH_MAX - 1] = '\0';
} else {
- strncpy(path, full_path, PATH_MAX - 1);
+ ret = lttng_strncpy(path, full_path, PATH_MAX);
+ if (ret) {
+ ERR("Failed to copy stream file name");
+ goto error_free_suffix;
+ }
}
path[PATH_MAX - 1] = '\0';
ret = 0;
goto error;
}
- flags = O_WRONLY | O_CREAT | O_TRUNC;
+ /*
+ * With the session rotation feature on the relay, we might need to seek
+ * and truncate a tracefile, so we need read and write access.
+ */
+ flags = O_RDWR | O_CREAT | O_TRUNC;
/* Open with 660 mode */
mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP;
PERROR("Closing tracefile");
goto error;
}
+ *stream_fd = -1;
if (count > 0) {
/*
return ret;
}
+/**
+ * Parse a string that represents a time in human readable format. It
+ * supports decimal integers suffixed by 's', 'u', 'm', 'us', and 'ms'.
+ *
+ * The suffix multiply the integer by:
+ * 'u'/'us': 1
+ * 'm'/'ms': 1000
+ * 's': 1000000
+ *
+ * Note that unit-less numbers are assumed to be microseconds.
+ *
+ * @param str The string to parse, assumed to be NULL-terminated.
+ * @param time_us Pointer to a uint64_t that will be filled with the
+ * resulting time in microseconds.
+ *
+ * @return 0 on success, -1 on failure.
+ */
+LTTNG_HIDDEN
+int utils_parse_time_suffix(char const * const str, uint64_t * const time_us)
+{
+ int ret;
+ uint64_t base_time;
+ long multiplier = 1;
+ const char *str_end;
+ char *num_end;
+
+ if (!str) {
+ DBG("utils_parse_time_suffix: received a NULL string.");
+ ret = -1;
+ goto end;
+ }
+
+ /* strtoull will accept a negative number, but we don't want to. */
+ if (strchr(str, '-') != NULL) {
+ DBG("utils_parse_time_suffix: invalid time string, should not contain '-'.");
+ ret = -1;
+ goto end;
+ }
+
+ /* str_end will point to the \0 */
+ str_end = str + strlen(str);
+ errno = 0;
+ base_time = strtoull(str, &num_end, 10);
+ if (errno != 0) {
+ PERROR("utils_parse_time_suffix strtoull on string \"%s\"", str);
+ ret = -1;
+ goto end;
+ }
+
+ if (num_end == str) {
+ /* strtoull parsed nothing, not good. */
+ DBG("utils_parse_time_suffix: strtoull had nothing good to parse.");
+ ret = -1;
+ goto end;
+ }
+
+ /* Check if a prefix is present. */
+ switch (*num_end) {
+ case 'u':
+ multiplier = 1;
+ /* Skip another letter in the 'us' case. */
+ num_end += (*(num_end + 1) == 's') ? 2 : 1;
+ break;
+ case 'm':
+ multiplier = 1000;
+ /* Skip another letter in the 'ms' case. */
+ num_end += (*(num_end + 1) == 's') ? 2 : 1;
+ break;
+ case 's':
+ multiplier = 1000000;
+ num_end++;
+ break;
+ case '\0':
+ break;
+ default:
+ DBG("utils_parse_time_suffix: invalid suffix.");
+ ret = -1;
+ goto end;
+ }
+
+ /* Check for garbage after the valid input. */
+ if (num_end != str_end) {
+ DBG("utils_parse_time_suffix: Garbage after time string.");
+ ret = -1;
+ goto end;
+ }
+
+ *time_us = base_time * multiplier;
+
+ /* Check for overflow */
+ if ((*time_us / multiplier) != base_time) {
+ DBG("utils_parse_time_suffix: oops, overflow detected.");
+ ret = -1;
+ goto end;
+ }
+
+ ret = 0;
+end:
+ return ret;
+}
+
/*
* fls: returns the position of the most significant bit.
* Returns 0 if no bit is set, else returns the position of the most
#define HAS_FLS_U32
#endif
+#if defined(__x86_64)
+static inline
+unsigned int fls_u64(uint64_t x)
+{
+ long r;
+
+ asm("bsrq %1,%0\n\t"
+ "jnz 1f\n\t"
+ "movq $-1,%0\n\t"
+ "1:\n\t"
+ : "=r" (r) : "rm" (x));
+ return r + 1;
+}
+#define HAS_FLS_U64
+#endif
+
+#ifndef HAS_FLS_U64
+static __attribute__((unused))
+unsigned int fls_u64(uint64_t x)
+{
+ unsigned int r = 64;
+
+ if (!x)
+ return 0;
+
+ if (!(x & 0xFFFFFFFF00000000ULL)) {
+ x <<= 32;
+ r -= 32;
+ }
+ if (!(x & 0xFFFF000000000000ULL)) {
+ x <<= 16;
+ r -= 16;
+ }
+ if (!(x & 0xFF00000000000000ULL)) {
+ x <<= 8;
+ r -= 8;
+ }
+ if (!(x & 0xF000000000000000ULL)) {
+ x <<= 4;
+ r -= 4;
+ }
+ if (!(x & 0xC000000000000000ULL)) {
+ x <<= 2;
+ r -= 2;
+ }
+ if (!(x & 0x8000000000000000ULL)) {
+ x <<= 1;
+ r -= 1;
+ }
+ return r;
+}
+#endif
+
#ifndef HAS_FLS_U32
static __attribute__((unused)) unsigned int fls_u32(uint32_t x)
{
return fls_u32(x - 1);
}
+/*
+ * Return the minimum order for which x <= (1UL << order).
+ * Return -1 if x is 0.
+ */
+LTTNG_HIDDEN
+int utils_get_count_order_u64(uint64_t x)
+{
+ if (!x) {
+ return -1;
+ }
+
+ return fls_u64(x - 1);
+}
+
/**
* Obtain the value of LTTNG_HOME environment variable, if exists.
* Otherwise returns the value of HOME.
return home_dir;
}
-/*
- * Obtain the value of LTTNG_KMOD_PROBES environment variable, if exists.
- * Otherwise returns NULL.
- */
-LTTNG_HIDDEN
-char *utils_get_kmod_probes_list(void)
-{
- return lttng_secure_getenv(DEFAULT_LTTNG_KMOD_PROBES);
-}
-
-/*
- * Obtain the value of LTTNG_EXTRA_KMOD_PROBES environment variable, if
- * exists. Otherwise returns NULL.
- */
-LTTNG_HIDDEN
-char *utils_get_extra_kmod_probes_list(void)
-{
- return lttng_secure_getenv(DEFAULT_LTTNG_EXTRA_KMOD_PROBES);
-}
-
/*
* With the given format, fill dst with the time of len maximum siz.
*
int utils_truncate_stream_file(int fd, off_t length)
{
int ret;
+ off_t lseek_ret;
ret = ftruncate(fd, length);
if (ret < 0) {
PERROR("ftruncate");
goto end;
}
- ret = lseek(fd, length, SEEK_SET);
- if (ret < 0) {
+ lseek_ret = lseek(fd, length, SEEK_SET);
+ if (lseek_ret < 0) {
PERROR("lseek");
+ ret = -1;
+ goto end;
+ }
+end:
+ return ret;
+}
+
+static const char *get_man_bin_path(void)
+{
+ char *env_man_path = lttng_secure_getenv(DEFAULT_MAN_BIN_PATH_ENV);
+
+ if (env_man_path) {
+ return env_man_path;
+ }
+
+ return DEFAULT_MAN_BIN_PATH;
+}
+
+LTTNG_HIDDEN
+int utils_show_help(int section, const char *page_name,
+ const char *help_msg)
+{
+ char section_string[8];
+ const char *man_bin_path = get_man_bin_path();
+ int ret = 0;
+
+ if (help_msg) {
+ printf("%s", help_msg);
goto end;
}
+ /* Section integer -> section string */
+ ret = sprintf(section_string, "%d", section);
+ assert(ret > 0 && ret < 8);
+
+ /*
+ * Execute man pager.
+ *
+ * We provide -M to man here because LTTng-tools can
+ * be installed outside /usr, in which case its man pages are
+ * not located in the default /usr/share/man directory.
+ */
+ ret = execlp(man_bin_path, "man", "-M", MANPATH,
+ section_string, page_name, NULL);
+
end:
return ret;
}