Commit | Line | Data |
---|---|---|
845dfc67 AT |
1 | #include "fs.h" |
2 | ||
3 | /* NB: not portable! assumes little endian (and probably other things) */ | |
4 | ||
5 | #define NIPB (512/sizeof(DInode)) | |
6 | #define NDPB (512/sizeof(Dirent)) | |
7 | ||
8 | /* v6 superblock */ | |
9 | typedef struct Filsys Filsys; | |
10 | struct Filsys | |
11 | { | |
12 | int16 s_isize; /* size in blocks of I list */ | |
13 | int16 s_fsize; /* size in blocks of entire volume */ | |
14 | int16 s_nfree; /* number of in core free blocks (0-100) */ | |
15 | int16 s_free[100]; /* in core free blocks */ | |
16 | int16 s_ninode; /* number of in core I nodes (0-100) */ | |
17 | int16 s_inode[100]; /* in core free I nodes */ | |
18 | uint8 s_flock; /* lock during free list manipulation */ | |
19 | uint8 s_ilock; /* lock during I list manipulation */ | |
20 | uint8 s_fmod; /* super block modified flag */ | |
21 | uint8 s_ronly; /* mounted read-only flag */ | |
22 | int16 s_time[2]; /* current date of last update */ | |
23 | int16 pad[48]; | |
24 | }; | |
25 | ||
26 | /* v6 and PWB/1.0 disk inode */ | |
27 | struct DInode | |
28 | { | |
29 | uint16 i_mode; | |
30 | int8 i_nlink; | |
31 | uint8 i_uid; | |
32 | uint8 i_gid; | |
33 | uint8 i_size0; | |
34 | uint16 i_size1; | |
35 | uint16 i_addr[8]; | |
36 | uint16 i_atime[2]; | |
37 | uint16 i_mtime[2]; | |
38 | }; | |
39 | ||
40 | /* modes */ | |
41 | #define IALLOC 0100000 | |
42 | #define IFMT 060000 | |
43 | #define IFDIR 040000 | |
44 | #define IFCHR 020000 | |
45 | #define IFBLK 060000 | |
46 | #define ILARG 010000 | |
47 | #define ISUID 04000 | |
48 | #define ISGID 02000 | |
49 | #define ISVTX 01000 | |
50 | #define IREAD 0400 | |
51 | #define IWRITE 0200 | |
52 | #define IEXEC 0100 | |
53 | ||
54 | typedef struct Dirent Dirent; | |
55 | struct Dirent | |
56 | { | |
57 | uint16 inode; | |
58 | char name[14]; | |
59 | }; | |
60 | ||
61 | Filsys *filesys; | |
62 | DInode *dinodes; | |
63 | Inode *inodes; | |
64 | ||
65 | #define ISIZE(ip) ((ip)->i_size0<<16 | (ip)->i_size1) | |
66 | int32 | |
67 | pdplong(void *p) | |
68 | { | |
69 | uint8 *up; | |
70 | uint32 ui; | |
71 | up = p; | |
72 | ui = up[1]<<24 | up[0]<<16 | up[3]<<8 | up[2]; | |
73 | return *(int32*)&ui; | |
74 | } | |
75 | ||
76 | void | |
77 | setpdplong(void *p, int32 i) | |
78 | { | |
79 | uint8 *up; | |
80 | uint32 ui; | |
81 | up = p; | |
82 | ui = *(uint32*)&i; | |
83 | up[1] = ui>>24; | |
84 | up[0] = ui>>16; | |
85 | up[3] = ui>>8; | |
86 | up[2] = ui; | |
87 | } | |
88 | ||
89 | void | |
90 | setint24(void *p, int32 i) | |
91 | { | |
92 | uint8 *up; | |
93 | uint32 ui; | |
94 | up = p; | |
95 | ui = *(uint32*)&i; | |
96 | up[0] = ui>>16; | |
97 | up[2] = ui>>8; | |
98 | up[1] = ui; | |
99 | } | |
100 | ||
101 | void *bget(int n) { return &fsdata[n*512]; } | |
102 | ||
103 | /* returns a free block or 0 */ | |
104 | int | |
105 | balloc(void) | |
106 | { | |
107 | int i, bno; | |
108 | uint16 *b; | |
109 | filesys->s_nfree--; | |
110 | if(filesys->s_nfree < 0 || filesys->s_nfree >= 100){ | |
111 | printf("bad free count\n"); | |
112 | return 0; | |
113 | } | |
114 | bno = filesys->s_free[filesys->s_nfree]; | |
115 | filesys->s_free[filesys->s_nfree] = 0; | |
116 | if(bno == 0) | |
117 | return 0; | |
118 | if(bno < filesys->s_isize+2 || bno >= filesys->s_fsize){ | |
119 | printf("bad free block (%d)\n", bno); | |
120 | return 0; | |
121 | } | |
122 | if(filesys->s_nfree <= 0){ | |
123 | b = bget(bno); | |
124 | filesys->s_nfree = b[0]; | |
125 | for(i = 0; i < 100; i++) | |
126 | filesys->s_free[i] = b[i+1]; | |
127 | } | |
128 | return bno; | |
129 | } | |
130 | ||
131 | void | |
132 | bfree(int bno) | |
133 | { | |
134 | int i; | |
135 | uint16 *b; | |
136 | ||
137 | printf("freeing block\n"); | |
138 | if(filesys->s_nfree >= 100){ | |
139 | b = bget(bno); | |
140 | b[0] = filesys->s_nfree; | |
141 | for(i = 0; i < 100; i++) | |
142 | b[i+1] = filesys->s_free[i]; | |
143 | filesys->s_nfree = 0; | |
144 | } | |
145 | filesys->s_free[filesys->s_nfree] = bno; | |
146 | filesys->s_nfree++; | |
147 | } | |
148 | ||
149 | int | |
150 | zalloc(void) | |
151 | { | |
152 | int bn; | |
153 | bn = balloc(); | |
154 | if(bn) | |
155 | memset(bget(bn), 0, 512); | |
156 | return bn; | |
157 | } | |
158 | ||
159 | /* returns a free inode or 0 */ | |
160 | int | |
161 | ialloc(void) | |
162 | { | |
163 | int ino; | |
164 | DInode *ip; | |
165 | int i, j; | |
166 | ||
167 | if(filesys->s_ninode <= 0){ | |
168 | ino = 0; | |
169 | for(i = 0; i < filesys->s_isize; i++) | |
170 | for(j = 0; j < NIPB; j++){ | |
171 | ino++; | |
172 | ip = &dinodes[ino]; | |
173 | if(ip->i_mode) | |
174 | continue; | |
175 | filesys->s_inode[filesys->s_ninode++] = ino; | |
176 | if(filesys->s_ninode >= 100) | |
177 | goto brk; | |
178 | } | |
179 | } | |
180 | brk: | |
181 | if(filesys->s_ninode > 0){ | |
182 | ino = filesys->s_inode[--filesys->s_ninode]; | |
183 | return ino; | |
184 | } | |
185 | return 0; | |
186 | } | |
187 | ||
188 | void | |
189 | ifree(int ino) | |
190 | { | |
191 | printf("freeing inode\n"); | |
192 | if(filesys->s_ninode >= 100) | |
193 | return; | |
194 | filesys->s_inode[filesys->s_ninode++] = ino; | |
195 | } | |
196 | ||
197 | void | |
198 | itrunc(DInode *ip) | |
199 | { | |
200 | int i; | |
201 | uint16 *bp, *cp, *dp, *ep; | |
202 | ||
203 | if(ip->i_mode & (IFCHR|IFBLK)) | |
204 | return; | |
205 | for(i = 7; i >= 0; i--) | |
206 | if(ip->i_addr[i]){ | |
207 | if(ip->i_mode & ILARG){ | |
208 | bp = bget(ip->i_addr[i]); | |
209 | for(cp = &bp[255]; cp >= bp; cp--) | |
210 | if(*cp){ | |
211 | if(i == 7){ | |
212 | dp = bget(*cp); | |
213 | for(ep = &dp[255]; ep >= dp; ep--) | |
214 | if(*ep) | |
215 | bfree(*ep); | |
216 | } | |
217 | bfree(*cp); | |
218 | } | |
219 | } | |
220 | bfree(ip->i_addr[i]); | |
221 | ip->i_addr[i] = 0; | |
222 | } | |
223 | ip->i_mode &= ~ILARG; | |
224 | setint24(&ip->i_size0, 0); | |
225 | } | |
226 | ||
227 | void | |
228 | dcheck(void) | |
229 | { | |
230 | Filsys fs; | |
231 | int i; | |
232 | ||
233 | fs = *filesys; | |
234 | i = 0; | |
235 | while(balloc()) | |
236 | i++; | |
237 | printf("free: %d\n", i); | |
238 | *filesys = fs; | |
239 | } | |
240 | ||
241 | int | |
242 | bmap(DInode *ip, uint bn) | |
243 | { | |
244 | uint i; | |
245 | uint nb; | |
246 | uint16 *b; | |
247 | ||
248 | if(bn & ~077777) | |
249 | return 0; | |
250 | ||
251 | if((ip->i_mode & ILARG) == 0){ | |
252 | ||
253 | /* small file, direct fetch */ | |
254 | ||
255 | if(bn & ~7){ | |
256 | /* convert to large */ | |
257 | nb = zalloc(); | |
258 | if(nb == 0) | |
259 | return 0; | |
260 | b = bget(nb); | |
261 | for(i = 0; i < 8; i++){ | |
262 | b[i] = ip->i_addr[i]; | |
263 | ip->i_addr[i] = 0; | |
264 | } | |
265 | ip->i_addr[0] = nb; | |
266 | ip->i_mode |= ILARG; | |
267 | goto large; | |
268 | } | |
269 | ||
270 | nb = ip->i_addr[bn]; | |
271 | if(nb == 0){ | |
272 | nb = zalloc(); | |
273 | if(nb == 0) | |
274 | return 0; | |
275 | ip->i_addr[bn] = nb; | |
276 | } | |
277 | return nb; | |
278 | } | |
279 | ||
280 | /* large file, 7 indirect blocks */ | |
281 | ||
282 | large: | |
283 | i = bn>>8; | |
284 | if(i > 7) | |
285 | i = 7; | |
286 | nb = ip->i_addr[i]; | |
287 | if(nb == 0){ | |
288 | nb = zalloc(); | |
289 | if(nb == 0) | |
290 | return 0; | |
291 | ip->i_addr[bn] = nb; | |
292 | } | |
293 | b = bget(nb); | |
294 | ||
295 | if(i == 7){ | |
296 | ||
297 | /* huge file, double indirect last block */ | |
298 | ||
299 | i = (bn>>8) - 7; | |
300 | nb = b[i&0377]; | |
301 | if(nb == 0){ | |
302 | nb = zalloc(); | |
303 | if(nb == 0) | |
304 | return 0; | |
305 | b[i&0377] = nb; | |
306 | } | |
307 | b = bget(nb); | |
308 | } | |
309 | ||
310 | nb = b[bn&0377]; | |
311 | return nb; | |
312 | }; | |
313 | ||
314 | uint8* | |
315 | getblock(DInode *ip, uint bn) | |
316 | { | |
317 | bn = bmap(ip, bn); | |
318 | if(bn == 0) | |
319 | return nil; | |
320 | return bget(bn); | |
321 | } | |
322 | ||
323 | void | |
324 | fs_init(void) | |
325 | { | |
326 | int i, ni; | |
327 | ||
328 | filesys = bget(1); | |
329 | dinodes = (DInode*)bget(2) - 1; | |
330 | ni = filesys->s_isize*NIPB + 1; | |
331 | inodes = malloc(ni*sizeof(Inode)); | |
332 | for(i = 0; i < ni; i++){ | |
333 | inodes[i].ino = i; | |
334 | inodes[i].count = 0; | |
335 | inodes[i].i = &dinodes[i]; | |
336 | } | |
337 | } | |
338 | ||
339 | int | |
340 | fs_open(uint ino, int flags) | |
341 | { | |
342 | DInode *ip; | |
343 | ||
344 | ip = &dinodes[ino]; | |
345 | if((ip->i_mode & IFMT) == IFDIR) | |
346 | return EISDIR; | |
347 | // if((flags & 3) != O_RDONLY) | |
348 | // return EACCES; | |
349 | return 0; | |
350 | } | |
351 | ||
352 | int | |
353 | fs_stat(uint ino, struct stat *stbuf) | |
354 | { | |
355 | DInode *ip; | |
356 | ip = &dinodes[ino]; | |
357 | ||
358 | stbuf->st_ino = ino; | |
359 | if((ip->i_mode & IFMT) == IFDIR) | |
360 | stbuf->st_mode = S_IFDIR; | |
361 | else if((ip->i_mode & IFMT) == IFCHR) | |
362 | stbuf->st_mode = S_IFCHR; | |
363 | else if((ip->i_mode & IFMT) == IFBLK) | |
364 | stbuf->st_mode = S_IFBLK; | |
365 | else | |
366 | stbuf->st_mode = S_IFREG; | |
367 | stbuf->st_mode |= ip->i_mode & 0777; | |
368 | stbuf->st_nlink = ip->i_nlink; | |
369 | stbuf->st_size = ISIZE(ip); | |
370 | if((ip->i_mode & IFMT) == IFCHR || | |
371 | (ip->i_mode & IFMT) == IFBLK) | |
372 | stbuf->st_rdev = makedev(ip->i_addr[0]>>8 & 0xFF, ip->i_addr[0]&0xFF); | |
373 | stbuf->st_uid = ip->i_uid; | |
374 | stbuf->st_gid = ip->i_gid; | |
375 | stbuf->st_atime = pdplong(ip->i_atime); | |
376 | stbuf->st_mtime = pdplong(ip->i_mtime); | |
377 | ||
378 | return 0; | |
379 | } | |
380 | ||
381 | int | |
382 | fs_atime(uint ino, int32 time) | |
383 | { | |
384 | DInode *ip; | |
385 | ip = &dinodes[ino]; | |
386 | setpdplong(ip->i_atime, time); | |
387 | return 0; | |
388 | } | |
389 | ||
390 | int | |
391 | fs_mtime(uint ino, int32 time) | |
392 | { | |
393 | DInode *ip; | |
394 | ip = &dinodes[ino]; | |
395 | setpdplong(ip->i_mtime, time); | |
396 | return 0; | |
397 | } | |
398 | ||
399 | int | |
400 | fs_uid(uint ino, int32 uid) | |
401 | { | |
402 | DInode *ip; | |
403 | ip = &dinodes[ino]; | |
404 | ip->i_uid = uid; | |
405 | return 0; | |
406 | } | |
407 | ||
408 | int | |
409 | fs_gid(uint ino, int32 gid) | |
410 | { | |
411 | DInode *ip; | |
412 | ip = &dinodes[ino]; | |
413 | ip->i_gid = gid; | |
414 | return 0; | |
415 | } | |
416 | ||
417 | int | |
418 | fs_read(uint ino, void *vdst, int offset, int len) | |
419 | { | |
420 | DInode *ip; | |
421 | int bn; | |
422 | uint8 *b; | |
423 | int isize; | |
424 | int n; | |
425 | uint8 *dst; | |
426 | ||
427 | ip = &dinodes[ino]; | |
428 | dst = vdst; | |
429 | isize = ISIZE(ip); | |
430 | if(offset + len > isize) | |
431 | len = isize - offset; | |
432 | if(len <= 0) | |
433 | return 0; | |
434 | ||
435 | bn = offset/512; | |
436 | offset %= 512; | |
437 | ||
438 | b = getblock(ip, bn); | |
439 | if(b == nil) | |
440 | /* TODO: handle gracefully */ | |
441 | panic("no block"); | |
442 | ||
443 | if(len < 512-offset){ | |
444 | /* smaller than block */ | |
445 | memcpy(dst, b+offset, len); | |
446 | return len; | |
447 | } | |
448 | ||
449 | /* at least one block */ | |
450 | memcpy(dst, b+offset, 512-offset); | |
451 | n = 512-offset; | |
452 | len -= n; | |
453 | dst += n; | |
454 | while(len > 0){ | |
455 | bn++; | |
456 | b = getblock(ip, bn); | |
457 | if(b == nil) | |
458 | /* TODO: handle gracefully */ | |
459 | panic("no block"); | |
460 | memcpy(dst, b, len > 512 ? 512 : len); | |
461 | n += len > 512 ? 512 : len; | |
462 | len -= 512; | |
463 | dst += 512; | |
464 | } | |
465 | return n; | |
466 | } | |
467 | ||
468 | int | |
469 | fs_write(uint ino, void *vsrc, int offset, int len) | |
470 | { | |
471 | DInode *ip; | |
472 | int bn; | |
473 | uint8 *b; | |
474 | int n; | |
475 | int32 size; | |
476 | uint8 *src; | |
477 | ||
478 | ip = &dinodes[ino]; | |
479 | src = vsrc; | |
480 | size = ISIZE(ip); | |
481 | // TODO: make this better: | |
482 | if(offset+len > size) | |
483 | setint24(&ip->i_size0, offset+len); | |
484 | if(len <= 0) | |
485 | return 0; | |
486 | ||
487 | bn = offset/512; | |
488 | offset %= 512; | |
489 | ||
490 | b = getblock(ip, bn); | |
491 | if(b == nil) | |
492 | /* TODO: handle gracefully */ | |
493 | panic("no block"); | |
494 | ||
495 | if(len < 512-offset){ | |
496 | /* smaller than block */ | |
497 | memcpy(b+offset, src, len); | |
498 | return len; | |
499 | } | |
500 | ||
501 | /* at least one block */ | |
502 | memcpy(b+offset, src, 512-offset); | |
503 | n = 512-offset; | |
504 | len -= n; | |
505 | src += n; | |
506 | while(len > 0){ | |
507 | bn++; | |
508 | b = getblock(ip, bn); | |
509 | if(b == nil) | |
510 | /* TODO: handle gracefully */ | |
511 | panic("no block"); | |
512 | memcpy(b, src, len > 512 ? 512 : len); | |
513 | n += len > 512 ? 512 : len; | |
514 | len -= 512; | |
515 | src += 512; | |
516 | } | |
517 | return n; | |
518 | } | |
519 | ||
520 | /* return a malloc'd array of dirents for a given inode */ | |
521 | struct dirent* | |
522 | fs_readdir(uint ino) | |
523 | { | |
524 | DInode *ip; | |
525 | struct dirent *des, *dp; | |
526 | int size; | |
527 | int ndes; | |
528 | Dirent de; | |
529 | int offset; | |
530 | ||
531 | ip = &dinodes[ino]; | |
532 | if((ip->i_mode & IFDIR) == 0) | |
533 | return nil; | |
534 | ||
535 | size = ISIZE(ip); | |
536 | ndes = size/sizeof(Dirent); | |
537 | des = malloc((ndes+1)*sizeof(struct dirent)); | |
538 | ||
539 | offset = 0; | |
540 | dp = des; | |
541 | while(fs_read(ino, &de, offset, sizeof(Dirent)) == sizeof(Dirent)){ | |
542 | if(de.inode){ | |
543 | dp->d_ino = de.inode; | |
544 | memcpy(dp->d_name, de.name, 14); | |
545 | dp->d_name[14] = '\0'; | |
546 | dp++; | |
547 | } | |
548 | offset += sizeof(Dirent); | |
549 | } | |
550 | dp->d_ino = 0; | |
551 | dp->d_name[0] = '\0'; | |
552 | ||
553 | return des; | |
554 | } | |
555 | ||
556 | static int | |
557 | lookup(uint ino, const char *name, Dirent *de) | |
558 | { | |
559 | int offset; | |
560 | ||
561 | assert(de); | |
562 | offset = 0; | |
563 | while(fs_read(ino, de, offset, sizeof(Dirent)) == sizeof(Dirent)){ | |
564 | if(de->inode) | |
565 | if(strcmp(de->name, name) == 0) | |
566 | return offset; | |
567 | offset += sizeof(Dirent); | |
568 | } | |
569 | memset(de, 0, sizeof(Dirent)); | |
570 | return -1; | |
571 | } | |
572 | ||
573 | static int | |
574 | allocdirent(uint ino) | |
575 | { | |
576 | Dirent de; | |
577 | int offset; | |
578 | ||
579 | offset = 0; | |
580 | while(fs_read(ino, &de, offset, sizeof(Dirent)) == sizeof(Dirent)){ | |
581 | if(de.inode == 0) | |
582 | return offset; | |
583 | offset += sizeof(Dirent); | |
584 | } | |
585 | memset(&de, 0, sizeof(Dirent)); | |
586 | fs_write(ino, &de, offset, sizeof(Dirent)); | |
587 | return offset; | |
588 | } | |
589 | ||
590 | int | |
591 | fs_link(uint ino, uint parent, const char *name) | |
592 | { | |
593 | Dirent de; | |
594 | int offset; | |
595 | ||
596 | offset = allocdirent(parent); | |
597 | /* TODO: can't happen right now */ | |
598 | if(offset < 0) | |
599 | return ENOSPC; | |
600 | memset(&de, 0, sizeof(Dirent)); | |
601 | de.inode = ino; | |
602 | strncpy(de.name, name, 14); | |
603 | fs_write(parent, &de, offset, sizeof(de)); | |
604 | fs_mtime(ino, time(nil)); | |
605 | fs_atime(ino, time(nil)); | |
606 | dinodes[ino].i_nlink++; | |
607 | ||
608 | return 0; | |
609 | } | |
610 | ||
611 | int | |
612 | fs_mknod(uint parent, const char *name, mode_t mode, dev_t rdev, uint *newino) | |
613 | { | |
614 | uint ino; | |
615 | DInode *ip, *ipp; | |
616 | int offset; | |
617 | Dirent de; | |
618 | ||
619 | USED(rdev); | |
620 | // TODO: support more files | |
621 | if((mode & S_IFMT) != S_IFREG && | |
622 | (mode & S_IFMT) != S_IFDIR) | |
623 | return EACCES; | |
624 | ||
625 | ino = ialloc(); | |
626 | if(ino == 0) | |
627 | return ENOSPC; | |
628 | ip = &dinodes[ino]; | |
629 | memset(ip, 0, sizeof(DInode)); | |
630 | ip->i_mode = (mode&0777) | IALLOC; | |
631 | if((mode & S_IFMT) == S_IFDIR) | |
632 | ip->i_mode |= IFDIR; | |
633 | else if((mode & S_IFMT) == S_IFCHR) | |
634 | ip->i_mode |= IFCHR; | |
635 | else if((mode & S_IFMT) == S_IFBLK) | |
636 | ip->i_mode |= IFBLK; | |
637 | if((ip->i_mode & IFMT) == IFCHR || | |
638 | (ip->i_mode & IFMT) == IFBLK) | |
639 | ip->i_addr[0] = | |
640 | major(rdev)<<8 & 0xFF00 | minor(rdev) & 0xFF; | |
641 | ||
642 | ipp = &dinodes[parent]; | |
643 | assert((ipp->i_mode & IFMT) == IFDIR); | |
644 | ||
645 | offset = allocdirent(parent); | |
646 | /* TODO: can't happen right now */ | |
647 | if(offset < 0){ | |
648 | ip->i_mode = 0; | |
649 | return ENOSPC; | |
650 | } | |
651 | ||
652 | ip->i_nlink = 1; | |
653 | memset(&de, 0, sizeof(Dirent)); | |
654 | de.inode = ino; | |
655 | strncpy(de.name, name, 14); | |
656 | fs_write(parent, &de, offset, sizeof(de)); | |
657 | fs_mtime(ino, time(nil)); | |
658 | fs_atime(ino, time(nil)); | |
659 | ||
660 | if(newino) | |
661 | *newino = ino; | |
662 | printf("making node %s %o\n", name, mode); | |
663 | return 0; | |
664 | } | |
665 | ||
666 | int | |
667 | fs_mkdir(uint parent, const char *name, mode_t mode) | |
668 | { | |
669 | int bn; | |
670 | int ino; | |
671 | int ret; | |
672 | DInode *ip; | |
673 | Dirent des[2]; | |
674 | ||
675 | /* Make sure we have space */ | |
676 | bn = balloc(); | |
677 | if(bn == 0) | |
678 | return ENOSPC; | |
679 | ret = fs_mknod(parent, name, mode | S_IFDIR, 0, &ino); | |
680 | if(ret){ | |
681 | bfree(bn); | |
682 | return ret; | |
683 | } | |
684 | ip = &dinodes[ino]; | |
685 | ip->i_addr[0] = bn; | |
686 | ||
687 | memset(des, 0, 2*sizeof(Dirent)); | |
688 | des[0].inode = ino; | |
689 | strcpy(des[0].name, "."); | |
690 | ip->i_nlink++; | |
691 | des[1].inode = parent; | |
692 | strcpy(des[1].name, ".."); | |
693 | dinodes[parent].i_nlink++; | |
694 | fs_write(ino, des, 0, 2*sizeof(Dirent)); | |
695 | return 0; | |
696 | } | |
697 | ||
698 | Inode* | |
699 | fs_iget(uint ino) | |
700 | { | |
701 | Inode *ip; | |
702 | ip = &inodes[ino]; | |
703 | ip->count++; | |
704 | return ip; | |
705 | } | |
706 | ||
707 | void | |
708 | fs_iput(Inode *ip) | |
709 | { | |
710 | assert(ip->count > 0); | |
711 | ip->count--; | |
712 | if(ip->count == 0) | |
713 | if(ip->i->i_nlink <= 0){ | |
714 | printf("truncating inode %d (%d)\n", ip->ino, ip->i->i_nlink); | |
715 | itrunc(ip->i); | |
716 | ip->i->i_mode = 0; | |
717 | ifree(ip->ino); | |
718 | } | |
719 | } | |
720 | ||
721 | int | |
722 | fs_unlink(uint parent, const char *name) | |
723 | { | |
724 | Dirent de; | |
725 | int offset; | |
726 | ||
727 | offset = lookup(parent, name, &de); | |
728 | if(offset < 0) | |
729 | /* shouldn't happen */ | |
730 | return 1; | |
731 | dinodes[de.inode].i_nlink--; | |
732 | ||
733 | de.inode = 0; | |
734 | fs_write(parent, &de, offset, sizeof(Dirent)); | |
735 | return 0; | |
736 | } |