Introduction
Introduction Statistics Contact Development Disclaimer Help
text2.c - plan9port - [fork] Plan 9 from user space
git clone git://src.adamsgaard.dk/plan9port
Log
Files
Refs
README
LICENSE
---
text2.c (18673B)
---
1 #include <u.h>
2 #include <libc.h>
3 #include <thread.h>
4 #include <sunrpc.h>
5 #include <nfs3.h>
6 #include <diskfs.h>
7 #include "ext2.h"
8
9 static void parsedirent(Dirent*, uchar*);
10 static void parseinode(Inode*, uchar*);
11 static void parsegroup(Group*, uchar*);
12 static void parsesuper(Super*, uchar*);
13
14 #define debug 0
15
16 static int ext2sync(Fsys*);
17 static void ext2close(Fsys*);
18 static Block* ext2blockread(Fsys*, u64int);
19
20 static Nfs3Status ext2root(Fsys*, Nfs3Handle*);
21 static Nfs3Status ext2getattr(Fsys*, SunAuthUnix *au, Nfs3Handle*, Nfs3A…
22 static Nfs3Status ext2lookup(Fsys*, SunAuthUnix *au, Nfs3Handle*, char*,…
23 static Nfs3Status ext2readfile(Fsys*, SunAuthUnix *au, Nfs3Handle*, u32i…
24 static Nfs3Status ext2readlink(Fsys *fsys, SunAuthUnix *au, Nfs3Handle *…
25 static Nfs3Status ext2readdir(Fsys *fsys, SunAuthUnix *au, Nfs3Handle *h…
26 static Nfs3Status ext2access(Fsys *fsys, SunAuthUnix *au, Nfs3Handle *h,…
27
28 Fsys*
29 fsysopenext2(Disk *disk)
30 {
31 Ext2 *fs;
32 Fsys *fsys;
33
34 fsys = emalloc(sizeof(Fsys));
35 fs = emalloc(sizeof(Ext2));
36 fs->disk = disk;
37 fsys->priv = fs;
38 fs->fsys = fsys;
39 fsys->type = "ext2";
40 fsys->_readblock = ext2blockread;
41 fsys->_sync = ext2sync;
42 fsys->_root = ext2root;
43 fsys->_getattr = ext2getattr;
44 fsys->_access = ext2access;
45 fsys->_lookup = ext2lookup;
46 fsys->_readfile = ext2readfile;
47 fsys->_readlink = ext2readlink;
48 fsys->_readdir = ext2readdir;
49 fsys->_close = ext2close;
50
51 if(ext2sync(fsys) < 0)
52 goto error;
53
54 return fsys;
55
56 error:
57 ext2close(fsys);
58 return nil;
59 }
60
61 static void
62 ext2close(Fsys *fsys)
63 {
64 Ext2 *fs;
65
66 fs = fsys->priv;
67 free(fs);
68 free(fsys);
69 }
70
71 static int
72 ext2group(Ext2 *fs, u32int i, Group *g)
73 {
74 Block *b;
75 u64int addr;
76
77 if(i >= fs->ngroup)
78 return -1;
79
80 addr = fs->groupaddr + i/fs->descperblock;
81 b = diskread(fs->disk, fs->blocksize, addr*fs->blocksize);
82 if(b == nil)
83 return -1;
84 parsegroup(g, b->data+i%fs->descperblock*GroupSize);
85 blockput(b);
86 return 0;
87 }
88
89 static Block*
90 ext2blockread(Fsys *fsys, u64int vbno)
91 {
92 Block *bitb;
93 Group g;
94 uchar *bits;
95 u32int bno, boff, bitblock;
96 u64int bitpos;
97 Ext2 *fs;
98
99 fs = fsys->priv;
100 if(vbno >= fs->nblock)
101 return nil;
102 bno = vbno;
103 if(bno != vbno)
104 return nil;
105
106 /*
107 if(bno < fs->firstblock)
108 return diskread(fs->disk, fs->blocksize, (u64int)bno*fs-…
109 */
110 if(bno < fs->firstblock)
111 return nil;
112
113 bno -= fs->firstblock;
114 if(ext2group(fs, bno/fs->blockspergroup, &g) < 0){
115 if(debug)
116 fprint(2, "loading group: %r...");
117 return nil;
118 }
119 /*
120 if(debug)
121 fprint(2, "ext2 group %d: bitblock=%ud inodebitblock=%ud…
122 (int)(bno/fs->blockspergroup),
123 g.bitblock,
124 g.inodebitblock,
125 g.inodeaddr,
126 g.freeblockscount,
127 g.freeinodescount,
128 g.useddirscount);
129 if(debug)
130 fprint(2, "group %d bitblock=%d...", bno/fs->blockspergr…
131 */
132 bitblock = g.bitblock;
133 bitpos = (u64int)bitblock*fs->blocksize;
134
135 if((bitb = diskread(fs->disk, fs->blocksize, bitpos)) == nil){
136 if(debug)
137 fprint(2, "loading bitblock: %r...");
138 return nil;
139 }
140 bits = bitb->data;
141 boff = bno%fs->blockspergroup;
142 if((bits[boff>>3] & (1<<(boff&7))) == 0){
143 if(debug)
144 fprint(2, "block %d not allocated in group %d: b…
145 boff, bno/fs->blockspergroup,
146 (int)bitblock,
147 bitpos,
148 boff>>3,
149 bits[boff>>3]);
150 blockput(bitb);
151 return nil;
152 }
153 blockput(bitb);
154
155 bno += fs->firstblock;
156 return diskread(fs->disk, fs->blocksize, (u64int)bno*fs->blocksi…
157 }
158
159 static Block*
160 ext2datablock(Ext2 *fs, u32int bno, int size)
161 {
162 USED(size);
163 return ext2blockread(fs->fsys, bno);
164 }
165
166 static Block*
167 ext2fileblock(Ext2 *fs, Inode *ino, u32int bno, int size)
168 {
169 int ppb;
170 Block *b;
171 u32int *a;
172 u32int obno, pbno;
173
174 obno = bno;
175 if(bno < NDIRBLOCKS){
176 if(debug)
177 fprint(2, "fileblock %d -> %d...",
178 bno, ino->block[bno]);
179 return ext2datablock(fs, ino->block[bno], size);
180 }
181 bno -= NDIRBLOCKS;
182 ppb = fs->blocksize/4;
183
184 /* one indirect */
185 if(bno < ppb){
186 b = ext2datablock(fs, ino->block[INDBLOCK], fs->blocksiz…
187 if(b == nil)
188 return nil;
189 a = (u32int*)b->data;
190 bno = a[bno];
191 blockput(b);
192 return ext2datablock(fs, bno, size);
193 }
194 bno -= ppb;
195
196 /* one double indirect */
197 if(bno < ppb*ppb){
198 b = ext2datablock(fs, ino->block[DINDBLOCK], fs->blocksi…
199 if(b == nil)
200 return nil;
201 a = (u32int*)b->data;
202 pbno = a[bno/ppb];
203 bno = bno%ppb;
204 blockput(b);
205 b = ext2datablock(fs, pbno, fs->blocksize);
206 if(b == nil)
207 return nil;
208 a = (u32int*)b->data;
209 bno = a[bno];
210 blockput(b);
211 return ext2datablock(fs, bno, size);
212 }
213 bno -= ppb*ppb;
214
215 /* one triple indirect */
216 if(bno < ppb*ppb*ppb){
217 b = ext2datablock(fs, ino->block[TINDBLOCK], fs->blocksi…
218 if(b == nil)
219 return nil;
220 a = (u32int*)b->data;
221 pbno = a[bno/(ppb*ppb)];
222 bno = bno%(ppb*ppb);
223 blockput(b);
224 b = ext2datablock(fs, pbno, fs->blocksize);
225 if(b == nil)
226 return nil;
227 a = (u32int*)b->data;
228 pbno = a[bno/ppb];
229 bno = bno%ppb;
230 blockput(b);
231 b = ext2datablock(fs, pbno, fs->blocksize);
232 if(b == nil)
233 return nil;
234 a = (u32int*)b->data;
235 bno = a[bno];
236 blockput(b);
237 return ext2datablock(fs, bno, size);
238 }
239
240 fprint(2, "ext2fileblock %ud: too big\n", obno);
241 return nil;
242 }
243
244 static int
245 checksuper(Super *super)
246 {
247 if(super->magic != SUPERMAGIC){
248 werrstr("bad magic 0x%ux wanted 0x%ux", super->magic, SU…
249 return -1;
250 }
251 return 0;
252 }
253
254 static int
255 ext2sync(Fsys *fsys)
256 {
257 int i;
258 Group g;
259 Block *b;
260 Super super;
261 Ext2 *fs;
262 Disk *disk;
263
264 fs = fsys->priv;
265 disk = fs->disk;
266 if((b = diskread(disk, SBSIZE, SBOFF)) == nil)
267 return -1;
268 parsesuper(&super, b->data);
269 blockput(b);
270 if(checksuper(&super) < 0)
271 return -1;
272 fs->blocksize = MINBLOCKSIZE<<super.logblocksize;
273 fs->nblock = super.nblock;
274 fs->ngroup = (super.nblock+super.blockspergroup-1)
275 / super.blockspergroup;
276 fs->inospergroup = super.inospergroup;
277 fs->blockspergroup = super.blockspergroup;
278 if(super.revlevel >= 1)
279 fs->inosize = super.inosize;
280 else
281 fs->inosize = 128;
282 fs->inosperblock = fs->blocksize / fs->inosize;
283 if(fs->blocksize == SBOFF)
284 fs->groupaddr = 2;
285 else
286 fs->groupaddr = 1;
287 fs->descperblock = fs->blocksize / GroupSize;
288 fs->firstblock = super.firstdatablock;
289
290 fsys->blocksize = fs->blocksize;
291 fsys->nblock = fs->nblock;
292 if(debug) fprint(2, "ext2 %d %d-byte blocks, first data block %d…
293 fs->nblock, fs->blocksize, fs->firstblock, fs->ngroup, f…
294
295 if(0){
296 for(i=0; i<fs->ngroup; i++)
297 if(ext2group(fs, i, &g) >= 0)
298 fprint(2, "grp %d: bitblock=%d\n", i, g.…
299 }
300 return 0;
301 }
302
303 static void
304 mkhandle(Nfs3Handle *h, u64int ino)
305 {
306 h->h[0] = ino>>24;
307 h->h[1] = ino>>16;
308 h->h[2] = ino>>8;
309 h->h[3] = ino;
310 h->len = 4;
311 }
312
313 static u32int
314 byte2u32(uchar *p)
315 {
316 return (p[0]<<24) | (p[1]<<16) | (p[2]<<8) | p[3];
317 }
318
319 static Nfs3Status
320 handle2ino(Ext2 *fs, Nfs3Handle *h, u32int *pinum, Inode *ino)
321 {
322 int i;
323 uint ioff;
324 u32int inum;
325 u32int addr;
326 Block *b;
327 Group g;
328
329 if(h->len != 4)
330 return Nfs3ErrBadHandle;
331 inum = byte2u32(h->h);
332 if(pinum)
333 *pinum = inum;
334 i = (inum-1) / fs->inospergroup;
335 if(i >= fs->ngroup)
336 return Nfs3ErrBadHandle;
337 ioff = (inum-1) % fs->inospergroup;
338 if(ext2group(fs, i, &g) < 0)
339 return Nfs3ErrIo;
340 addr = g.inodeaddr + ioff/fs->inosperblock;
341 if((b = diskread(fs->disk, fs->blocksize, (u64int)addr*fs->block…
342 return Nfs3ErrIo;
343 parseinode(ino, b->data+fs->inosize*(ioff%fs->inosperblock));
344 blockput(b);
345 return Nfs3Ok;
346 }
347
348 static Nfs3Status
349 ext2root(Fsys *fsys, Nfs3Handle *h)
350 {
351 USED(fsys);
352 mkhandle(h, ROOTINODE);
353 return Nfs3Ok;
354 }
355
356 static u64int
357 inosize(Inode* ino)
358 {
359 u64int size;
360
361 size = ino->size;
362 if((ino->mode&IFMT)==IFREG)
363 size |= (u64int)ino->diracl << 32;
364 return size;
365 }
366
367 static Nfs3Status
368 ino2attr(Ext2 *fs, Inode *ino, u32int inum, Nfs3Attr *attr)
369 {
370 u32int rdev;
371
372 attr->type = -1;
373 switch(ino->mode&IFMT){
374 case IFIFO:
375 attr->type = Nfs3FileFifo;
376 break;
377 case IFCHR:
378 attr->type = Nfs3FileChar;
379 break;
380 case IFDIR:
381 attr->type = Nfs3FileDir;
382 break;
383 case IFBLK:
384 attr->type = Nfs3FileBlock;
385 break;
386 case IFREG:
387 attr->type = Nfs3FileReg;
388 break;
389 case IFLNK:
390 attr->type = Nfs3FileSymlink;
391 break;
392 case IFSOCK:
393 attr->type = Nfs3FileSocket;
394 break;
395 case IFWHT:
396 default:
397 return Nfs3ErrBadHandle;
398 }
399
400 attr->mode = ino->mode&07777;
401 attr->nlink = ino->nlink;
402 attr->uid = ino->uid;
403 attr->gid = ino->gid;
404 attr->size = inosize(ino);
405 attr->used = (u64int)ino->nblock*fs->blocksize;
406 if(attr->type==Nfs3FileBlock || attr->type==Nfs3FileChar){
407 rdev = ino->block[0];
408 attr->major = (rdev>>8)&0xFF;
409 attr->minor = rdev & 0xFFFF00FF;
410 }else{
411 attr->major = 0;
412 attr->minor = 0;
413 }
414 attr->fsid = 0;
415 attr->fileid = inum;
416 attr->atime.sec = ino->atime;
417 attr->atime.nsec = 0;
418 attr->mtime.sec = ino->mtime;
419 attr->mtime.nsec = 0;
420 attr->ctime.sec = ino->ctime;
421 attr->ctime.nsec = 0;
422 return Nfs3Ok;
423 }
424
425 static int
426 ingroup(SunAuthUnix *au, uint gid)
427 {
428 int i;
429
430 for(i=0; i<au->ng; i++)
431 if(au->g[i] == gid)
432 return 1;
433 return 0;
434 }
435
436 static Nfs3Status
437 inoperm(Inode *ino, SunAuthUnix *au, int need)
438 {
439 int have;
440
441 if(allowall)
442 return Nfs3Ok;
443
444 have = ino->mode&0777;
445 if(ino->uid == au->uid)
446 have >>= 6;
447 else if(ino->gid == au->gid || ingroup(au, ino->gid))
448 have >>= 3;
449
450 if((have&need) != need)
451 return Nfs3ErrNotOwner; /* really EPERM */
452 return Nfs3Ok;
453 }
454
455 static Nfs3Status
456 ext2getattr(Fsys *fsys, SunAuthUnix *au, Nfs3Handle *h, Nfs3Attr *attr)
457 {
458 Inode ino;
459 u32int inum;
460 Ext2 *fs;
461 Nfs3Status ok;
462
463 fs = fsys->priv;
464 if((ok = handle2ino(fs, h, &inum, &ino)) != Nfs3Ok)
465 return ok;
466
467 USED(au); /* anyone can getattr */
468 return ino2attr(fs, &ino, inum, attr);
469 }
470
471 static Nfs3Status
472 ext2access(Fsys *fsys, SunAuthUnix *au, Nfs3Handle *h, u32int want, u32i…
473 {
474 int have;
475 Inode ino;
476 u32int inum;
477 Ext2 *fs;
478 Nfs3Status ok;
479
480 fs = fsys->priv;
481 if((ok = handle2ino(fs, h, &inum, &ino)) != Nfs3Ok)
482 return ok;
483
484 have = ino.mode&0777;
485 if(ino.uid == au->uid)
486 have >>= 6;
487 else if(ino.gid == au->gid || ingroup(au, ino.gid))
488 have >>= 3;
489
490 *got = 0;
491 if((want&Nfs3AccessRead) && (have&AREAD))
492 *got |= Nfs3AccessRead;
493 if((want&Nfs3AccessLookup) && (ino.mode&IFMT)==IFDIR && (have&AE…
494 *got |= Nfs3AccessLookup;
495 if((want&Nfs3AccessExecute) && (ino.mode&IFMT)!=IFDIR && (have&A…
496 *got |= Nfs3AccessExecute;
497
498 return ino2attr(fs, &ino, inum, attr);
499 }
500
501 static Nfs3Status
502 ext2lookup(Fsys *fsys, SunAuthUnix *au, Nfs3Handle *h, char *name, Nfs3H…
503 {
504 u32int nblock;
505 u32int i;
506 uchar *p, *ep;
507 Dirent de;
508 Inode ino;
509 Block *b;
510 Ext2 *fs;
511 Nfs3Status ok;
512 int len, want;
513
514 fs = fsys->priv;
515 if((ok = handle2ino(fs, h, nil, &ino)) != Nfs3Ok)
516 return ok;
517
518 if((ino.mode&IFMT) != IFDIR)
519 return Nfs3ErrNotDir;
520
521 if((ok = inoperm(&ino, au, AEXEC)) != Nfs3Ok)
522 return ok;
523
524 len = strlen(name);
525 nblock = (ino.size+fs->blocksize-1) / fs->blocksize;
526 if(debug) fprint(2, "%d blocks in dir...", nblock);
527 for(i=0; i<nblock; i++){
528 if(i==nblock-1)
529 want = ino.size % fs->blocksize;
530 else
531 want = fs->blocksize;
532 b = ext2fileblock(fs, &ino, i, want);
533 if(b == nil){
534 if(debug) fprint(2, "empty block...");
535 continue;
536 }
537 p = b->data;
538 ep = p+b->len;
539 while(p < ep){
540 parsedirent(&de, p);
541 if(de.reclen == 0){
542 if(debug)
543 fprint(2, "reclen 0 at offset %d…
544 break;
545 }
546 p += de.reclen;
547 if(p > ep){
548 if(debug)
549 fprint(2, "bad len %d at offset …
550 break;
551 }
552 if(de.ino == 0)
553 continue;
554 if(4+2+2+de.namlen > de.reclen){
555 if(debug)
556 fprint(2, "bad namelen %d at off…
557 break;
558 }
559 if(de.namlen == len && memcmp(de.name, name, len…
560 mkhandle(nh, de.ino);
561 blockput(b);
562 return Nfs3Ok;
563 }
564 }
565 blockput(b);
566 }
567 return Nfs3ErrNoEnt;
568 }
569
570 static Nfs3Status
571 ext2readdir(Fsys *fsys, SunAuthUnix *au, Nfs3Handle *h, u32int count, u6…
572 {
573 u32int nblock;
574 u32int i;
575 int off, outofspace;
576 uchar *data, *dp, *dep, *p, *ep, *ndp;
577 Dirent de;
578 Inode ino;
579 Block *b;
580 Ext2 *fs;
581 Nfs3Status ok;
582 Nfs3Entry e;
583 int want;
584
585 fs = fsys->priv;
586 if((ok = handle2ino(fs, h, nil, &ino)) != Nfs3Ok)
587 return ok;
588
589 if((ino.mode&IFMT) != IFDIR)
590 return Nfs3ErrNotDir;
591
592 if((ok = inoperm(&ino, au, AREAD)) != Nfs3Ok)
593 return ok;
594
595 if(debug) print("readdir cookie %#llux ino.size %#llux\n",
596 (u64int)cookie, (u64int)ino.size);
597
598 if(cookie >= ino.size){
599 *peof = 1;
600 *pcount = 0;
601 *pdata = 0;
602 return Nfs3Ok;
603 }
604
605 dp = malloc(count);
606 data = dp;
607 if(dp == nil)
608 return Nfs3ErrNoMem;
609 dep = dp+count;
610 *peof = 0;
611 nblock = (ino.size+fs->blocksize-1) / fs->blocksize;
612 i = cookie/fs->blocksize;
613 off = cookie%fs->blocksize;
614 outofspace = 0;
615 for(; i<nblock && !outofspace; i++, off=0){
616 if(i==nblock-1)
617 want = ino.size % fs->blocksize;
618 else
619 want = fs->blocksize;
620 b = ext2fileblock(fs, &ino, i, want);
621 if(b == nil)
622 continue;
623 p = b->data;
624 ep = p+b->len;
625 memset(&e, 0, sizeof e);
626 while(p < ep){
627 parsedirent(&de, p);
628 if(de.reclen == 0){
629 if(debug) fprint(2, "reclen 0 at offset …
630 break;
631 }
632 p += de.reclen;
633 if(p > ep){
634 if(debug) fprint(2, "reclen %d at offset…
635 break;
636 }
637 if(de.ino == 0){
638 if(debug) fprint(2, "zero inode\n");
639 continue;
640 }
641 if(4+2+2+de.namlen > de.reclen){
642 if(debug) fprint(2, "bad namlen %d recle…
643 break;
644 }
645 if(debug) print("%.*s/%d ", de.namlen, de.name, …
646 if(p-de.reclen - b->data < off)
647 continue;
648 e.fileid = de.ino;
649 e.name = de.name;
650 e.namelen = de.namlen;
651 e.cookie = (u64int)i*fs->blocksize + (p - b->dat…
652 if(debug) print("%.*s %#llux\n", utfnlen(e.name,…
653 if(nfs3entrypack(dp, dep, &ndp, &e) < 0){
654 outofspace = 1;
655 break;
656 }
657 dp = ndp;
658 }
659 blockput(b);
660 }
661 if(i==nblock && !outofspace)
662 *peof = 1;
663
664 *pcount = dp - data;
665 *pdata = data;
666 return Nfs3Ok;
667 }
668
669 static Nfs3Status
670 ext2readfile(Fsys *fsys, SunAuthUnix *au, Nfs3Handle *h, u32int count,
671 u64int offset, uchar **pdata, u32int *pcount, u1int *peof)
672 {
673 uchar *data;
674 Block *b;
675 Ext2 *fs;
676 int skip1, tot, want, fragcount;
677 Inode ino;
678 Nfs3Status ok;
679 u64int size;
680
681 fs = fsys->priv;
682 if((ok = handle2ino(fs, h, nil, &ino)) != Nfs3Ok)
683 return ok;
684
685 if((ok = inoperm(&ino, au, AREAD)) != Nfs3Ok)
686 return ok;
687
688 size = inosize(&ino);
689 if(offset >= size){
690 *pdata = 0;
691 *pcount = 0;
692 *peof = 1;
693 return Nfs3Ok;
694 }
695 if(offset+count > size)
696 count = size-offset;
697
698 data = malloc(count);
699 if(data == nil)
700 return Nfs3ErrNoMem;
701 memset(data, 0, count);
702
703 skip1 = offset%fs->blocksize;
704 offset -= skip1;
705 want = skip1+count;
706
707 /*
708 * have to read multiple blocks if we get asked for a big read.
709 * Linux NFS client assumes that if you ask for 8k and only get …
710 * back, the remaining 4k is zeros.
711 */
712 for(tot=0; tot<want; tot+=fragcount){
713 b = ext2fileblock(fs, &ino, (offset+tot)/fs->blocksize, …
714 fragcount = fs->blocksize;
715 if(b == nil)
716 continue;
717 if(tot+fragcount > want)
718 fragcount = want - tot;
719 if(tot == 0)
720 memmove(data, b->data+skip1, fragcount-skip1);
721 else
722 memmove(data+tot-skip1, b->data, fragcount);
723 blockput(b);
724 }
725 count = tot - skip1;
726
727 *peof = (offset+count == size);
728 *pcount = count;
729 *pdata = data;
730 return Nfs3Ok;
731 }
732
733 static Nfs3Status
734 ext2readlink(Fsys *fsys, SunAuthUnix *au, Nfs3Handle *h, char **link)
735 {
736 Ext2 *fs;
737 Nfs3Status ok;
738 int len;
739 Inode ino;
740 Block *b;
741
742 fs = fsys->priv;
743 if((ok = handle2ino(fs, h, nil, &ino)) != Nfs3Ok)
744 return ok;
745 if((ok = inoperm(&ino, au, AREAD)) != Nfs3Ok)
746 return ok;
747
748 if(ino.size > 1024)
749 return Nfs3ErrIo;
750 len = ino.size;
751
752 if(ino.nblock != 0){
753 /* BUG: assumes symlink fits in one block */
754 b = ext2fileblock(fs, &ino, 0, len);
755 if(b == nil)
756 return Nfs3ErrIo;
757 if(memchr(b->data, 0, len) != nil){
758 blockput(b);
759 return Nfs3ErrIo;
760 }
761 *link = malloc(len+1);
762 if(*link == 0){
763 blockput(b);
764 return Nfs3ErrNoMem;
765 }
766 memmove(*link, b->data, len);
767 (*link)[len] = 0;
768 blockput(b);
769 return Nfs3Ok;
770 }
771
772 if(len > sizeof ino.block)
773 return Nfs3ErrIo;
774
775 *link = malloc(len+1);
776 if(*link == 0)
777 return Nfs3ErrNoMem;
778 memmove(*link, ino.block, ino.size);
779 (*link)[len] = 0;
780 return Nfs3Ok;
781 }
782
783 /*
784 * Ext2 is always little-endian, even on big-endian machines.
785 */
786
787 static u32int
788 l32(uchar *p)
789 {
790 return p[0] | (p[1]<<8) | (p[2]<<16) | (p[3]<<24);
791 }
792
793 static u16int
794 l16(uchar *p)
795 {
796 return p[0] | (p[1]<<8);
797 }
798
799 static u8int
800 l8(uchar *p)
801 {
802 return p[0];
803 }
804
805 static void
806 parsedirent(Dirent *de, uchar *p)
807 {
808 de->ino = l32(p);
809 de->reclen = l16(p+4);
810 de->namlen = l8(p+6);
811 /* 1 byte pad */
812 de->name = (char*)p+8;
813 }
814
815 static void
816 parseinode(Inode *ino, uchar *p)
817 {
818 int i;
819
820 ino->mode = l16(p);
821 ino->uid = l16(p+2);
822 ino->size = l32(p+4);
823 ino->atime = l32(p+8);
824 ino->ctime = l32(p+12);
825 ino->mtime = l32(p+16);
826 ino->dtime = l32(p+20);
827 ino->gid = l16(p+24);
828 ino->nlink = l16(p+26);
829 ino->nblock = l32(p+28);
830 ino->flags = l32(p+32);
831 /* 4 byte osd1 */
832 for(i=0; i<NBLOCKS; i++)
833 ino->block[i] = l32(p+40+i*4);
834 ino->version = l32(p+100);
835 ino->fileacl = l32(p+104);
836 ino->diracl = l32(p+108);
837 ino->faddr = l32(p+112);
838 /* 12 byte osd2 */
839 }
840
841 static void
842 parsegroup(Group *g, uchar *p)
843 {
844 g->bitblock = l32(p);
845 g->inodebitblock = l32(p+4);
846 g->inodeaddr = l32(p+8);
847 g->freeblockscount = l16(p+12);
848 g->freeinodescount = l16(p+14);
849 g->useddirscount = l16(p+16);
850 /* 2 byte pad */
851 /* 12 byte reserved */
852 }
853
854 static void
855 parsesuper(Super *s, uchar *p)
856 {
857 s->ninode = l32(p);
858 s->nblock = l32(p+4);
859 s->rblockcount = l32(p+8);
860 s->freeblockcount = l32(p+12);
861 s->freeinodecount = l32(p+16);
862 s->firstdatablock = l32(p+20);
863 s->logblocksize = l32(p+24);
864 s->logfragsize = l32(p+28);
865 s->blockspergroup = l32(p+32);
866 s->fragpergroup = l32(p+36);
867 s->inospergroup = l32(p+40);
868 s->mtime = l32(p+44);
869 s->wtime = l32(p+48);
870 s->mntcount = l16(p+52);
871 s->maxmntcount = l16(p+54);
872 s->magic = l16(p+56);
873 s->state = l16(p+58);
874 s->errors = l16(p+60);
875 /* 2 byte pad */
876 s->lastcheck = l32(p+64);
877 s->checkinterval = l32(p+68);
878 s->creatoros = l32(p+72);
879 s->revlevel = l32(p+76);
880 s->defresuid = l16(p+80);
881 s->defresgid = l16(p+82);
882 s->firstino = l32(p+84);
883 s->inosize = l32(p+88);
884 s->blockgroupnr = l16(p+60);
885 /* 932 byte reserved */
886 }
You are viewing proxied material from mx1.adamsgaard.dk. The copyright of proxied material belongs to its original authors. Any comments or complaints in relation to proxied material should be directed to the original authors of the content concerned. Please see the disclaimer for more details.