summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFRIGN <dev@frign.de>2014-09-18 22:27:51 +0200
committersin <sin@2f30.org>2014-09-19 10:10:20 +0100
commitdd4665bfbd4d5255d3671a7a41afb5afdf179576 (patch)
tree6bf86a63f844ec81059a023c662ea7118ce6320e
parent12194aceff061d9fdb2c90cfeac9a9283569d5b0 (diff)
Change global in-fifos from O_RDWR to O_RDONLY
O_RDWR is a dirty hack to get around the issue of infinite EOFs while reading an in-FIFO. Instead, stop breaking POSIX and set the FIFOs to O_RDONLY. In case a read returns EOF (r == 0), we reopen the fd. Same will be applied to the friend-fifos (especially file_in), helping us get rid of strange timeouts and heuristics and rather solve the problem the POSIX-way. The only downside to this is that we are blind for writes to the in-FIFOs between catching read == 0 and close(), but this is not an issue. To make reopening as easy as possible, I added a dirfd to all slots. While at it, I changed the initial setup and removed the chdir() in favor of the POSIX-2008-compliant *at-functions. This lets us do stuff without having to use snprintf to build paths and is more bulletproof even in case the directory is renamed.
-rw-r--r--ratox.c61
1 files changed, 46 insertions, 15 deletions
diff --git a/ratox.c b/ratox.c
index 76c8b39..3c18649 100644
--- a/ratox.c
+++ b/ratox.c
@@ -49,6 +49,7 @@ struct slot {
const char *name;
void (*cb)(void *);
int outtype;
+ int dirfd;
int fd[NR_GFILES];
};
@@ -76,7 +77,7 @@ static struct slot gslots[] = {
};
static struct file gfiles[] = {
- { .type = FIFO, .name = "in", .flags = O_RDWR | O_NONBLOCK, },
+ { .type = FIFO, .name = "in", .flags = O_RDONLY | O_NONBLOCK, },
{ .type = OUT_F, .name = "out", .flags = O_WRONLY | O_TRUNC | O_CREAT },
{ .type = OUT_F, .name = "err", .flags = O_WRONLY | O_TRUNC | O_CREAT },
};
@@ -549,19 +550,25 @@ localinit(void)
perror("mkdir");
exit(EXIT_FAILURE);
}
- r = chdir(gslots[i].name);
+ d = opendir(gslots[i].name);
+ if (!d) {
+ perror("opendir");
+ exit(EXIT_FAILURE);
+ }
+ r = dirfd(d);
if (r < 0) {
- perror("chdir");
+ perror("dirfd");
exit(EXIT_FAILURE);
}
+ gslots[i].dirfd = r;
for (m = 0; m < LEN(gfiles); m++) {
if (gfiles[m].type == FIFO) {
- r = mkfifo(gfiles[m].name, 0644);
+ r = mkfifoat(gslots[i].dirfd, gfiles[m].name, 0644);
if (r < 0 && errno != EEXIST) {
perror("mkfifo");
exit(EXIT_FAILURE);
}
- r = open(gfiles[m].name, gfiles[m].flags, 0644);
+ r = openat(gslots[i].dirfd, gfiles[m].name, gfiles[m].flags, 0644);
if (r < 0) {
perror("open");
exit(EXIT_FAILURE);
@@ -569,33 +576,27 @@ localinit(void)
gslots[i].fd[m] = r;
} else if (gfiles[m].type == OUT_F) {
if (gslots[i].outtype == STATIC) {
- r = open(gfiles[m].name, gfiles[m].flags, 0644);
+ r = openat(gslots[i].dirfd, gfiles[m].name, gfiles[m].flags, 0644);
if (r < 0) {
perror("open");
exit(EXIT_FAILURE);
}
gslots[i].fd[m] = r;
} else if (gslots[i].outtype == FOLDER) {
- r = mkdir(gfiles[m].name, 0777);
+ r = mkdirat(gslots[i].dirfd, gfiles[m].name, 0777);
if (r < 0 && errno != EEXIST) {
perror("mkdir");
exit(EXIT_FAILURE);
}
- d = opendir(gfiles[m].name);
- if (!d) {
- perror("opendir");
- exit(EXIT_FAILURE);
- }
- r = dirfd(d);
+ r = openat(gslots[i].dirfd, gfiles[m].name, O_RDONLY | O_DIRECTORY);
if (r < 0) {
- perror("dirfd");
+ perror("openat");
exit(EXIT_FAILURE);
}
gslots[i].fd[m] = r;
}
}
}
- chdir("..");
}
/* Dump current name */
@@ -789,6 +790,16 @@ setname(void *data)
again:
r = read(gslots[NAME].fd[IN], name, sizeof(name) - 1);
+ if (r == 0) {
+ close(gslots[NAME].fd[IN]);
+ r = openat(gslots[NAME].dirfd, gfiles[IN].name, gfiles[IN].flags, 0644);
+ if (r < 0) {
+ perror("openat");
+ exit(EXIT_FAILURE);
+ }
+ gslots[NAME].fd[IN] = r;
+ return;
+ }
if (r < 0) {
if (errno == EINTR)
goto again;
@@ -815,6 +826,16 @@ setstatus(void *data)
again:
r = read(gslots[STATUS].fd[IN], status, sizeof(status) - 1);
+ if (r == 0) {
+ close(gslots[STATUS].fd[IN]);
+ r = openat(gslots[STATUS].dirfd, gfiles[IN].name, gfiles[IN].flags, 0644);
+ if (r < 0) {
+ perror("openat");
+ exit(EXIT_FAILURE);
+ }
+ gslots[STATUS].fd[IN] = r;
+ return;
+ }
if (r < 0) {
if (errno == EINTR)
goto again;
@@ -843,6 +864,16 @@ sendfriendreq(void *data)
again:
r = read(gslots[REQUEST].fd[IN], buf, sizeof(buf) - 1);
+ if (r == 0) {
+ close(gslots[REQUEST].fd[IN]);
+ r = openat(gslots[REQUEST].dirfd, gfiles[IN].name, gfiles[IN].flags, 0644);
+ if (r < 0) {
+ perror("openat");
+ exit(EXIT_FAILURE);
+ }
+ gslots[REQUEST].fd[IN] = r;
+ return;
+ }
if (r < 0) {
if (errno == EINTR)
goto again;