tChange global in-fifos from O_RDWR to O_RDONLY - ratox - FIFO based tox client
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) README
 (DIR) LICENSE
       ---
 (DIR) commit dd4665bfbd4d5255d3671a7a41afb5afdf179576
 (DIR) parent 12194aceff061d9fdb2c90cfeac9a9283569d5b0
 (HTM) 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
       tto 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
       tto 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:
         M ratox.c                             |      61 +++++++++++++++++++++++--------
       
       1 file changed, 46 insertions(+), 15 deletions(-)
       ---
 (DIR) diff --git a/ratox.c b/ratox.c
       t@@ -49,6 +49,7 @@ struct slot {
                const char *name;
                void (*cb)(void *);
                int outtype;
       +        int dirfd;
                int fd[NR_GFILES];
        };
        
       t@@ -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 },
        };
       t@@ -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);
       t@@ -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 */
       t@@ -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;
       t@@ -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;
       t@@ -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;