This source file includes following definitions.
- read_inode
- block_map
- buf_read_file
- search_directory
- ufs_open
- ufs_close
- ufs_read
- ufs_write
- ufs_seek
- ufs_stat
- ufs_readdir
- ffs_oldfscompat
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66 #include <sys/param.h>
67 #include <sys/time.h>
68 #include <sys/stat.h>
69 #include <ufs/ffs/fs.h>
70 #include <ufs/ufs/dinode.h>
71 #include <ufs/ufs/dir.h>
72 #include <lib/libkern/libkern.h>
73
74 #include "stand.h"
75 #include "ufs.h"
76
77
78
79
80 struct file {
81 off_t f_seekp;
82 struct fs *f_fs;
83 struct ufs1_dinode f_di;
84 int f_nindir[NIADDR];
85
86
87 char *f_blk[NIADDR];
88
89 size_t f_blksize[NIADDR];
90
91 daddr_t f_blkno[NIADDR];
92 char *f_buf;
93 size_t f_buf_size;
94 daddr_t f_buf_blkno;
95 };
96
97 static int read_inode(ino_t, struct open_file *);
98 static int block_map(struct open_file *, daddr_t, daddr_t *);
99 static int buf_read_file(struct open_file *, char **, size_t *);
100 static int search_directory(char *, struct open_file *, ino_t *);
101 #ifdef COMPAT_UFS
102 static void ffs_oldfscompat(struct fs *);
103 #endif
104
105
106
107
108 static int
109 read_inode(ino_t inumber, struct open_file *f)
110 {
111 struct file *fp = (struct file *)f->f_fsdata;
112 struct fs *fs = fp->f_fs;
113 char *buf;
114 size_t rsize;
115 int rc;
116
117
118
119
120 buf = alloc(fs->fs_bsize);
121 twiddle();
122 rc = (f->f_dev->dv_strategy)(f->f_devdata, F_READ,
123 fsbtodb(fs, ino_to_fsba(fs, inumber)), fs->fs_bsize,
124 buf, &rsize);
125 if (rc)
126 goto out;
127 if (rsize != (size_t)fs->fs_bsize) {
128 rc = EIO;
129 goto out;
130 }
131
132 {
133 struct ufs1_dinode *dp;
134
135 dp = (struct ufs1_dinode *)buf;
136 fp->f_di = dp[ino_to_fsbo(fs, inumber)];
137 }
138
139
140
141
142 {
143 int level;
144
145 for (level = 0; level < NIADDR; level++)
146 fp->f_blkno[level] = -1;
147 fp->f_buf_blkno = -1;
148 fp->f_seekp = 0;
149 }
150 out:
151 free(buf, fs->fs_bsize);
152 return (rc);
153 }
154
155
156
157
158
159 static int
160 block_map(struct open_file *f, daddr_t file_block, daddr_t *disk_block_p)
161 {
162 struct file *fp = (struct file *)f->f_fsdata;
163 daddr_t ind_block_num, *ind_p;
164 struct fs *fs = fp->f_fs;
165 int level, idx, rc;
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190 if (file_block < NDADDR) {
191
192 *disk_block_p = fp->f_di.di_db[file_block];
193 return (0);
194 }
195
196 file_block -= NDADDR;
197
198
199
200
201
202
203
204 for (level = 0; level < NIADDR; level++) {
205 if (file_block < fp->f_nindir[level])
206 break;
207 file_block -= fp->f_nindir[level];
208 }
209 if (level == NIADDR) {
210
211 return (EFBIG);
212 }
213
214 ind_block_num = fp->f_di.di_ib[level];
215
216 for (; level >= 0; level--) {
217 if (ind_block_num == 0) {
218 *disk_block_p = 0;
219 return (0);
220 }
221
222 if (fp->f_blkno[level] != ind_block_num) {
223 if (fp->f_blk[level] == (char *)0)
224 fp->f_blk[level] =
225 alloc(fs->fs_bsize);
226 twiddle();
227 rc = (f->f_dev->dv_strategy)(f->f_devdata, F_READ,
228 fsbtodb(fp->f_fs, ind_block_num), fs->fs_bsize,
229 fp->f_blk[level], &fp->f_blksize[level]);
230 if (rc)
231 return (rc);
232 if (fp->f_blksize[level] != (size_t)fs->fs_bsize)
233 return (EIO);
234 fp->f_blkno[level] = ind_block_num;
235 }
236
237 ind_p = (daddr_t *)fp->f_blk[level];
238
239 if (level > 0) {
240 idx = file_block / fp->f_nindir[level - 1];
241 file_block %= fp->f_nindir[level - 1];
242 } else
243 idx = file_block;
244
245 ind_block_num = ind_p[idx];
246 }
247
248 *disk_block_p = ind_block_num;
249 return (0);
250 }
251
252
253
254
255
256 static int
257 buf_read_file(struct open_file *f, char **buf_p, size_t *size_p)
258 {
259 struct file *fp = (struct file *)f->f_fsdata;
260 struct fs *fs = fp->f_fs;
261 daddr_t file_block, disk_block;
262 size_t block_size;
263 long off;
264 int rc;
265
266 off = blkoff(fs, fp->f_seekp);
267 file_block = lblkno(fs, fp->f_seekp);
268 block_size = dblksize(fs, &fp->f_di, file_block);
269
270 if (file_block != fp->f_buf_blkno) {
271 rc = block_map(f, file_block, &disk_block);
272 if (rc)
273 return (rc);
274
275 if (fp->f_buf == (char *)0)
276 fp->f_buf = alloc(fs->fs_bsize);
277
278 if (disk_block == 0) {
279 bzero(fp->f_buf, block_size);
280 fp->f_buf_size = block_size;
281 } else {
282 twiddle();
283 rc = (f->f_dev->dv_strategy)(f->f_devdata, F_READ,
284 fsbtodb(fs, disk_block),
285 block_size, fp->f_buf, &fp->f_buf_size);
286 if (rc)
287 return (rc);
288 }
289
290 fp->f_buf_blkno = file_block;
291 }
292
293
294
295
296
297
298 *buf_p = fp->f_buf + off;
299 *size_p = block_size - off;
300
301
302
303
304 if (*size_p > fp->f_di.di_size - fp->f_seekp)
305 *size_p = fp->f_di.di_size - fp->f_seekp;
306
307 return (0);
308 }
309
310
311
312
313
314 static int
315 search_directory(char *name, struct open_file *f, ino_t *inumber_p)
316 {
317 struct file *fp = (struct file *)f->f_fsdata;
318 int namlen, length, rc;
319 struct direct *dp, *edp;
320 size_t buf_size;
321 char *buf;
322
323 length = strlen(name);
324
325 fp->f_seekp = 0;
326 while (fp->f_seekp < fp->f_di.di_size) {
327 rc = buf_read_file(f, &buf, &buf_size);
328 if (rc)
329 return (rc);
330
331 dp = (struct direct *)buf;
332 edp = (struct direct *)(buf + buf_size);
333 while (dp < edp) {
334 if (dp->d_ino == (ino_t)0)
335 goto next;
336 #if BYTE_ORDER == LITTLE_ENDIAN
337 if (fp->f_fs->fs_maxsymlinklen <= 0)
338 namlen = dp->d_type;
339 else
340 #endif
341 namlen = dp->d_namlen;
342 if (namlen == length &&
343 !strcmp(name, dp->d_name)) {
344
345 *inumber_p = dp->d_ino;
346 return (0);
347 }
348 next:
349 dp = (struct direct *)((char *)dp + dp->d_reclen);
350 }
351 fp->f_seekp += buf_size;
352 }
353 return (ENOENT);
354 }
355
356
357
358
359 int
360 ufs_open(char *path, struct open_file *f)
361 {
362 char namebuf[MAXPATHLEN+1], *cp, *ncp, *buf = NULL;
363 ino_t inumber, parent_inumber;
364 int rc, c, nlinks = 0;
365 struct file *fp;
366 size_t buf_size;
367 struct fs *fs;
368
369
370 fp = alloc(sizeof(struct file));
371 bzero(fp, sizeof(struct file));
372 f->f_fsdata = (void *)fp;
373
374
375 fs = alloc(SBSIZE);
376 fp->f_fs = fs;
377 twiddle();
378 rc = (f->f_dev->dv_strategy)(f->f_devdata, F_READ,
379 SBLOCK, SBSIZE, (char *)fs, &buf_size);
380 if (rc)
381 goto out;
382
383 if (buf_size != SBSIZE || fs->fs_magic != FS_MAGIC ||
384 fs->fs_bsize > MAXBSIZE || fs->fs_bsize < sizeof(struct fs)) {
385 rc = EINVAL;
386 goto out;
387 }
388 #ifdef COMPAT_UFS
389 ffs_oldfscompat(fs);
390 #endif
391
392
393
394
395 {
396 int mult;
397 int level;
398
399 mult = 1;
400 for (level = 0; level < NIADDR; level++) {
401 mult *= NINDIR(fs);
402 fp->f_nindir[level] = mult;
403 }
404 }
405
406 inumber = ROOTINO;
407 if ((rc = read_inode(inumber, f)) != 0)
408 goto out;
409
410 cp = path;
411 while (*cp) {
412
413
414
415
416 while (*cp == '/')
417 cp++;
418 if (*cp == '\0')
419 break;
420
421
422
423
424 if ((fp->f_di.di_mode & IFMT) != IFDIR) {
425 rc = ENOTDIR;
426 goto out;
427 }
428
429
430
431
432 {
433 int len = 0;
434
435 ncp = cp;
436 while ((c = *cp) != '\0' && c != '/') {
437 if (++len > MAXNAMLEN) {
438 rc = ENOENT;
439 goto out;
440 }
441 cp++;
442 }
443 *cp = '\0';
444 }
445
446
447
448
449
450
451 parent_inumber = inumber;
452 rc = search_directory(ncp, f, &inumber);
453 *cp = c;
454 if (rc)
455 goto out;
456
457
458
459
460 if ((rc = read_inode(inumber, f)) != 0)
461 goto out;
462
463
464
465
466 if ((fp->f_di.di_mode & IFMT) == IFLNK) {
467 int link_len = fp->f_di.di_size;
468 int len;
469
470 len = strlen(cp);
471
472 if (link_len + len > MAXPATHLEN ||
473 ++nlinks > MAXSYMLINKS) {
474 rc = ENOENT;
475 goto out;
476 }
477
478 bcopy(cp, &namebuf[link_len], len + 1);
479
480 if (link_len < fs->fs_maxsymlinklen) {
481 bcopy(fp->f_di.di_shortlink, namebuf,
482 (unsigned) link_len);
483 } else {
484
485
486
487 size_t buf_size;
488 daddr_t disk_block;
489 struct fs *fs = fp->f_fs;
490
491 if (!buf)
492 buf = alloc(fs->fs_bsize);
493 rc = block_map(f, (daddr_t)0, &disk_block);
494 if (rc)
495 goto out;
496
497 twiddle();
498 rc = (f->f_dev->dv_strategy)(f->f_devdata,
499 F_READ, fsbtodb(fs, disk_block),
500 fs->fs_bsize, buf, &buf_size);
501 if (rc)
502 goto out;
503
504 bcopy((char *)buf, namebuf, (unsigned)link_len);
505 }
506
507
508
509
510
511 cp = namebuf;
512 if (*cp != '/')
513 inumber = parent_inumber;
514 else
515 inumber = (ino_t)ROOTINO;
516
517 if ((rc = read_inode(inumber, f)) != 0)
518 goto out;
519 }
520 }
521
522
523
524
525 rc = 0;
526 out:
527 if (buf)
528 free(buf, fs->fs_bsize);
529 if (rc) {
530 free(fp->f_fs, SBSIZE);
531 free(fp, sizeof(struct file));
532 }
533 return (rc);
534 }
535
536 int
537 ufs_close(struct open_file *f)
538 {
539 struct file *fp = (struct file *)f->f_fsdata;
540 int level;
541
542 f->f_fsdata = (void *)0;
543 if (fp == (struct file *)0)
544 return (0);
545
546 for (level = 0; level < NIADDR; level++) {
547 if (fp->f_blk[level])
548 free(fp->f_blk[level], fp->f_fs->fs_bsize);
549 }
550 if (fp->f_buf)
551 free(fp->f_buf, fp->f_fs->fs_bsize);
552 free(fp->f_fs, SBSIZE);
553 free(fp, sizeof(struct file));
554 return (0);
555 }
556
557
558
559
560
561 int
562 ufs_read(struct open_file *f, void *start, size_t size, size_t *resid)
563 {
564 struct file *fp = (struct file *)f->f_fsdata;
565 char *buf, *addr = start;
566 size_t csize, buf_size;
567 int rc = 0;
568
569 while (size != 0) {
570 if (fp->f_seekp >= fp->f_di.di_size)
571 break;
572
573 rc = buf_read_file(f, &buf, &buf_size);
574 if (rc)
575 break;
576
577 csize = size;
578 if (csize > buf_size)
579 csize = buf_size;
580
581 bcopy(buf, addr, csize);
582
583 fp->f_seekp += csize;
584 addr += csize;
585 size -= csize;
586 }
587 if (resid)
588 *resid = size;
589 return (rc);
590 }
591
592
593
594
595 int
596 ufs_write(struct open_file *f, void *start, size_t size, size_t *resid)
597 {
598
599 return (EROFS);
600 }
601
602 off_t
603 ufs_seek(struct open_file *f, off_t offset, int where)
604 {
605 struct file *fp = (struct file *)f->f_fsdata;
606
607 switch (where) {
608 case SEEK_SET:
609 fp->f_seekp = offset;
610 break;
611 case SEEK_CUR:
612 fp->f_seekp += offset;
613 break;
614 case SEEK_END:
615 fp->f_seekp = fp->f_di.di_size - offset;
616 break;
617 default:
618 return (-1);
619 }
620 return (fp->f_seekp);
621 }
622
623 int
624 ufs_stat(struct open_file *f, struct stat *sb)
625 {
626 struct file *fp = (struct file *)f->f_fsdata;
627
628
629 sb->st_mode = fp->f_di.di_mode;
630 sb->st_uid = fp->f_di.di_uid;
631 sb->st_gid = fp->f_di.di_gid;
632 sb->st_size = fp->f_di.di_size;
633 return (0);
634 }
635
636 #ifndef NO_READDIR
637 int
638 ufs_readdir(struct open_file *f, char *name)
639 {
640 struct file *fp = (struct file *)f->f_fsdata;
641 struct direct *dp, *edp;
642 size_t buf_size;
643 int rc, namlen;
644 char *buf;
645
646 if (name == NULL)
647 fp->f_seekp = 0;
648 else {
649
650 if (fp->f_seekp >= fp->f_di.di_size) {
651 *name = '\0';
652 return -1;
653 }
654
655 do {
656 if ((rc = buf_read_file(f, &buf, &buf_size)) != 0)
657 return rc;
658
659 dp = (struct direct *)buf;
660 edp = (struct direct *)(buf + buf_size);
661 while (dp < edp && dp->d_ino == (ino_t)0)
662 dp = (struct direct *)((char *)dp + dp->d_reclen);
663 fp->f_seekp += buf_size -
664 ((u_int8_t *)edp - (u_int8_t *)dp);
665 } while (dp >= edp);
666
667 #if BYTE_ORDER == LITTLE_ENDIAN
668 if (fp->f_fs->fs_maxsymlinklen <= 0)
669 namlen = dp->d_type;
670 else
671 #endif
672 namlen = dp->d_namlen;
673 strncpy(name, dp->d_name, namlen + 1);
674
675 fp->f_seekp += dp->d_reclen;
676 }
677
678 return 0;
679 }
680 #endif
681
682 #ifdef COMPAT_UFS
683
684
685
686
687
688 static void
689 ffs_oldfscompat(struct fs *fs)
690 {
691 int i;
692
693 fs->fs_npsect = max(fs->fs_npsect, fs->fs_nsect);
694 fs->fs_interleave = max(fs->fs_interleave, 1);
695 if (fs->fs_postblformat == FS_42POSTBLFMT)
696 fs->fs_nrpos = 8;
697 if (fs->fs_inodefmt < FS_44INODEFMT) {
698 quad_t sizepb = fs->fs_bsize;
699
700 fs->fs_maxfilesize = fs->fs_bsize * NDADDR - 1;
701 for (i = 0; i < NIADDR; i++) {
702 sizepb *= NINDIR(fs);
703 fs->fs_maxfilesize += sizepb;
704 }
705 fs->fs_qbmask = ~fs->fs_bmask;
706 fs->fs_qfmask = ~fs->fs_fmask;
707 }
708 }
709 #endif