Blob
- Date:
- Message:
- acme: check file content before declaring file "modified since last read" Bad remote file systems can change mtime unexpectedly, and then there is the problem that git rebase and similar operations like to change the files and then change them back, modifying the mtimes but not the content. Avoid spurious Put errors on both of those by checking file content. (False positive "modified since last read" make the real ones difficult to notice.)
- Actions:
- History | Blame | Raw File
1 #include <u.h>2 #include <libc.h>3 #include <draw.h>4 #include <thread.h>5 #include <cursor.h>6 #include <mouse.h>7 #include <keyboard.h>8 #include <frame.h>9 #include <fcall.h>10 #include <plumb.h>11 #include <libsec.h>12 #include "dat.h"13 #include "fns.h"15 static Block *blist;17 int18 tempfile(void)19 {20 char buf[128];21 int i, fd;23 snprint(buf, sizeof buf, "/tmp/X%d.%.4sacme", getpid(), getuser());24 for(i='A'; i<='Z'; i++){25 buf[5] = i;26 if(access(buf, AEXIST) == 0)27 continue;28 fd = create(buf, ORDWR|ORCLOSE|OCEXEC, 0600);29 if(fd >= 0)30 return fd;31 }32 return -1;33 }35 Disk*36 diskinit()37 {38 Disk *d;40 d = emalloc(sizeof(Disk));41 d->fd = tempfile();42 if(d->fd < 0){43 fprint(2, "acme: can't create temp file: %r\n");44 threadexitsall("diskinit");45 }46 return d;47 }49 static50 uint51 ntosize(uint n, uint *ip)52 {53 uint size;55 if(n > Maxblock)56 error("internal error: ntosize");57 size = n;58 if(size & (Blockincr-1))59 size += Blockincr - (size & (Blockincr-1));60 /* last bucket holds blocks of exactly Maxblock */61 if(ip)62 *ip = size/Blockincr;63 return size * sizeof(Rune);64 }66 Block*67 disknewblock(Disk *d, uint n)68 {69 uint i, j, size;70 Block *b;72 size = ntosize(n, &i);73 b = d->free[i];74 if(b)75 d->free[i] = b->u.next;76 else{77 /* allocate in chunks to reduce malloc overhead */78 if(blist == nil){79 blist = emalloc(100*sizeof(Block));80 for(j=0; j<100-1; j++)81 blist[j].u.next = &blist[j+1];82 }83 b = blist;84 blist = b->u.next;85 b->addr = d->addr;86 if(d->addr+size < d->addr){87 error("temp file overflow");88 }89 d->addr += size;90 }91 b->u.n = n;92 return b;93 }95 void96 diskrelease(Disk *d, Block *b)97 {98 uint i;100 ntosize(b->u.n, &i);101 b->u.next = d->free[i];102 d->free[i] = b;103 }105 void106 diskwrite(Disk *d, Block **bp, Rune *r, uint n)107 {108 int size, nsize;109 Block *b;111 b = *bp;112 size = ntosize(b->u.n, nil);113 nsize = ntosize(n, nil);114 if(size != nsize){115 diskrelease(d, b);116 b = disknewblock(d, n);117 *bp = b;118 }119 if(pwrite(d->fd, r, n*sizeof(Rune), b->addr) != n*sizeof(Rune))120 error("write error to temp file");121 b->u.n = n;122 }124 void125 diskread(Disk *d, Block *b, Rune *r, uint n)126 {127 if(n > b->u.n)128 error("internal error: diskread");130 ntosize(b->u.n, nil);131 if(pread(d->fd, r, n*sizeof(Rune), b->addr) != n*sizeof(Rune))132 error("read error from temp file");133 }