+ * Create lock file to the given path and filename.
+ * Returns the associated file descriptor, -1 on error.
+ */
+LTTNG_HIDDEN
+int utils_create_lock_file(const char *filepath)
+{
+ int ret;
+ int fd;
+
+ assert(filepath);
+
+ fd = open(filepath, O_CREAT,
+ O_WRONLY | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
+ if (fd < 0) {
+ PERROR("open lock file %s", filepath);
+ ret = -1;
+ goto error;
+ }
+
+ /*
+ * Attempt to lock the file. If this fails, there is
+ * already a process using the same lock file running
+ * and we should exit.
+ */
+ ret = flock(fd, LOCK_EX | LOCK_NB);
+ if (ret) {
+ ERR("Could not get lock file %s, another instance is running.",
+ filepath);
+ if (close(fd)) {
+ PERROR("close lock file");
+ }
+ fd = ret;
+ goto error;
+ }
+
+error:
+ return fd;
+}
+
+/*
+ * On some filesystems (e.g. nfs), mkdir will validate access rights before
+ * checking for the existence of the path element. This means that on a setup
+ * where "/home/" is a mounted NFS share, and running as an unpriviledged user,
+ * recursively creating a path of the form "/home/my_user/trace/" will fail with
+ * EACCES on mkdir("/home", ...).
+ *
+ * Performing a stat(...) on the path to check for existence allows us to
+ * work around this behaviour.
+ */
+static
+int mkdir_check_exists(const char *path, mode_t mode)
+{
+ int ret = 0;
+ struct stat st;
+
+ ret = stat(path, &st);
+ if (ret == 0) {
+ if (S_ISDIR(st.st_mode)) {
+ /* Directory exists, skip. */
+ goto end;
+ } else {
+ /* Exists, but is not a directory. */
+ errno = ENOTDIR;
+ ret = -1;
+ goto end;
+ }
+ }
+
+ /*
+ * Let mkdir handle other errors as the caller expects mkdir
+ * semantics.
+ */
+ ret = mkdir(path, mode);
+end:
+ return ret;
+}
+
+/*
+ * Create directory using the given path and mode.