ratox

FIFO based tox client
git clone git://git.2f30.org/ratox
Log | Files | Refs | README | LICENSE

commit dd4665bfbd4d5255d3671a7a41afb5afdf179576
parent 12194aceff061d9fdb2c90cfeac9a9283569d5b0
Author: FRIGN <dev@frign.de>
Date:   Thu, 18 Sep 2014 22:27:51 +0200

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.

Diffstat:
Mratox.c | 61++++++++++++++++++++++++++++++++++++++++++++++---------------
1 file changed, 46 insertions(+), 15 deletions(-)

diff --git 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;