close(fd);
}
-typedef void (*lockFn)(int fd, const char *fname);
+typedef void (*lockFn)(int fd, const char *fname, int dupfd);
-static void lock_fn_none(int fd _U_, const char *fname _U_)
+static void lock_fn_none(int fd _U_, const char *fname _U_, int dupfd _U_)
{
/* Do nothing */
}
-static void lock_fn_flock_sh(int fd, const char *fname)
+static void lock_fn_flock_sh(int fd, const char *fname, int dupfd)
{
if (flock(fd, LOCK_SH) < 0) {
int e = errno;
close(fd);
+ close(dupfd);
if (fname)
unlink(fname);
errno = e;
}
}
-static void lock_fn_flock_ex(int fd, const char *fname)
+static void lock_fn_flock_ex(int fd, const char *fname, int dupfd)
{
if (flock(fd, LOCK_EX) < 0) {
int e = errno;
close(fd);
+ close(dupfd);
if (fname)
unlink(fname);
errno = e;
}
}
-static void lock_fn_posix_r_(int fd, const char *fname)
+static void lock_fn_posix_r_(int fd, const char *fname, int dupfd)
{
struct flock r = {
.l_type = F_RDLCK,
if (fcntl(fd, F_SETLK, &r) < 0) {
int e = errno;
close(fd);
+ close(dupfd);
if (fname)
unlink(fname);
errno = e;
}
}
-static void lock_fn_posix__w(int fd, const char *fname)
+static void lock_fn_posix__w(int fd, const char *fname, int dupfd)
{
struct flock w = {
.l_type = F_WRLCK,
if (fcntl(fd, F_SETLK, &w) < 0) {
int e = errno;
close(fd);
+ close(dupfd);
if (fname)
unlink(fname);
errno = e;
}
}
-static void lock_fn_posix_rw(int fd, const char *fname)
+static void lock_fn_posix_rw(int fd, const char *fname, int dupfd)
{
struct flock r = {
.l_type = F_RDLCK,
if (fcntl(fd, F_SETLK, &r) < 0) {
int e = errno;
close(fd);
+ close(dupfd);
if (fname)
unlink(fname);
errno = e;
if (fcntl(fd, F_SETLK, &w) < 0) {
int e = errno;
close(fd);
+ close(dupfd);
if (fname)
unlink(fname);
errno = e;
}
}
-static void lock_fn_ofd_r_(int fd, const char *fname)
+static void lock_fn_ofd_r_(int fd, const char *fname, int dupfd)
{
struct flock r = {
.l_type = F_RDLCK,
if (fcntl(fd, F_OFD_SETLK, &r) < 0) {
int e = errno;
close(fd);
+ close(dupfd);
if (fname)
unlink(fname);
errno = e;
}
}
-static void lock_fn_ofd__w(int fd, const char *fname)
+static void lock_fn_ofd__w(int fd, const char *fname, int dupfd)
{
struct flock w = {
.l_type = F_WRLCK,
if (fcntl(fd, F_OFD_SETLK, &w) < 0) {
int e = errno;
close(fd);
+ close(dupfd);
if (fname)
unlink(fname);
errno = e;
}
}
-static void lock_fn_ofd_rw(int fd, const char *fname)
+static void lock_fn_ofd_rw(int fd, const char *fname, int dupfd)
{
struct flock r = {
.l_type = F_RDLCK,
if (fcntl(fd, F_OFD_SETLK, &r) < 0) {
int e = errno;
close(fd);
+ close(dupfd);
if (fname)
unlink(fname);
errno = e;
if (fcntl(fd, F_OFD_SETLK, &w) < 0) {
int e = errno;
close(fd);
+ close(dupfd);
if (fname)
unlink(fname);
errno = e;
}
}
-static void lock_fn_lease_w(int fd, const char *fname)
+static void lock_fn_lease_w(int fd, const char *fname, int dupfd)
{
if (fcntl(fd, F_SETLEASE, F_WRLCK) < 0) {
int e = errno;
close(fd);
+ close(dupfd);
if (fname)
unlink(fname);
errno = e;
const char *sLock = ARG_STRING(lock);
lockFn lock_fn;
+ struct arg dupfd = decode_arg("dupfd", factory->params, argc, argv);
+ int iDupfd = ARG_INTEGER(dupfd);
+
+ void *data = NULL;
+
if (iWrite_bytes < 0)
errx(EXIT_FAILURE, "write-bytes must be a positive number or zero.");
else
errx(EXIT_FAILURE, "unexpected value for lock parameter: %s", sLock);
+ free_arg(&dupfd);
free_arg(&lock);
free_arg(&readable);
free_arg(&write_bytes);
}
}
- lock_fn(fd, fname);
+ if (iDupfd >= 0) {
+ if (dup2(fd, iDupfd) < 0) {
+ int e = errno;
+ close(fd);
+ if (fname)
+ unlink(fname);
+ errno = e;
+ err(EXIT_FAILURE, "failed in dup2");
+ }
+ data = xmalloc(sizeof (iDupfd));
+ *((int *)data) = iDupfd;
+ }
+
+ lock_fn(fd, fname, iDupfd);
fdescs[0] = (struct fdesc){
.fd = fdescs[0].fd,
.data = fname,
};
- return NULL;
+ return data;
+}
+
+static void free_after_closing_duplicated_fd(const struct factory * factory _U_, void *data)
+{
+ if (data) {
+ int *fdp = data;
+ close(*fdp);
+ free (data);
+ }
}
static void *make_pipe(const struct factory *factory, struct fdesc fdescs[],
.N = 1,
.EX_N = 0,
.make = make_w_regular_file,
+ .free = free_after_closing_duplicated_fd,
.params = (struct parameter []) {
{
.name = "file",
.desc = "the way for file locking: [none]|flock-sh|flock-ex|posix-r-|posix--w|posix-rw|ofd-r-|ofd--w|ofd-rw|lease-w",
.defv.string = "none",
},
+ {
+ .name = "dupfd",
+ .type = PTYPE_INTEGER,
+ .desc = "the number for the fd duplicated from the original fd",
+ .defv.integer = -1,
+ },
PARAM_END
},
},