+ ret = snprintf(out_stream_path, stream_path_len, "%s%s%s%s%s",
+ path_name, path_separator, file_name, count_str,
+ suffix);
+ if (ret < 0 || ret >= stream_path_len) {
+ ERR("Truncation occurred while formatting stream path");
+ ret = -1;
+ } else {
+ ret = 0;
+ }
+ return ret;
+}
+
+/**
+ * Parse a string that represents a size in human readable format. It
+ * supports decimal integers suffixed by 'k', 'K', 'M' or 'G'.
+ *
+ * The suffix multiply the integer by:
+ * 'k': 1024
+ * 'M': 1024^2
+ * 'G': 1024^3
+ *
+ * @param str The string to parse.
+ * @param size Pointer to a uint64_t that will be filled with the
+ * resulting size.
+ *
+ * @return 0 on success, -1 on failure.
+ */
+LTTNG_HIDDEN
+int utils_parse_size_suffix(const char * const str, uint64_t * const size)
+{
+ int ret;
+ uint64_t base_size;
+ long shift = 0;
+ const char *str_end;
+ char *num_end;
+
+ if (!str) {
+ DBG("utils_parse_size_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_size_suffix: invalid size string, should not contain '-'.");
+ ret = -1;
+ goto end;
+ }
+
+ /* str_end will point to the \0 */
+ str_end = str + strlen(str);
+ errno = 0;
+ base_size = strtoull(str, &num_end, 0);
+ if (errno != 0) {
+ PERROR("utils_parse_size_suffix strtoull");
+ ret = -1;
+ goto end;
+ }
+
+ if (num_end == str) {
+ /* strtoull parsed nothing, not good. */
+ DBG("utils_parse_size_suffix: strtoull had nothing good to parse.");
+ ret = -1;
+ goto end;
+ }
+
+ /* Check if a prefix is present. */
+ switch (*num_end) {
+ case 'G':
+ shift = GIBI_LOG2;
+ num_end++;
+ break;
+ case 'M': /* */
+ shift = MEBI_LOG2;
+ num_end++;
+ break;
+ case 'K':
+ case 'k':
+ shift = KIBI_LOG2;
+ num_end++;
+ break;
+ case '\0':
+ break;
+ default:
+ DBG("utils_parse_size_suffix: invalid suffix.");
+ ret = -1;
+ goto end;
+ }
+
+ /* Check for garbage after the valid input. */
+ if (num_end != str_end) {
+ DBG("utils_parse_size_suffix: Garbage after size string.");
+ ret = -1;
+ goto end;
+ }
+
+ *size = base_size << shift;
+
+ /* Check for overflow */
+ if ((*size >> shift) != base_size) {
+ DBG("utils_parse_size_suffix: oops, overflow detected.");
+ ret = -1;
+ goto end;
+ }
+
+ ret = 0;
+end:
+ return ret;
+}
+
+/**
+ * Parse a string that represents a time in human readable format. It
+ * supports decimal integers suffixed by:
+ * "us" for microsecond,
+ * "ms" for millisecond,
+ * "s" for second,
+ * "m" for minute,
+ * "h" for hour
+ *
+ * The suffix multiply the integer by:
+ * "us" : 1
+ * "ms" : 1000
+ * "s" : 1000000
+ * "m" : 60000000
+ * "h" : 3600000000
+ *
+ * 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;
+ uint64_t 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':
+ /*
+ * Microsecond (us)
+ *
+ * Skip the "us" if the string matches the "us" suffix,
+ * otherwise let the check for the end of the string handle
+ * the error reporting.
+ */
+ if (*(num_end + 1) == 's') {
+ num_end += 2;
+ }
+ break;
+ case 'm':
+ if (*(num_end + 1) == 's') {
+ /* Millisecond (ms) */
+ multiplier = USEC_PER_MSEC;
+ /* Skip the 's' */
+ num_end++;