/* retrieve the OPEN group options and perform the open() call. returns the file descriptor or a negative value. Applies options of phases PREOPEN, OPEN, PASTOPEN, and FD */ int _xioopen_open(const char *path, int rw, struct opt *opts) { mode_t mode = 0666; flags_t flags = rw; bool flag; int fd; applyopts_named(path, opts, PH_PREOPEN); /* this only applies pure OPEN flags, not mixed OPEN/FCNTL options */ applyopts_flags(opts, GROUP_OPEN, &flags); /* we have to handle mixed OPEN/FCNTL flags specially */ if (retropt_bool(opts, OPT_O_APPEND, &flag) >= 0 && flag) flags |= O_APPEND; if (retropt_bool(opts, OPT_O_NONBLOCK, &flag) >= 0 && flag) flags |= O_NONBLOCK; #ifdef O_ASYNC if (retropt_bool(opts, OPT_O_ASYNC, &flag) >= 0 && flag) flags |= O_ASYNC; #endif if (retropt_bool(opts, OPT_O_TRUNC, &flag) >= 0 && flag) flags |= O_TRUNC; #ifdef O_BINARY if (retropt_bool(opts, OPT_O_BINARY, &flag) >= 0 && flag) flags |= O_BINARY; #endif #ifdef O_TEXT if (retropt_bool(opts, OPT_O_TEXT, &flag) >= 0 && flag) flags |= O_TEXT; #endif #ifdef O_NOINHERIT if (retropt_bool(opts, OPT_O_NOINHERIT, &flag) >= 0 && flag) flags |= O_NOINHERIT; #endif #ifdef O_NOATIME if (retropt_bool(opts, OPT_O_NOATIME, &flag) >= 0 && flag) flags |= O_NOATIME; #endif retropt_modet(opts, OPT_PERM, &mode); if ((fd = Open(path, flags, mode)) < 0) { Error4("open(\"%s\", 0%lo, 0%03o): %s", path, flags, mode, strerror(errno)); return STAT_RETRYLATER; } /*0 Info4("open(\"%s\", 0%o, 0%03o) -> %d", path, flags, mode, fd);*/ applyopts_named(path, opts, PH_PASTOPEN); #if 0 applyopts_named(path, opts, PH_FD); applyopts(fd, opts, PH_FD); applyopts_cloexec(fd, opts); #endif return fd; }
/* retrieve the mode option and perform the creat() call. returns the file descriptor or a negative value. */ static int _xioopen_creat(const char *path, int rw, struct opt *opts) { mode_t mode = 0666; int fd; retropt_modet(opts, OPT_PERM, &mode); if ((fd = Creat(path, mode)) < 0) { Error3("creat(\"%s\", 0%03o): %s", path, mode, strerror(errno)); return STAT_RETRYLATER; } return fd; }
/* open a named or unnamed pipe/fifo */ static int xioopen_fifo(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *fd, unsigned groups, int dummy1, int dummy2, int dummy3) { const char *pipename = argv[1]; int rw = (xioflags & XIO_ACCMODE); #if HAVE_STAT64 struct stat64 pipstat; #else struct stat pipstat; #endif /* !HAVE_STAT64 */ bool opt_unlink_early = false; bool opt_unlink_close = true; mode_t mode = 0666; int result; if (argc == 1) { return xioopen_fifo_unnamed(fd, fd->stream.opts); } if (argc != 2) { Error2("%s: wrong number of parameters (%d instead of 1)", argv[0], argc-1); } if (applyopts_single(&fd->stream, opts, PH_INIT) < 0) return -1; applyopts(-1, opts, PH_INIT); retropt_bool(opts, OPT_UNLINK_EARLY, &opt_unlink_early); applyopts_named(pipename, opts, PH_EARLY); /* umask! */ applyopts(-1, opts, PH_EARLY); if (opt_unlink_early) { if (Unlink(pipename) < 0) { if (errno == ENOENT) { Warn2("unlink(%s): %s", pipename, strerror(errno)); } else { Error2("unlink(%s): %s", pipename, strerror(errno)); return STAT_RETRYLATER; } } } retropt_bool(opts, OPT_UNLINK_CLOSE, &opt_unlink_close); retropt_modet(opts, OPT_PERM, &mode); if (applyopts_named(pipename, opts, PH_EARLY) < 0) { return STAT_RETRYLATER; } if (applyopts_named(pipename, opts, PH_PREOPEN) < 0) { return STAT_RETRYLATER; } if ( #if HAVE_STAT64 Stat64(pipename, &pipstat) < 0 #else Stat(pipename, &pipstat) < 0 #endif /* !HAVE_STAT64 */ ) { if (errno != ENOENT) { Error3("stat(\"%s\", %p): %s", pipename, &pipstat, strerror(errno)); } else { Debug1("xioopen_fifo(\"%s\"): does not exist, creating fifo", pipename); #if 0 result = Mknod(pipename, S_IFIFO|mode, 0); if (result < 0) { Error3("mknod(%s, %d, 0): %s", pipename, mode, strerror(errno)); return STAT_RETRYLATER; } #else result = Mkfifo(pipename, mode); if (result < 0) { Error3("mkfifo(%s, %d): %s", pipename, mode, strerror(errno)); return STAT_RETRYLATER; } #endif Notice2("created named pipe \"%s\" for %s", pipename, ddirection[rw]); applyopts_named(pipename, opts, PH_ALL); } if (opt_unlink_close) { if ((fd->stream.unlink_close = strdup(pipename)) == NULL) { Error1("strdup(\"%s\"): out of memory", pipename); } fd->stream.opt_unlink_close = true; } } else { /* exists */ Debug1("xioopen_fifo(\"%s\"): already exist, opening it", pipename); Notice3("opening %s \"%s\" for %s", filetypenames[(pipstat.st_mode&S_IFMT)>>12], pipename, ddirection[rw]); /*applyopts_early(pipename, opts);*/ applyopts_named(pipename, opts, PH_EARLY); } if ((result = _xioopen_open(pipename, rw, opts)) < 0) { return result; } fd->stream.fd = result; applyopts_named(pipename, opts, PH_FD); applyopts(fd->stream.fd, opts, PH_FD); applyopts_cloexec(fd->stream.fd, opts); return _xio_openlate(&fd->stream, opts); }