URI:
       tacme: use buffered i/o to write file - plan9port - [fork] Plan 9 from user space
  HTML git clone git://src.adamsgaard.dk/plan9port
   DIR Log
   DIR Files
   DIR Refs
   DIR README
   DIR LICENSE
       ---
   DIR commit 1d2c3c3945a229f896640b615b84f3d9a78e8b5a
   DIR parent d213189122bb3cd509cfe706240ffea528fee5f2
  HTML Author: Russ Cox <rsc@swtch.com>
       Date:   Sat, 19 Apr 2014 10:09:22 -0400
       
       acme: use buffered i/o to write file
       
       Bakul Shah has observed corrupted files being written
       when acme writes over osxfuse to sshfs to a remote file system.
       In one example we examined, acme is writing an 0xf03-byte
       file in two system calls, first an 0x806-byte write and then a 0x6fd-byte
       write. (0x806 is BUFSIZE/sizeof(Rune); this file has no multibyte UTF-8.)
       
       What actually ends up happening is that an 0x806-byte file is written:
       
               0x000-0x6fd contains what should be 0x806-0xf03
               0x6fd-0x7fa contains zeros
               0x7fa-0x806 contains what should be 0x7fa-0x806 (correct!)
       
       The theory is that fuse or sshfs or perhaps the remote file server is
       mishandling the unaligned writes. acme does not seem to be at fault.
       
       Using bio here will make the writes align to 8K boundaries,
       avoiding the bugs in whatever underlying piece is broken.
       
       TBR=r
       https://codereview.appspot.com/89550043
       
       Diffstat:
         M src/cmd/acme/exec.c                 |      17 ++++++++++++++++-
       
       1 file changed, 16 insertions(+), 1 deletion(-)
       ---
   DIR diff --git a/src/cmd/acme/exec.c b/src/cmd/acme/exec.c
       t@@ -1,5 +1,6 @@
        #include <u.h>
        #include <libc.h>
       +#include <bio.h>
        #include <draw.h>
        #include <thread.h>
        #include <cursor.h>
       t@@ -633,6 +634,7 @@ putfile(File *f, int q0, int q1, Rune *namer, int nname)
        {
                uint n, m;
                Rune *r;
       +        Biobuf *b;
                char *s, *name;
                int i, fd, q;
                Dir *d, *d1;
       t@@ -660,6 +662,8 @@ putfile(File *f, int q0, int q1, Rune *namer, int nname)
                        warning(nil, "can't create file %s: %r\n", name);
                        goto Rescue1;
                }
       +        b = emalloc(sizeof *b);
       +        Binit(b, fd, OWRITE);
                r = fbufalloc();
                s = fbufalloc();
                free(d);
       t@@ -676,11 +680,18 @@ putfile(File *f, int q0, int q1, Rune *namer, int nname)
                                n = BUFSIZE/UTFmax;
                        bufread(&f->b, q, r, n);
                        m = snprint(s, BUFSIZE+1, "%.*S", n, r);
       -                if(write(fd, s, m) != m){
       +                if(Bwrite(b, s, m) != m){
                                warning(nil, "can't write file %s: %r\n", name);
                                goto Rescue2;
                        }
                }
       +        if(Bflush(b) < 0) {
       +                warning(nil, "can't write file %s: %r\n", name);
       +                goto Rescue2;
       +        }
       +        Bterm(b);
       +        free(b);
       +        b = nil;
                if(runeeq(namer, nname, f->name, f->nname)){
                        if(q0!=0 || q1!=f->b.nc){
                                f->mod = TRUE;
       t@@ -727,6 +738,10 @@ putfile(File *f, int q0, int q1, Rune *namer, int nname)
                return;
        
            Rescue2:
       +        if(b != nil) {
       +                Bterm(b);
       +                free(b);
       +        }
                fbuffree(s);
                fbuffree(r);
                close(fd);