+
+/*
+ * Create a new string using two strings range.
+ */
+__attribute__((visibility("hidden")))
+char *utils_strdupdelim(const char *begin, const char *end)
+{
+ char *str;
+
+ str = zmalloc(end - begin + 1);
+ if (str == NULL) {
+ PERROR("zmalloc strdupdelim");
+ goto error;
+ }
+
+ memcpy(str, begin, end - begin);
+ str[end - begin] = '\0';
+
+error:
+ return str;
+}
+
+/*
+ * Set CLOEXEC flag to the give file descriptor.
+ */
+__attribute__((visibility("hidden")))
+int utils_set_fd_cloexec(int fd)
+{
+ int ret;
+
+ if (fd < 0) {
+ ret = -EINVAL;
+ goto end;
+ }
+
+ ret = fcntl(fd, F_SETFD, FD_CLOEXEC);
+ if (ret < 0) {
+ PERROR("fcntl cloexec");
+ ret = -errno;
+ }
+
+end:
+ return ret;
+}
+
+/*
+ * Create pid file to the given path and filename.
+ */
+__attribute__((visibility("hidden")))
+int utils_create_pid_file(pid_t pid, const char *filepath)
+{
+ int ret;
+ FILE *fp;
+
+ assert(filepath);
+
+ fp = fopen(filepath, "w");
+ if (fp == NULL) {
+ PERROR("open pid file %s", filepath);
+ ret = -1;
+ goto error;
+ }
+
+ ret = fprintf(fp, "%d\n", pid);
+ if (ret < 0) {
+ PERROR("fprintf pid file");
+ }
+
+ fclose(fp);
+ DBG("Pid %d written in file %s", pid, filepath);
+error:
+ return ret;
+}
+
+/*
+ * Recursively create directory using the given path and mode.
+ *
+ * On success, return 0 else a negative error code.
+ */
+__attribute__((visibility("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;
+}