diff options
author | FRIGN <dev@frign.de> | 2014-09-18 22:27:51 +0200 |
---|---|---|
committer | sin <sin@2f30.org> | 2014-09-19 10:10:20 +0100 |
commit | dd4665bfbd4d5255d3671a7a41afb5afdf179576 (patch) | |
tree | 6bf86a63f844ec81059a023c662ea7118ce6320e /ratox.c | |
parent | 12194aceff061d9fdb2c90cfeac9a9283569d5b0 (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.
Diffstat (limited to 'ratox.c')
-rw-r--r-- | ratox.c | 61 |
1 files changed, 46 insertions, 15 deletions
@@ -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; |