17dd7cddfSDavid du Colombier #include "sam.h" 27dd7cddfSDavid du Colombier 37dd7cddfSDavid du Colombier static Block *blist; 47dd7cddfSDavid du Colombier 57dd7cddfSDavid du Colombier static int 67dd7cddfSDavid du Colombier tempdisk(void) 77dd7cddfSDavid du Colombier { 87dd7cddfSDavid du Colombier char dir[DIRLEN]; 97dd7cddfSDavid du Colombier char buf[128]; 107dd7cddfSDavid du Colombier int i, fd; 117dd7cddfSDavid du Colombier 12*59cc4ca5SDavid du Colombier snprint(buf, sizeof buf, "/tmp/X%d.%.4ssam", getpid(), getuser()); 137dd7cddfSDavid du Colombier for(i='A'; i<='Z'; i++){ 147dd7cddfSDavid du Colombier buf[5] = i; 157dd7cddfSDavid du Colombier if(stat(buf, dir) == 0) 167dd7cddfSDavid du Colombier continue; 177dd7cddfSDavid du Colombier fd = create(buf, ORDWR|ORCLOSE|OCEXEC, 0600); 187dd7cddfSDavid du Colombier if(fd >= 0) 197dd7cddfSDavid du Colombier return fd; 207dd7cddfSDavid du Colombier } 217dd7cddfSDavid du Colombier return -1; 227dd7cddfSDavid du Colombier } 237dd7cddfSDavid du Colombier 247dd7cddfSDavid du Colombier Disk* 257dd7cddfSDavid du Colombier diskinit() 267dd7cddfSDavid du Colombier { 277dd7cddfSDavid du Colombier Disk *d; 287dd7cddfSDavid du Colombier 297dd7cddfSDavid du Colombier d = emalloc(sizeof(Disk)); 307dd7cddfSDavid du Colombier d->fd = tempdisk(); 317dd7cddfSDavid du Colombier if(d->fd < 0){ 327dd7cddfSDavid du Colombier fprint(2, "sam: can't create temp file: %r\n"); 337dd7cddfSDavid du Colombier exits("diskinit"); 347dd7cddfSDavid du Colombier } 357dd7cddfSDavid du Colombier return d; 367dd7cddfSDavid du Colombier } 377dd7cddfSDavid du Colombier 387dd7cddfSDavid du Colombier static 397dd7cddfSDavid du Colombier uint 407dd7cddfSDavid du Colombier ntosize(uint n, uint *ip) 417dd7cddfSDavid du Colombier { 427dd7cddfSDavid du Colombier uint size; 437dd7cddfSDavid du Colombier 447dd7cddfSDavid du Colombier if(n > Maxblock) 457dd7cddfSDavid du Colombier panic("internal error: ntosize"); 467dd7cddfSDavid du Colombier size = n; 477dd7cddfSDavid du Colombier if(size & (Blockincr-1)) 487dd7cddfSDavid du Colombier size += Blockincr - (size & (Blockincr-1)); 497dd7cddfSDavid du Colombier /* last bucket holds blocks of exactly Maxblock */ 507dd7cddfSDavid du Colombier if(ip) 517dd7cddfSDavid du Colombier *ip = size/Blockincr; 527dd7cddfSDavid du Colombier return size * sizeof(Rune); 537dd7cddfSDavid du Colombier } 547dd7cddfSDavid du Colombier 557dd7cddfSDavid du Colombier Block* 567dd7cddfSDavid du Colombier disknewblock(Disk *d, uint n) 577dd7cddfSDavid du Colombier { 587dd7cddfSDavid du Colombier uint i, j, size; 597dd7cddfSDavid du Colombier Block *b; 607dd7cddfSDavid du Colombier 617dd7cddfSDavid du Colombier size = ntosize(n, &i); 627dd7cddfSDavid du Colombier b = d->free[i]; 637dd7cddfSDavid du Colombier if(b) 647dd7cddfSDavid du Colombier d->free[i] = b->next; 657dd7cddfSDavid du Colombier else{ 667dd7cddfSDavid du Colombier /* allocate in chunks to reduce malloc overhead */ 677dd7cddfSDavid du Colombier if(blist == nil){ 687dd7cddfSDavid du Colombier blist = emalloc(100*sizeof(Block)); 697dd7cddfSDavid du Colombier for(j=0; j<100-1; j++) 707dd7cddfSDavid du Colombier blist[j].next = &blist[j+1]; 717dd7cddfSDavid du Colombier } 727dd7cddfSDavid du Colombier b = blist; 737dd7cddfSDavid du Colombier blist = b->next; 747dd7cddfSDavid du Colombier b->addr = d->addr; 757dd7cddfSDavid du Colombier d->addr += size; 767dd7cddfSDavid du Colombier } 777dd7cddfSDavid du Colombier b->n = n; 787dd7cddfSDavid du Colombier return b; 797dd7cddfSDavid du Colombier } 807dd7cddfSDavid du Colombier 817dd7cddfSDavid du Colombier void 827dd7cddfSDavid du Colombier diskrelease(Disk *d, Block *b) 837dd7cddfSDavid du Colombier { 847dd7cddfSDavid du Colombier uint i; 857dd7cddfSDavid du Colombier 867dd7cddfSDavid du Colombier ntosize(b->n, &i); 877dd7cddfSDavid du Colombier b->next = d->free[i]; 887dd7cddfSDavid du Colombier d->free[i] = b; 897dd7cddfSDavid du Colombier } 907dd7cddfSDavid du Colombier 917dd7cddfSDavid du Colombier void 927dd7cddfSDavid du Colombier diskwrite(Disk *d, Block **bp, Rune *r, uint n) 937dd7cddfSDavid du Colombier { 947dd7cddfSDavid du Colombier int size, nsize; 957dd7cddfSDavid du Colombier Block *b; 967dd7cddfSDavid du Colombier 977dd7cddfSDavid du Colombier b = *bp; 987dd7cddfSDavid du Colombier size = ntosize(b->n, nil); 997dd7cddfSDavid du Colombier nsize = ntosize(n, nil); 1007dd7cddfSDavid du Colombier if(size != nsize){ 1017dd7cddfSDavid du Colombier diskrelease(d, b); 1027dd7cddfSDavid du Colombier b = disknewblock(d, n); 1037dd7cddfSDavid du Colombier *bp = b; 1047dd7cddfSDavid du Colombier } 1057dd7cddfSDavid du Colombier if(seek(d->fd, b->addr, 0) < 0) 1067dd7cddfSDavid du Colombier panic("seek error in temp file"); 1077dd7cddfSDavid du Colombier if(write(d->fd, r, n*sizeof(Rune)) != n*sizeof(Rune)) 1087dd7cddfSDavid du Colombier panic("write error to temp file"); 1097dd7cddfSDavid du Colombier b->n = n; 1107dd7cddfSDavid du Colombier } 1117dd7cddfSDavid du Colombier 1127dd7cddfSDavid du Colombier void 1137dd7cddfSDavid du Colombier diskread(Disk *d, Block *b, Rune *r, uint n) 1147dd7cddfSDavid du Colombier { 1157dd7cddfSDavid du Colombier if(n > b->n) 1167dd7cddfSDavid du Colombier panic("internal error: diskread"); 1177dd7cddfSDavid du Colombier 1187dd7cddfSDavid du Colombier ntosize(b->n, nil); 1197dd7cddfSDavid du Colombier if(seek(d->fd, b->addr, 0) < 0) 1207dd7cddfSDavid du Colombier panic("seek error in temp file"); 1217dd7cddfSDavid du Colombier if(read(d->fd, r, n*sizeof(Rune)) != n*sizeof(Rune)) 1227dd7cddfSDavid du Colombier panic("read error from temp file"); 1237dd7cddfSDavid du Colombier } 124