+
+static int fifo_address_create(
+ const char *path,
+ mode_t directory_mode,
+ mode_t socket_mode,
+ int *_fd) {
+
+ int fd = -1, r = 0;
+ struct stat st;
+ mode_t old_mask;
+
+ assert(path);
+ assert(_fd);
+
+ mkdir_parents(path, directory_mode);
+
+ if ((r = label_fifofile_set(path)) < 0)
+ goto fail;
+
+ /* Enforce the right access mode for the fifo */
+ old_mask = umask(~ socket_mode);
+
+ /* Include the original umask in our mask */
+ umask(~socket_mode | old_mask);
+
+ r = mkfifo(path, socket_mode);
+ umask(old_mask);
+
+ if (r < 0) {
+ r = -errno;
+ goto fail;
+ }
+
+ if ((fd = open(path, O_RDWR|O_CLOEXEC|O_NOCTTY|O_NONBLOCK|O_NOFOLLOW)) < 0) {
+ r = -errno;
+ goto fail;
+ }
+
+ label_file_clear();
+
+ if (fstat(fd, &st) < 0) {
+ r = -errno;
+ goto fail;
+ }
+
+ if (!S_ISFIFO(st.st_mode) ||
+ (st.st_mode & 0777) != (socket_mode & ~old_mask) ||
+ st.st_uid != getuid() ||
+ st.st_gid != getgid()) {
+
+ r = -EEXIST;
+ goto fail;
+ }
+
+ *_fd = fd;
+ return 0;
+
+fail:
+ label_file_clear();
+
+ if (fd >= 0)
+ close_nointr_nofail(fd);
+
+ return r;
+}
+