1 #include "all.h" 2 3 enum{ 4 MAXWREN = 7, 5 }; 6 7 #define WMAGIC "kfs wren device\n" 8 9 typedef struct Wren Wren; 10 11 struct Wren{ 12 QLock; 13 Device dev; 14 ulong size; 15 int fd; 16 }; 17 18 static Wren *wrens; 19 static int maxwren; 20 char *wrenfile; 21 int badmagic; 22 23 static Wren * 24 wren(Device dev) 25 { 26 int i; 27 28 for(i = 0; i < maxwren; i++) 29 if(devcmp(dev, wrens[i].dev) == 0) 30 return &wrens[i]; 31 panic("can't find wren for %D", dev); 32 return 0; 33 } 34 35 /* 36 * find out the length of a file 37 * given the mesg version of a stat buffer 38 * we call this because convM2D is different 39 * for the file system than in the os 40 */ 41 long 42 statlen(char *ap) 43 { 44 uchar *p; 45 46 p = (uchar*)ap; 47 p += 3*NAMELEN+5*4; 48 return p[0] | (p[1]<<8) | (p[2]<<16) | (p[3]<<24); 49 } 50 51 void 52 wreninit(Device dev) 53 { 54 char buf[8*1024], d[DIRREC]; 55 Wren *w; 56 int fd, i; 57 58 if(wrens == 0) 59 wrens = ialloc(MAXWREN * sizeof *wrens); 60 w = &wrens[maxwren]; 61 fd = open(wrenfile, ORDWR); 62 if(fd < 0) 63 panic("can't open %s", wrenfile); 64 if(fstat(fd, d) < 0) 65 panic("can't stat %s\n", wrenfile); 66 seek(fd, 0, 0); 67 i = read(fd, buf, sizeof buf); 68 if(i < sizeof buf) 69 panic("can't read %s", wrenfile); 70 badmagic = 0; 71 RBUFSIZE = 1024; 72 if(strncmp(buf+256, WMAGIC, strlen(WMAGIC)) == 0){ 73 RBUFSIZE = atol(buf+256+strlen(WMAGIC)); 74 if(RBUFSIZE % 512){ 75 fprint(2, "kfs: bad buffersize(%d): assuming 1k blocks\n", RBUFSIZE); 76 RBUFSIZE = 1024; 77 } 78 }else 79 badmagic = 1; 80 w->dev = dev; 81 w->size = statlen(d); 82 w->fd = fd; 83 maxwren++; 84 } 85 86 void 87 wrenream(Device dev) 88 { 89 Wren *w; 90 char buf[8*1024]; 91 int fd, i; 92 93 if(RBUFSIZE % 512) 94 panic("kfs: bad buffersize(%d): restart a multiple of 512\n", RBUFSIZE); 95 print("kfs: reaming the file system using %d byte blocks\n", RBUFSIZE); 96 w = wren(dev); 97 fd = w->fd; 98 memset(buf, 0, sizeof buf); 99 sprint(buf+256, "%s%d\n", WMAGIC, RBUFSIZE); 100 qlock(w); 101 i = seek(fd, 0, 0) < 0 || write(fd, buf, RBUFSIZE) != RBUFSIZE; 102 qunlock(w); 103 if(i < 0) 104 panic("can't ream disk"); 105 } 106 107 int 108 wrentag(char *p, int tag, long qpath) 109 { 110 Tag *t; 111 112 t = (Tag*)(p+BUFSIZE); 113 return t->tag != tag || (qpath&~QPDIR) != t->path; 114 } 115 116 int 117 wrencheck(Device dev) 118 { 119 char buf[8*1024]; 120 121 if(badmagic) 122 return 1; 123 if(RBUFSIZE > sizeof buf) 124 panic("bufsize too big"); 125 if(wrenread(dev, wrensuper(dev), buf) || wrentag(buf, Tsuper, QPSUPER) 126 || wrenread(dev, wrenroot(dev), buf) || wrentag(buf, Tdir, QPROOT)) 127 return 1; 128 if(((Dentry *)buf)[0].mode & DALLOC) 129 return 0; 130 return 1; 131 } 132 133 long 134 wrensize(Device dev) 135 { 136 return wren(dev)->size / RBUFSIZE; 137 } 138 139 long 140 wrensuper(Device dev) 141 { 142 USED(dev); 143 return 1; 144 } 145 146 long 147 wrenroot(Device dev) 148 { 149 USED(dev); 150 return 2; 151 } 152 153 int 154 wrenread(Device dev, long addr, void *b) 155 { 156 Wren *w; 157 int fd, i; 158 159 w = wren(dev); 160 fd = w->fd; 161 qlock(w); 162 i = seek(fd, addr*RBUFSIZE, 0) < 0 || read(fd, b, RBUFSIZE) != RBUFSIZE; 163 qunlock(w); 164 return i; 165 } 166 167 int 168 wrenwrite(Device dev, long addr, void *b) 169 { 170 Wren *w; 171 int fd, i; 172 173 w = wren(dev); 174 fd = w->fd; 175 qlock(w); 176 i = seek(fd, addr*RBUFSIZE, 0) < 0 || write(fd, b, RBUFSIZE) != RBUFSIZE; 177 qunlock(w); 178 return i; 179 } 180