19a747e4fSDavid du Colombier #include <u.h> 29a747e4fSDavid du Colombier #include <libc.h> 39a747e4fSDavid du Colombier #include <authsrv.h> 49a747e4fSDavid du Colombier 59a747e4fSDavid du Colombier static long finddosfile(int, char*); 69a747e4fSDavid du Colombier 79a747e4fSDavid du Colombier static int 89a747e4fSDavid du Colombier check(void *x, int len, uchar sum, char *msg) 99a747e4fSDavid du Colombier { 109a747e4fSDavid du Colombier if(nvcsum(x, len) == sum) 119a747e4fSDavid du Colombier return 0; 129a747e4fSDavid du Colombier memset(x, 0, len); 139a747e4fSDavid du Colombier fprint(2, "%s\n", msg); 149a747e4fSDavid du Colombier return 1; 159a747e4fSDavid du Colombier } 169a747e4fSDavid du Colombier 179a747e4fSDavid du Colombier /* 189a747e4fSDavid du Colombier * get key info out of nvram. since there isn't room in the PC's nvram use 199a747e4fSDavid du Colombier * a disk partition there. 209a747e4fSDavid du Colombier */ 219a747e4fSDavid du Colombier static struct { 229a747e4fSDavid du Colombier char *cputype; 239a747e4fSDavid du Colombier char *file; 249a747e4fSDavid du Colombier int off; 259a747e4fSDavid du Colombier int len; 269a747e4fSDavid du Colombier } nvtab[] = { 279a747e4fSDavid du Colombier "sparc", "#r/nvram", 1024+850, sizeof(Nvrsafe), 289a747e4fSDavid du Colombier "pc", "#S/sdC0/nvram", 0, sizeof(Nvrsafe), 299a747e4fSDavid du Colombier "pc", "#S/sdC0/9fat", -1, sizeof(Nvrsafe), 30dc5a79c1SDavid du Colombier "pc", "#S/sdC1/nvram", 0, sizeof(Nvrsafe), 31dc5a79c1SDavid du Colombier "pc", "#S/sdC1/9fat", -1, sizeof(Nvrsafe), 3222a0222bSDavid du Colombier "pc", "#S/sdD0/nvram", 0, sizeof(Nvrsafe), 3322a0222bSDavid du Colombier "pc", "#S/sdD0/9fat", -1, sizeof(Nvrsafe), 34*0aa8dc3cSDavid du Colombier "pc", "#S/sdE0/nvram", 0, sizeof(Nvrsafe), 35*0aa8dc3cSDavid du Colombier "pc", "#S/sdE0/9fat", -1, sizeof(Nvrsafe), 36*0aa8dc3cSDavid du Colombier "pc", "#S/sdF0/nvram", 0, sizeof(Nvrsafe), 37*0aa8dc3cSDavid du Colombier "pc", "#S/sdF0/9fat", -1, sizeof(Nvrsafe), 389a747e4fSDavid du Colombier "pc", "#S/sd00/nvram", 0, sizeof(Nvrsafe), 399a747e4fSDavid du Colombier "pc", "#S/sd00/9fat", -1, sizeof(Nvrsafe), 40d3c05884SDavid du Colombier "pc", "#S/sd01/nvram", 0, sizeof(Nvrsafe), 41d3c05884SDavid du Colombier "pc", "#S/sd01/9fat", -1, sizeof(Nvrsafe), 429a747e4fSDavid du Colombier "pc", "#f/fd0disk", -1, 512, /* 512: #f requires whole sector reads */ 439a747e4fSDavid du Colombier "pc", "#f/fd1disk", -1, 512, 449a747e4fSDavid du Colombier "mips", "#r/nvram", 1024+900, sizeof(Nvrsafe), 45dc5a79c1SDavid du Colombier "power", "#F/flash/flash0", 0x440000, sizeof(Nvrsafe), 469a747e4fSDavid du Colombier "power", "#r/nvram", 4352, sizeof(Nvrsafe), /* OK for MTX-604e */ 472cca75a1SDavid du Colombier "power", "/nvram", 0, sizeof(Nvrsafe), /* OK for Ucu */ 489a747e4fSDavid du Colombier "debug", "/tmp/nvram", 0, sizeof(Nvrsafe), 499a747e4fSDavid du Colombier }; 509a747e4fSDavid du Colombier 519a747e4fSDavid du Colombier static char* 529a747e4fSDavid du Colombier readcons(char *prompt, char *def, int raw, char *buf, int nbuf) 539a747e4fSDavid du Colombier { 549a747e4fSDavid du Colombier int fdin, fdout, ctl, n, m; 559a747e4fSDavid du Colombier char line[10]; 569a747e4fSDavid du Colombier 579a747e4fSDavid du Colombier fdin = open("/dev/cons", OREAD); 589a747e4fSDavid du Colombier if(fdin < 0) 599a747e4fSDavid du Colombier fdin = 0; 609a747e4fSDavid du Colombier fdout = open("/dev/cons", OWRITE); 619a747e4fSDavid du Colombier if(fdout < 0) 629a747e4fSDavid du Colombier fdout = 1; 639a747e4fSDavid du Colombier if(def != nil) 649a747e4fSDavid du Colombier fprint(fdout, "%s[%s]: ", prompt, def); 659a747e4fSDavid du Colombier else 669a747e4fSDavid du Colombier fprint(fdout, "%s: ", prompt); 679a747e4fSDavid du Colombier if(raw){ 689a747e4fSDavid du Colombier ctl = open("/dev/consctl", OWRITE); 699a747e4fSDavid du Colombier if(ctl >= 0) 709a747e4fSDavid du Colombier write(ctl, "rawon", 5); 719a747e4fSDavid du Colombier } else 729a747e4fSDavid du Colombier ctl = -1; 739a747e4fSDavid du Colombier 749a747e4fSDavid du Colombier m = 0; 759a747e4fSDavid du Colombier for(;;){ 769a747e4fSDavid du Colombier n = read(fdin, line, 1); 779a747e4fSDavid du Colombier if(n == 0){ 789a747e4fSDavid du Colombier close(ctl); 799a747e4fSDavid du Colombier werrstr("readcons: EOF"); 809a747e4fSDavid du Colombier return nil; 819a747e4fSDavid du Colombier } 829a747e4fSDavid du Colombier if(n < 0){ 839a747e4fSDavid du Colombier close(ctl); 849a747e4fSDavid du Colombier werrstr("can't read cons"); 859a747e4fSDavid du Colombier return nil; 869a747e4fSDavid du Colombier } 879a747e4fSDavid du Colombier if(line[0] == 0x7f) 889a747e4fSDavid du Colombier exits(0); 899a747e4fSDavid du Colombier if(n == 0 || line[0] == '\n' || line[0] == '\r'){ 909a747e4fSDavid du Colombier if(raw){ 919a747e4fSDavid du Colombier write(ctl, "rawoff", 6); 929a747e4fSDavid du Colombier write(fdout, "\n", 1); 939a747e4fSDavid du Colombier close(ctl); 949a747e4fSDavid du Colombier } 959a747e4fSDavid du Colombier buf[m] = '\0'; 969a747e4fSDavid du Colombier if(buf[0]=='\0' && def) 979a747e4fSDavid du Colombier strcpy(buf, def); 989a747e4fSDavid du Colombier return buf; 999a747e4fSDavid du Colombier } 1009a747e4fSDavid du Colombier if(line[0] == '\b'){ 1019a747e4fSDavid du Colombier if(m > 0) 1029a747e4fSDavid du Colombier m--; 1039a747e4fSDavid du Colombier }else if(line[0] == 0x15){ /* ^U: line kill */ 1049a747e4fSDavid du Colombier m = 0; 1059a747e4fSDavid du Colombier if(def != nil) 1069a747e4fSDavid du Colombier fprint(fdout, "%s[%s]: ", prompt, def); 1079a747e4fSDavid du Colombier else 1089a747e4fSDavid du Colombier fprint(fdout, "%s: ", prompt); 1099a747e4fSDavid du Colombier }else{ 1109a747e4fSDavid du Colombier if(m >= nbuf-1){ 1119a747e4fSDavid du Colombier fprint(fdout, "line too long\n"); 1129a747e4fSDavid du Colombier m = 0; 1139a747e4fSDavid du Colombier if(def != nil) 1149a747e4fSDavid du Colombier fprint(fdout, "%s[%s]: ", prompt, def); 1159a747e4fSDavid du Colombier else 1169a747e4fSDavid du Colombier fprint(fdout, "%s: ", prompt); 1179a747e4fSDavid du Colombier }else 1189a747e4fSDavid du Colombier buf[m++] = line[0]; 1199a747e4fSDavid du Colombier } 1209a747e4fSDavid du Colombier } 1219a747e4fSDavid du Colombier } 1229a747e4fSDavid du Colombier 1239a747e4fSDavid du Colombier 1249a747e4fSDavid du Colombier /* 1259a747e4fSDavid du Colombier * get key info out of nvram. since there isn't room in the PC's nvram use 1269a747e4fSDavid du Colombier * a disk partition there. 1279a747e4fSDavid du Colombier */ 1289a747e4fSDavid du Colombier int 1299a747e4fSDavid du Colombier readnvram(Nvrsafe *safep, int flag) 1309a747e4fSDavid du Colombier { 131d3c05884SDavid du Colombier char buf[1024], in[128], *cputype, *nvrfile, *nvrlen, *nvroff, *v[2]; 1329a747e4fSDavid du Colombier int fd, err, i, safeoff, safelen; 1339a747e4fSDavid du Colombier Nvrsafe *safe; 1349a747e4fSDavid du Colombier 1359a747e4fSDavid du Colombier err = 0; 1369a747e4fSDavid du Colombier memset(safep, 0, sizeof(*safep)); 1379a747e4fSDavid du Colombier 138d3c05884SDavid du Colombier nvrfile = getenv("nvram"); 1399a747e4fSDavid du Colombier cputype = getenv("cputype"); 1409a747e4fSDavid du Colombier if(cputype == nil) 1419a747e4fSDavid du Colombier cputype = "mips"; 1429a747e4fSDavid du Colombier if(strcmp(cputype, "386")==0 || strcmp(cputype, "alpha")==0) 1439a747e4fSDavid du Colombier cputype = "pc"; 1449a747e4fSDavid du Colombier 1459a747e4fSDavid du Colombier safe = (Nvrsafe*)buf; 1469a747e4fSDavid du Colombier 1479a747e4fSDavid du Colombier fd = -1; 1489a747e4fSDavid du Colombier safeoff = -1; 1499a747e4fSDavid du Colombier safelen = -1; 150d3c05884SDavid du Colombier if(nvrfile != nil){ 151d3c05884SDavid du Colombier /* accept device and device!file */ 152d3c05884SDavid du Colombier i = gettokens(nvrfile, v, nelem(v), "!"); 153d3c05884SDavid du Colombier fd = open(v[0], ORDWR); 154d3c05884SDavid du Colombier safelen = sizeof(Nvrsafe); 155d3c05884SDavid du Colombier if(strstr(v[0], "/9fat") == nil) 156d3c05884SDavid du Colombier safeoff = 0; 157d3c05884SDavid du Colombier nvrlen = getenv("nvrlen"); 158d3c05884SDavid du Colombier if(nvrlen != nil) 159d3c05884SDavid du Colombier safelen = atoi(nvrlen); 160d3c05884SDavid du Colombier nvroff = getenv("nvroff"); 161d3c05884SDavid du Colombier if(nvroff != nil){ 162d3c05884SDavid du Colombier if(strcmp(nvroff, "dos") == 0) 163d3c05884SDavid du Colombier safeoff = -1; 164d3c05884SDavid du Colombier else 165d3c05884SDavid du Colombier safeoff = atoi(nvroff); 166d3c05884SDavid du Colombier } 167d3c05884SDavid du Colombier if(safeoff < 0 && fd >= 0){ 168d3c05884SDavid du Colombier safelen = 512; 169d3c05884SDavid du Colombier safeoff = finddosfile(fd, i == 2 ? v[1] : "plan9.nvr"); 170d3c05884SDavid du Colombier if(safeoff < 0){ 171d3c05884SDavid du Colombier close(fd); 172d3c05884SDavid du Colombier fd = -1; 173d3c05884SDavid du Colombier } 174d3c05884SDavid du Colombier } 175d3c05884SDavid du Colombier free(nvrfile); 176d3c05884SDavid du Colombier if(nvrlen != nil) 177d3c05884SDavid du Colombier free(nvrlen); 178d3c05884SDavid du Colombier if(nvroff != nil) 179d3c05884SDavid du Colombier free(nvroff); 180d3c05884SDavid du Colombier }else{ 1819a747e4fSDavid du Colombier for(i=0; i<nelem(nvtab); i++){ 1829a747e4fSDavid du Colombier if(strcmp(cputype, nvtab[i].cputype) != 0) 1839a747e4fSDavid du Colombier continue; 1849a747e4fSDavid du Colombier if((fd = open(nvtab[i].file, ORDWR)) < 0) 1859a747e4fSDavid du Colombier continue; 1869a747e4fSDavid du Colombier safeoff = nvtab[i].off; 1879a747e4fSDavid du Colombier safelen = nvtab[i].len; 1889a747e4fSDavid du Colombier if(safeoff == -1){ 1899a747e4fSDavid du Colombier safeoff = finddosfile(fd, "plan9.nvr"); 1909a747e4fSDavid du Colombier if(safeoff < 0){ 1919a747e4fSDavid du Colombier close(fd); 1929a747e4fSDavid du Colombier fd = -1; 1939a747e4fSDavid du Colombier continue; 1949a747e4fSDavid du Colombier } 1959a747e4fSDavid du Colombier } 1969a747e4fSDavid du Colombier break; 1979a747e4fSDavid du Colombier } 198d3c05884SDavid du Colombier } 1999a747e4fSDavid du Colombier 2009a747e4fSDavid du Colombier if(fd < 0 2019a747e4fSDavid du Colombier || seek(fd, safeoff, 0) < 0 2029a747e4fSDavid du Colombier || read(fd, buf, safelen) != safelen){ 2039a747e4fSDavid du Colombier err = 1; 2049a747e4fSDavid du Colombier if(flag&(NVwrite|NVwriteonerr)) 2053ff48bf5SDavid du Colombier fprint(2, "can't read nvram: %r\n"); 2069a747e4fSDavid du Colombier memset(safep, 0, sizeof(*safep)); 2079a747e4fSDavid du Colombier safe = safep; 2089a747e4fSDavid du Colombier }else{ 2099a747e4fSDavid du Colombier *safep = *safe; 2109a747e4fSDavid du Colombier safe = safep; 2119a747e4fSDavid du Colombier 2129a747e4fSDavid du Colombier err |= check(safe->machkey, DESKEYLEN, safe->machsum, "bad nvram key"); 2139a747e4fSDavid du Colombier // err |= check(safe->config, CONFIGLEN, safe->configsum, "bad secstore key"); 2149a747e4fSDavid du Colombier err |= check(safe->authid, ANAMELEN, safe->authidsum, "bad authentication id"); 2159a747e4fSDavid du Colombier err |= check(safe->authdom, DOMLEN, safe->authdomsum, "bad authentication domain"); 2165fe11e25SDavid du Colombier 2175fe11e25SDavid du Colombier if(err == 0) 2185fe11e25SDavid du Colombier if(safe->authid[0]==0 || safe->authdom[0]==0){ 2195fe11e25SDavid du Colombier fprint(2, "empty nvram authid or authdom\n"); 2205fe11e25SDavid du Colombier err = 1; 2215fe11e25SDavid du Colombier } 2229a747e4fSDavid du Colombier } 2239a747e4fSDavid du Colombier 2249a747e4fSDavid du Colombier if((flag&NVwrite) || (err && (flag&NVwriteonerr))){ 2259a747e4fSDavid du Colombier readcons("authid", nil, 0, safe->authid, sizeof(safe->authid)); 2269a747e4fSDavid du Colombier readcons("authdom", nil, 0, safe->authdom, sizeof(safe->authdom)); 2279a747e4fSDavid du Colombier readcons("secstore key", nil, 1, safe->config, sizeof(safe->config)); 2289a747e4fSDavid du Colombier for(;;){ 2299a747e4fSDavid du Colombier if(readcons("password", nil, 1, in, sizeof in) == nil) 2309a747e4fSDavid du Colombier goto Out; 2319a747e4fSDavid du Colombier if(passtokey(safe->machkey, in)) 2329a747e4fSDavid du Colombier break; 2339a747e4fSDavid du Colombier } 2349a747e4fSDavid du Colombier safe->machsum = nvcsum(safe->machkey, DESKEYLEN); 2359a747e4fSDavid du Colombier safe->configsum = nvcsum(safe->config, CONFIGLEN); 2369a747e4fSDavid du Colombier safe->authidsum = nvcsum(safe->authid, sizeof(safe->authid)); 2379a747e4fSDavid du Colombier safe->authdomsum = nvcsum(safe->authdom, sizeof(safe->authdom)); 2389a747e4fSDavid du Colombier *(Nvrsafe*)buf = *safe; 2399a747e4fSDavid du Colombier if(seek(fd, safeoff, 0) < 0 2409a747e4fSDavid du Colombier || write(fd, buf, safelen) != safelen){ 2419a747e4fSDavid du Colombier fprint(2, "can't write key to nvram: %r\n"); 2429a747e4fSDavid du Colombier err = 1; 2439a747e4fSDavid du Colombier }else 2449a747e4fSDavid du Colombier err = 0; 2459a747e4fSDavid du Colombier } 2469a747e4fSDavid du Colombier Out: 2479a747e4fSDavid du Colombier close(fd); 2489a747e4fSDavid du Colombier return err ? -1 : 0; 2499a747e4fSDavid du Colombier } 2509a747e4fSDavid du Colombier 2519a747e4fSDavid du Colombier typedef struct Dosboot Dosboot; 2529a747e4fSDavid du Colombier struct Dosboot{ 2539a747e4fSDavid du Colombier uchar magic[3]; /* really an xx86 JMP instruction */ 2549a747e4fSDavid du Colombier uchar version[8]; 2559a747e4fSDavid du Colombier uchar sectsize[2]; 2569a747e4fSDavid du Colombier uchar clustsize; 2579a747e4fSDavid du Colombier uchar nresrv[2]; 2589a747e4fSDavid du Colombier uchar nfats; 2599a747e4fSDavid du Colombier uchar rootsize[2]; 2609a747e4fSDavid du Colombier uchar volsize[2]; 2619a747e4fSDavid du Colombier uchar mediadesc; 2629a747e4fSDavid du Colombier uchar fatsize[2]; 2639a747e4fSDavid du Colombier uchar trksize[2]; 2649a747e4fSDavid du Colombier uchar nheads[2]; 2659a747e4fSDavid du Colombier uchar nhidden[4]; 2669a747e4fSDavid du Colombier uchar bigvolsize[4]; 2679a747e4fSDavid du Colombier uchar driveno; 2689a747e4fSDavid du Colombier uchar reserved0; 2699a747e4fSDavid du Colombier uchar bootsig; 2709a747e4fSDavid du Colombier uchar volid[4]; 2719a747e4fSDavid du Colombier uchar label[11]; 2729a747e4fSDavid du Colombier uchar type[8]; 2739a747e4fSDavid du Colombier }; 2749a747e4fSDavid du Colombier #define GETSHORT(p) (((p)[1]<<8) | (p)[0]) 2759a747e4fSDavid du Colombier #define GETLONG(p) ((GETSHORT((p)+2) << 16) | GETSHORT((p))) 2769a747e4fSDavid du Colombier 2779a747e4fSDavid du Colombier typedef struct Dosdir Dosdir; 2789a747e4fSDavid du Colombier struct Dosdir 2799a747e4fSDavid du Colombier { 2809a747e4fSDavid du Colombier char name[8]; 2819a747e4fSDavid du Colombier char ext[3]; 2829a747e4fSDavid du Colombier uchar attr; 2839a747e4fSDavid du Colombier uchar reserved[10]; 2849a747e4fSDavid du Colombier uchar time[2]; 2859a747e4fSDavid du Colombier uchar date[2]; 2869a747e4fSDavid du Colombier uchar start[2]; 2879a747e4fSDavid du Colombier uchar length[4]; 2889a747e4fSDavid du Colombier }; 2899a747e4fSDavid du Colombier 2909a747e4fSDavid du Colombier static char* 2919a747e4fSDavid du Colombier dosparse(char *from, char *to, int len) 2929a747e4fSDavid du Colombier { 2939a747e4fSDavid du Colombier char c; 2949a747e4fSDavid du Colombier 2959a747e4fSDavid du Colombier memset(to, ' ', len); 2969a747e4fSDavid du Colombier if(from == 0) 2979a747e4fSDavid du Colombier return 0; 2989a747e4fSDavid du Colombier while(len-- > 0){ 2999a747e4fSDavid du Colombier c = *from++; 3009a747e4fSDavid du Colombier if(c == '.') 3019a747e4fSDavid du Colombier return from; 3029a747e4fSDavid du Colombier if(c == 0) 3039a747e4fSDavid du Colombier break; 3049a747e4fSDavid du Colombier if(c >= 'a' && c <= 'z') 3059a747e4fSDavid du Colombier *to++ = c + 'A' - 'a'; 3069a747e4fSDavid du Colombier else 3079a747e4fSDavid du Colombier *to++ = c; 3089a747e4fSDavid du Colombier } 3099a747e4fSDavid du Colombier return 0; 3109a747e4fSDavid du Colombier } 3119a747e4fSDavid du Colombier 3129a747e4fSDavid du Colombier /* 3139a747e4fSDavid du Colombier * return offset of first file block 3149a747e4fSDavid du Colombier * 3159a747e4fSDavid du Colombier * This is a very simplistic dos file system. It only 3169a747e4fSDavid du Colombier * works on floppies, only looks in the root, and only 3179a747e4fSDavid du Colombier * returns a pointer to the first block of a file. 3189a747e4fSDavid du Colombier * 3199a747e4fSDavid du Colombier * This exists for cpu servers that have no hard disk 3209a747e4fSDavid du Colombier * or nvram to store the key on. 3219a747e4fSDavid du Colombier * 3229a747e4fSDavid du Colombier * Please don't make this any smarter: it stays resident 3239a747e4fSDavid du Colombier * and I'ld prefer not to waste the space on something that 3249a747e4fSDavid du Colombier * runs only at boottime -- presotto. 3259a747e4fSDavid du Colombier */ 3269a747e4fSDavid du Colombier static long 3279a747e4fSDavid du Colombier finddosfile(int fd, char *file) 3289a747e4fSDavid du Colombier { 3299a747e4fSDavid du Colombier uchar secbuf[512]; 3309a747e4fSDavid du Colombier char name[8]; 3319a747e4fSDavid du Colombier char ext[3]; 3329a747e4fSDavid du Colombier Dosboot *b; 3339a747e4fSDavid du Colombier Dosdir *root, *dp; 3349a747e4fSDavid du Colombier int nroot, sectsize, rootoff, rootsects, n; 3359a747e4fSDavid du Colombier 3369a747e4fSDavid du Colombier /* dos'ize file name */ 3379a747e4fSDavid du Colombier file = dosparse(file, name, 8); 3389a747e4fSDavid du Colombier dosparse(file, ext, 3); 3399a747e4fSDavid du Colombier 3409a747e4fSDavid du Colombier /* read boot block, check for sanity */ 3419a747e4fSDavid du Colombier b = (Dosboot*)secbuf; 3429a747e4fSDavid du Colombier if(read(fd, secbuf, sizeof(secbuf)) != sizeof(secbuf)) 3439a747e4fSDavid du Colombier return -1; 3449a747e4fSDavid du Colombier if(b->magic[0] != 0xEB || b->magic[1] != 0x3C || b->magic[2] != 0x90) 3459a747e4fSDavid du Colombier return -1; 3469a747e4fSDavid du Colombier sectsize = GETSHORT(b->sectsize); 3479a747e4fSDavid du Colombier if(sectsize != 512) 3489a747e4fSDavid du Colombier return -1; 3499a747e4fSDavid du Colombier rootoff = (GETSHORT(b->nresrv) + b->nfats*GETSHORT(b->fatsize)) * sectsize; 3509a747e4fSDavid du Colombier if(seek(fd, rootoff, 0) < 0) 3519a747e4fSDavid du Colombier return -1; 3529a747e4fSDavid du Colombier nroot = GETSHORT(b->rootsize); 3539a747e4fSDavid du Colombier rootsects = (nroot*sizeof(Dosdir)+sectsize-1)/sectsize; 3549a747e4fSDavid du Colombier if(rootsects <= 0 || rootsects > 64) 3559a747e4fSDavid du Colombier return -1; 3569a747e4fSDavid du Colombier 3579a747e4fSDavid du Colombier /* 3589a747e4fSDavid du Colombier * read root. it is contiguous to make stuff like 3599a747e4fSDavid du Colombier * this easier 3609a747e4fSDavid du Colombier */ 3619a747e4fSDavid du Colombier root = malloc(rootsects*sectsize); 3629a747e4fSDavid du Colombier if(read(fd, root, rootsects*sectsize) != rootsects*sectsize) 3639a747e4fSDavid du Colombier return -1; 3649a747e4fSDavid du Colombier n = -1; 3659a747e4fSDavid du Colombier for(dp = root; dp < &root[nroot]; dp++) 3669a747e4fSDavid du Colombier if(memcmp(name, dp->name, 8) == 0 && memcmp(ext, dp->ext, 3) == 0){ 3679a747e4fSDavid du Colombier n = GETSHORT(dp->start); 3689a747e4fSDavid du Colombier break; 3699a747e4fSDavid du Colombier } 3709a747e4fSDavid du Colombier free(root); 3719a747e4fSDavid du Colombier 3729a747e4fSDavid du Colombier if(n < 0) 3739a747e4fSDavid du Colombier return -1; 3749a747e4fSDavid du Colombier 3759a747e4fSDavid du Colombier /* 3769a747e4fSDavid du Colombier * dp->start is in cluster units, not sectors. The first 3779a747e4fSDavid du Colombier * cluster is cluster 2 which starts immediately after the 3789a747e4fSDavid du Colombier * root directory 3799a747e4fSDavid du Colombier */ 3809a747e4fSDavid du Colombier return rootoff + rootsects*sectsize + (n-2)*sectsize*b->clustsize; 3819a747e4fSDavid du Colombier } 3829a747e4fSDavid du Colombier 383