ufs.c revision 1.56 1 /* $NetBSD: ufs.c,v 1.56 2011/12/25 06:09:08 tsutsui Exp $ */
2
3 /*-
4 * Copyright (c) 1993
5 * The Regents of the University of California. All rights reserved.
6 *
7 * This code is derived from software contributed to Berkeley by
8 * The Mach Operating System project at Carnegie-Mellon University.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. Neither the name of the University nor the names of its contributors
19 * may be used to endorse or promote products derived from this software
20 * without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * SUCH DAMAGE.
33 *
34 *
35 * Copyright (c) 1990, 1991 Carnegie Mellon University
36 * All Rights Reserved.
37 *
38 * Author: David Golub
39 *
40 * Permission to use, copy, modify and distribute this software and its
41 * documentation is hereby granted, provided that both the copyright
42 * notice and this permission notice appear in all copies of the
43 * software, derivative works or modified versions, and any portions
44 * thereof, and that both notices appear in supporting documentation.
45 *
46 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
47 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
48 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
49 *
50 * Carnegie Mellon requests users of this software to return to
51 *
52 * Software Distribution Coordinator or Software.Distribution (at) CS.CMU.EDU
53 * School of Computer Science
54 * Carnegie Mellon University
55 * Pittsburgh PA 15213-3890
56 *
57 * any improvements or extensions that they make and grant Carnegie the
58 * rights to redistribute these changes.
59 */
60
61 /*
62 * Stand-alone file reading package for UFS and LFS filesystems.
63 */
64
65 #include <sys/param.h>
66 #include <sys/time.h>
67 #include <ufs/ufs/dinode.h>
68 #include <ufs/ufs/dir.h>
69 #ifdef LIBSA_LFS
70 #include <sys/queue.h>
71 #include <sys/condvar.h>
72 #include <sys/mount.h> /* XXX for MNAMELEN */
73 #include <ufs/lfs/lfs.h>
74 #else
75 #include <ufs/ffs/fs.h>
76 #endif
77 #ifdef _STANDALONE
78 #include <lib/libkern/libkern.h>
79 #else
80 #include <string.h>
81 #endif
82
83 #include "stand.h"
84 #ifdef LIBSA_LFS
85 #include "lfs.h"
86 #else
87 #include "ufs.h"
88 #endif
89
90 /* If this file is compiled by itself, build ufs (aka ffsv1) support */
91 #if !defined(LIBSA_FFSv2) && !defined(LIBSA_LFS)
92 #define LIBSA_FFSv1
93 #endif
94
95 #if defined(LIBSA_FS_SINGLECOMPONENT) && !defined(LIBSA_NO_FS_SYMLINK)
96 #define LIBSA_NO_FS_SYMLINK
97 #endif
98 #if defined(COMPAT_UFS) && defined(LIBSA_NO_COMPAT_UFS)
99 #undef COMPAT_UFS
100 #endif
101
102 #ifdef LIBSA_LFS
103 /*
104 * In-core LFS superblock. This exists only to placate the macros in lfs.h,
105 */
106 struct fs {
107 struct dlfs lfs_dlfs;
108 };
109 #define fs_magic lfs_magic
110 #define fs_maxsymlinklen lfs_maxsymlinklen
111
112 #define FS_MAGIC LFS_MAGIC
113 #define SBLOCKSIZE LFS_SBPAD
114 #define SBLOCKOFFSET LFS_LABELPAD
115 #else
116 /* NB ufs2 doesn't use the common suberblock code... */
117 #define FS_MAGIC FS_UFS1_MAGIC
118 #define SBLOCKOFFSET SBLOCK_UFS1
119 #endif
120
121 #if defined(LIBSA_NO_TWIDDLE)
122 #define twiddle()
123 #endif
124
125 #undef cgstart
126 #if defined(LIBSA_FFSv2)
127 #define cgstart(fc, c) cgstart_ufs2((fs), (c))
128 #else
129 #define cgstart(fc, c) cgstart_ufs1((fs), (c))
130 #endif
131
132 #ifndef ufs_dinode
133 #define ufs_dinode ufs1_dinode
134 #endif
135 #ifndef indp_t
136 #define indp_t int32_t
137 #endif
138 typedef uint32_t ino32_t;
139 #ifndef FSBTODB
140 #define FSBTODB(fs, indp) fsbtodb(fs, indp)
141 #endif
142
143 /*
144 * To avoid having a lot of filesystem-block sized buffers lurking (which
145 * could be 32k) we only keep a few entries of the indirect block map.
146 * With 8k blocks, 2^8 blocks is ~500k so we reread the indirect block
147 * ~13 times pulling in a 6M kernel.
148 * The cache size must be smaller than the smallest filesystem block,
149 * so LN2_IND_CACHE_SZ <= 9 (UFS2 and 4k blocks).
150 */
151 #define LN2_IND_CACHE_SZ 6
152 #define IND_CACHE_SZ (1 << LN2_IND_CACHE_SZ)
153 #define IND_CACHE_MASK (IND_CACHE_SZ - 1)
154
155 /*
156 * In-core open file.
157 */
158 struct file {
159 off_t f_seekp; /* seek pointer */
160 struct fs *f_fs; /* pointer to super-block */
161 struct ufs_dinode f_di; /* copy of on-disk inode */
162 uint f_nishift; /* for blocks in indirect block */
163 indp_t f_ind_cache_block;
164 indp_t f_ind_cache[IND_CACHE_SZ];
165
166 char *f_buf; /* buffer for data block */
167 size_t f_buf_size; /* size of data block */
168 daddr_t f_buf_blkno; /* block number of data block */
169 };
170
171 static int read_inode(ino32_t, struct open_file *);
172 static int block_map(struct open_file *, indp_t, indp_t *);
173 static int buf_read_file(struct open_file *, char **, size_t *);
174 static int search_directory(const char *, int, struct open_file *, ino32_t *);
175 #ifdef LIBSA_FFSv1
176 static void ffs_oldfscompat(struct fs *);
177 #endif
178 #ifdef LIBSA_FFSv2
179 static int ffs_find_superblock(struct open_file *, struct fs *);
180 #endif
181
182 #if defined(LIBSA_ENABLE_LS_OP)
183
184 #define NELEM(x) (sizeof (x) / sizeof(*x))
185
186 typedef struct entry_t entry_t;
187 struct entry_t {
188 entry_t *e_next;
189 ino32_t e_ino;
190 uint8_t e_type;
191 char e_name[1];
192 };
193
194 static const char *const typestr[] = {
195 "unknown",
196 "FIFO",
197 "CHR",
198 0,
199 "DIR",
200 0,
201 "BLK",
202 0,
203 "REG",
204 0,
205 "LNK",
206 0,
207 "SOCK",
208 0,
209 "WHT"
210 };
211
212 static int
213 fn_match(const char *fname, const char *pattern)
214 {
215 char fc, pc;
216
217 do {
218 fc = *fname++;
219 pc = *pattern++;
220 if (!fc && !pc)
221 return 1;
222 if (pc == '?' && fc)
223 pc = fc;
224 } while (fc == pc);
225
226 if (pc != '*')
227 return 0;
228 /*
229 * Too hard (and unnecessary really) too check for "*?name" etc....
230 * "**" will look for a '*' and "*?" a '?'
231 */
232 pc = *pattern++;
233 if (!pc)
234 return 1;
235 while ((fname = strchr(fname, pc)))
236 if (fn_match(++fname, pattern))
237 return 1;
238 return 0;
239 }
240 #endif /* LIBSA_ENABLE_LS_OP */
241
242 #ifdef LIBSA_LFS
243 /*
244 * Find an inode's block. Look it up in the ifile. Whee!
245 */
246 static int
247 find_inode_sector(ino32_t inumber, struct open_file *f, daddr_t *isp)
248 {
249 struct file *fp = (struct file *)f->f_fsdata;
250 struct fs *fs = fp->f_fs;
251 daddr_t ifileent_blkno;
252 char *ent_in_buf;
253 size_t buf_after_ent;
254 int rc;
255
256 rc = read_inode(fs->lfs_ifile, f);
257 if (rc)
258 return rc;
259
260 ifileent_blkno =
261 (inumber / fs->lfs_ifpb) + fs->lfs_cleansz + fs->lfs_segtabsz;
262 fp->f_seekp = (off_t)ifileent_blkno * fs->fs_bsize +
263 (inumber % fs->lfs_ifpb) * sizeof (IFILE_Vx);
264 rc = buf_read_file(f, &ent_in_buf, &buf_after_ent);
265 if (rc)
266 return rc;
267 /* make sure something's not badly wrong, but don't panic. */
268 if (buf_after_ent < sizeof (IFILE_Vx))
269 return EINVAL;
270
271 *isp = FSBTODB(fs, ((IFILE_Vx *)ent_in_buf)->if_daddr);
272 if (*isp == LFS_UNUSED_DADDR) /* again, something badly wrong */
273 return EINVAL;
274 return 0;
275 }
276 #endif
277
278 /*
279 * Read a new inode into a file structure.
280 */
281 static int
282 read_inode(ino32_t inumber, struct open_file *f)
283 {
284 struct file *fp = (struct file *)f->f_fsdata;
285 struct fs *fs = fp->f_fs;
286 char *buf;
287 size_t rsize;
288 int rc;
289 daddr_t inode_sector;
290 #ifdef LIBSA_LFS
291 struct ufs_dinode *dip;
292 int cnt;
293 #endif
294
295 #ifdef LIBSA_LFS
296 if (inumber == fs->lfs_ifile)
297 inode_sector = FSBTODB(fs, fs->lfs_idaddr);
298 else if ((rc = find_inode_sector(inumber, f, &inode_sector)) != 0)
299 return rc;
300 #else
301 inode_sector = FSBTODB(fs, ino_to_fsba(fs, inumber));
302 #endif
303
304 /*
305 * Read inode and save it.
306 */
307 buf = fp->f_buf;
308 twiddle();
309 rc = DEV_STRATEGY(f->f_dev)(f->f_devdata, F_READ,
310 inode_sector, fs->fs_bsize, buf, &rsize);
311 if (rc)
312 return rc;
313 if (rsize != fs->fs_bsize)
314 return EIO;
315
316 #ifdef LIBSA_LFS
317 cnt = INOPBx(fs);
318 dip = (struct ufs_dinode *)buf + (cnt - 1);
319 for (; dip->di_inumber != inumber; --dip) {
320 /* kernel code panics, but boot blocks which panic are Bad. */
321 if (--cnt == 0)
322 return EINVAL;
323 }
324 fp->f_di = *dip;
325 #else
326 fp->f_di = ((struct ufs_dinode *)buf)[ino_to_fsbo(fs, inumber)];
327 #endif
328
329 /*
330 * Clear out the old buffers
331 */
332 fp->f_ind_cache_block = ~0;
333 fp->f_buf_blkno = -1;
334 return rc;
335 }
336
337 /*
338 * Given an offset in a file, find the disk block number that
339 * contains that block.
340 */
341 static int
342 block_map(struct open_file *f, indp_t file_block, indp_t *disk_block_p)
343 {
344 struct file *fp = (struct file *)f->f_fsdata;
345 struct fs *fs = fp->f_fs;
346 uint level;
347 indp_t ind_cache;
348 indp_t ind_block_num;
349 size_t rsize;
350 int rc;
351 indp_t *buf = (void *)fp->f_buf;
352
353 /*
354 * Index structure of an inode:
355 *
356 * di_db[0..NDADDR-1] hold block numbers for blocks
357 * 0..NDADDR-1
358 *
359 * di_ib[0] index block 0 is the single indirect block
360 * holds block numbers for blocks
361 * NDADDR .. NDADDR + NINDIR(fs)-1
362 *
363 * di_ib[1] index block 1 is the double indirect block
364 * holds block numbers for INDEX blocks for blocks
365 * NDADDR + NINDIR(fs) ..
366 * NDADDR + NINDIR(fs) + NINDIR(fs)**2 - 1
367 *
368 * di_ib[2] index block 2 is the triple indirect block
369 * holds block numbers for double-indirect
370 * blocks for blocks
371 * NDADDR + NINDIR(fs) + NINDIR(fs)**2 ..
372 * NDADDR + NINDIR(fs) + NINDIR(fs)**2
373 * + NINDIR(fs)**3 - 1
374 */
375
376 if (file_block < NDADDR) {
377 /* Direct block. */
378 *disk_block_p = fp->f_di.di_db[file_block];
379 return 0;
380 }
381
382 file_block -= NDADDR;
383
384 ind_cache = file_block >> LN2_IND_CACHE_SZ;
385 if (ind_cache == fp->f_ind_cache_block) {
386 *disk_block_p = fp->f_ind_cache[file_block & IND_CACHE_MASK];
387 return 0;
388 }
389
390 for (level = 0;;) {
391 level += fp->f_nishift;
392 if (file_block < (indp_t)1 << level)
393 break;
394 if (level > NIADDR * fp->f_nishift)
395 /* Block number too high */
396 return EFBIG;
397 file_block -= (indp_t)1 << level;
398 }
399
400 ind_block_num = fp->f_di.di_ib[level / fp->f_nishift - 1];
401
402 for (;;) {
403 level -= fp->f_nishift;
404 if (ind_block_num == 0) {
405 *disk_block_p = 0; /* missing */
406 return 0;
407 }
408
409 twiddle();
410 /*
411 * If we were feeling brave, we could work out the number
412 * of the disk sector and read a single disk sector instead
413 * of a filesystem block.
414 * However we don't do this very often anyway...
415 */
416 rc = DEV_STRATEGY(f->f_dev)(f->f_devdata, F_READ,
417 FSBTODB(fp->f_fs, ind_block_num), fs->fs_bsize,
418 buf, &rsize);
419 if (rc)
420 return rc;
421 if (rsize != fs->fs_bsize)
422 return EIO;
423 ind_block_num = buf[file_block >> level];
424 if (level == 0)
425 break;
426 file_block &= (1 << level) - 1;
427 }
428
429 /* Save the part of the block that contains this sector */
430 memcpy(fp->f_ind_cache, &buf[file_block & ~IND_CACHE_MASK],
431 IND_CACHE_SZ * sizeof fp->f_ind_cache[0]);
432 fp->f_ind_cache_block = ind_cache;
433
434 *disk_block_p = ind_block_num;
435
436 return 0;
437 }
438
439 /*
440 * Read a portion of a file into an internal buffer.
441 * Return the location in the buffer and the amount in the buffer.
442 */
443 static int
444 buf_read_file(struct open_file *f, char **buf_p, size_t *size_p)
445 {
446 struct file *fp = (struct file *)f->f_fsdata;
447 struct fs *fs = fp->f_fs;
448 long off;
449 indp_t file_block;
450 indp_t disk_block;
451 size_t block_size;
452 int rc;
453
454 off = blkoff(fs, fp->f_seekp);
455 file_block = lblkno(fs, fp->f_seekp);
456 #ifdef LIBSA_LFS
457 block_size = dblksize(fs, &fp->f_di, file_block);
458 #else
459 block_size = sblksize(fs, (int64_t)fp->f_di.di_size, file_block);
460 #endif
461
462 if (file_block != fp->f_buf_blkno) {
463 rc = block_map(f, file_block, &disk_block);
464 if (rc)
465 return rc;
466
467 if (disk_block == 0) {
468 memset(fp->f_buf, 0, block_size);
469 fp->f_buf_size = block_size;
470 } else {
471 twiddle();
472 rc = DEV_STRATEGY(f->f_dev)(f->f_devdata, F_READ,
473 FSBTODB(fs, disk_block),
474 block_size, fp->f_buf, &fp->f_buf_size);
475 if (rc)
476 return rc;
477 }
478
479 fp->f_buf_blkno = file_block;
480 }
481
482 /*
483 * Return address of byte in buffer corresponding to
484 * offset, and size of remainder of buffer after that
485 * byte.
486 */
487 *buf_p = fp->f_buf + off;
488 *size_p = block_size - off;
489
490 /*
491 * But truncate buffer at end of file.
492 */
493 if (*size_p > fp->f_di.di_size - fp->f_seekp)
494 *size_p = fp->f_di.di_size - fp->f_seekp;
495
496 return 0;
497 }
498
499 /*
500 * Search a directory for a name and return its
501 * inode number.
502 */
503 static int
504 search_directory(const char *name, int length, struct open_file *f,
505 ino32_t *inumber_p)
506 {
507 struct file *fp = (struct file *)f->f_fsdata;
508 struct direct *dp;
509 struct direct *edp;
510 char *buf;
511 size_t buf_size;
512 int namlen;
513 int rc;
514
515 fp->f_seekp = 0;
516 while (fp->f_seekp < (off_t)fp->f_di.di_size) {
517 rc = buf_read_file(f, &buf, &buf_size);
518 if (rc)
519 return rc;
520
521 dp = (struct direct *)buf;
522 edp = (struct direct *)(buf + buf_size);
523 for (;dp < edp; dp = (void *)((char *)dp + dp->d_reclen)) {
524 if (dp->d_reclen <= 0)
525 break;
526 if (dp->d_ino == (ino32_t)0)
527 continue;
528 #if BYTE_ORDER == LITTLE_ENDIAN
529 if (fp->f_fs->fs_maxsymlinklen <= 0)
530 namlen = dp->d_type;
531 else
532 #endif
533 namlen = dp->d_namlen;
534 if (namlen == length &&
535 !memcmp(name, dp->d_name, length)) {
536 /* found entry */
537 *inumber_p = dp->d_ino;
538 return 0;
539 }
540 }
541 fp->f_seekp += buf_size;
542 }
543 return ENOENT;
544 }
545
546 #ifdef LIBSA_FFSv2
547
548 daddr_t sblock_try[] = SBLOCKSEARCH;
549
550 static int
551 ffs_find_superblock(struct open_file *f, struct fs *fs)
552 {
553 int i, rc;
554 size_t buf_size;
555
556 for (i = 0; sblock_try[i] != -1; i++) {
557 rc = DEV_STRATEGY(f->f_dev)(f->f_devdata, F_READ,
558 sblock_try[i] / DEV_BSIZE, SBLOCKSIZE, fs, &buf_size);
559 if (rc != 0 || buf_size != SBLOCKSIZE)
560 return rc;
561 if (fs->fs_sblockloc != sblock_try[i])
562 /* an alternate superblock - try again */
563 continue;
564 if (fs->fs_magic == FS_UFS2_MAGIC) {
565 return 0;
566 }
567 }
568 return EINVAL;
569 }
570
571 #endif
572
573 /*
574 * Open a file.
575 */
576 __compactcall int
577 ufs_open(const char *path, struct open_file *f)
578 {
579 #ifndef LIBSA_FS_SINGLECOMPONENT
580 const char *cp, *ncp;
581 int c;
582 #endif
583 ino32_t inumber;
584 struct file *fp;
585 struct fs *fs;
586 int rc;
587 #ifndef LIBSA_NO_FS_SYMLINK
588 ino32_t parent_inumber;
589 int nlinks = 0;
590 char namebuf[MAXPATHLEN+1];
591 char *buf;
592 #endif
593
594 /* allocate file system specific data structure */
595 fp = alloc(sizeof(struct file));
596 memset(fp, 0, sizeof(struct file));
597 f->f_fsdata = (void *)fp;
598
599 /* allocate space and read super block */
600 fs = alloc(SBLOCKSIZE);
601 fp->f_fs = fs;
602 twiddle();
603
604 #ifdef LIBSA_FFSv2
605 rc = ffs_find_superblock(f, fs);
606 if (rc)
607 goto out;
608 #else
609 {
610 size_t buf_size;
611 rc = DEV_STRATEGY(f->f_dev)(f->f_devdata, F_READ,
612 SBLOCKOFFSET / DEV_BSIZE, SBLOCKSIZE, fs, &buf_size);
613 if (rc)
614 goto out;
615 if (buf_size != SBLOCKSIZE ||
616 #ifdef LIBSA_FFS
617 fs->lfs_version != REQUIRED_LFS_VERSION ||
618 #endif
619 fs->fs_magic != FS_MAGIC) {
620 rc = EINVAL;
621 goto out;
622 }
623 }
624 #if defined(LIBSA_LFS) && REQUIRED_LFS_VERSION == 2
625 /*
626 * XXX We should check the second superblock and use the eldest
627 * of the two. See comments near the top of lfs_mountfs()
628 * in sys/ufs/lfs/lfs_vfsops.c.
629 * This may need a LIBSA_LFS_SMALL check as well.
630 */
631 #endif
632 #endif
633
634 #ifdef LIBSA_FFSv1
635 ffs_oldfscompat(fs);
636 #endif
637
638 if (fs->fs_bsize > MAXBSIZE ||
639 (size_t)fs->fs_bsize < sizeof(struct fs)) {
640 rc = EINVAL;
641 goto out;
642 }
643
644 /*
645 * Calculate indirect block levels.
646 */
647 {
648 indp_t mult;
649 int ln2;
650
651 /*
652 * We note that the number of indirect blocks is always
653 * a power of 2. This lets us use shifts and masks instead
654 * of divide and remainder and avoinds pulling in the
655 * 64bit division routine into the boot code.
656 */
657 mult = NINDIR(fs);
658 #ifdef DEBUG
659 if (mult & (mult - 1)) {
660 /* Hummm was't a power of 2 */
661 rc = EINVAL;
662 goto out;
663 }
664 #endif
665 for (ln2 = 0; mult != 1; ln2++)
666 mult >>= 1;
667
668 fp->f_nishift = ln2;
669 }
670
671 /* alloc a block sized buffer used for all fs transfers */
672 fp->f_buf = alloc(fs->fs_bsize);
673 inumber = ROOTINO;
674 if ((rc = read_inode(inumber, f)) != 0)
675 goto out;
676
677 #ifndef LIBSA_FS_SINGLECOMPONENT
678 cp = path;
679 while (*cp) {
680
681 /*
682 * Remove extra separators
683 */
684 while (*cp == '/')
685 cp++;
686 if (*cp == '\0')
687 break;
688
689 /*
690 * Check that current node is a directory.
691 */
692 if ((fp->f_di.di_mode & IFMT) != IFDIR) {
693 rc = ENOTDIR;
694 goto out;
695 }
696
697 /*
698 * Get next component of path name.
699 */
700 ncp = cp;
701 while ((c = *cp) != '\0' && c != '/')
702 cp++;
703
704 /*
705 * Look up component in current directory.
706 * Save directory inumber in case we find a
707 * symbolic link.
708 */
709 #ifndef LIBSA_NO_FS_SYMLINK
710 parent_inumber = inumber;
711 #endif
712 rc = search_directory(ncp, cp - ncp, f, &inumber);
713 if (rc)
714 goto out;
715
716 /*
717 * Open next component.
718 */
719 if ((rc = read_inode(inumber, f)) != 0)
720 goto out;
721
722 #ifndef LIBSA_NO_FS_SYMLINK
723 /*
724 * Check for symbolic link.
725 */
726 if ((fp->f_di.di_mode & IFMT) == IFLNK) {
727 int link_len = fp->f_di.di_size;
728 int len;
729
730 len = strlen(cp);
731
732 if (link_len + len > MAXPATHLEN ||
733 ++nlinks > MAXSYMLINKS) {
734 rc = ENOENT;
735 goto out;
736 }
737
738 memmove(&namebuf[link_len], cp, len + 1);
739
740 if (link_len < fs->fs_maxsymlinklen) {
741 memcpy(namebuf, fp->f_di.di_db, link_len);
742 } else {
743 /*
744 * Read file for symbolic link
745 */
746 size_t buf_size;
747 indp_t disk_block;
748
749 buf = fp->f_buf;
750 rc = block_map(f, (indp_t)0, &disk_block);
751 if (rc)
752 goto out;
753
754 twiddle();
755 rc = DEV_STRATEGY(f->f_dev)(f->f_devdata,
756 F_READ, FSBTODB(fs, disk_block),
757 fs->fs_bsize, buf, &buf_size);
758 if (rc)
759 goto out;
760
761 memcpy(namebuf, buf, link_len);
762 }
763
764 /*
765 * If relative pathname, restart at parent directory.
766 * If absolute pathname, restart at root.
767 */
768 cp = namebuf;
769 if (*cp != '/')
770 inumber = parent_inumber;
771 else
772 inumber = (ino32_t)ROOTINO;
773
774 if ((rc = read_inode(inumber, f)) != 0)
775 goto out;
776 }
777 #endif /* !LIBSA_NO_FS_SYMLINK */
778 }
779
780 /*
781 * Found terminal component.
782 */
783 rc = 0;
784
785 #else /* !LIBSA_FS_SINGLECOMPONENT */
786
787 /* look up component in the current (root) directory */
788 rc = search_directory(path, strlen(path), f, &inumber);
789 if (rc)
790 goto out;
791
792 /* open it */
793 rc = read_inode(inumber, f);
794
795 #endif /* !LIBSA_FS_SINGLECOMPONENT */
796
797 fp->f_seekp = 0; /* reset seek pointer */
798
799 out:
800 if (rc)
801 ufs_close(f);
802 else {
803 #ifdef FSMOD
804 fsmod = FSMOD;
805 #endif
806 #ifdef FSMOD2
807 fsmod2 = FSMOD2;
808 #endif
809 }
810 return rc;
811 }
812
813 __compactcall int
814 ufs_close(struct open_file *f)
815 {
816 struct file *fp = (struct file *)f->f_fsdata;
817
818 f->f_fsdata = NULL;
819 if (fp == NULL)
820 return 0;
821
822 if (fp->f_buf)
823 dealloc(fp->f_buf, fp->f_fs->fs_bsize);
824 dealloc(fp->f_fs, SBLOCKSIZE);
825 dealloc(fp, sizeof(struct file));
826 return 0;
827 }
828
829 /*
830 * Copy a portion of a file into kernel memory.
831 * Cross block boundaries when necessary.
832 */
833 __compactcall int
834 ufs_read(struct open_file *f, void *start, size_t size, size_t *resid)
835 {
836 struct file *fp = (struct file *)f->f_fsdata;
837 size_t csize;
838 char *buf;
839 size_t buf_size;
840 int rc = 0;
841 char *addr = start;
842
843 while (size != 0) {
844 if (fp->f_seekp >= (off_t)fp->f_di.di_size)
845 break;
846
847 rc = buf_read_file(f, &buf, &buf_size);
848 if (rc)
849 break;
850
851 csize = size;
852 if (csize > buf_size)
853 csize = buf_size;
854
855 memcpy(addr, buf, csize);
856
857 fp->f_seekp += csize;
858 addr += csize;
859 size -= csize;
860 }
861 if (resid)
862 *resid = size;
863 return rc;
864 }
865
866 /*
867 * Not implemented.
868 */
869 #ifndef LIBSA_NO_FS_WRITE
870 __compactcall int
871 ufs_write(struct open_file *f, void *start, size_t size, size_t *resid)
872 {
873
874 return EROFS;
875 }
876 #endif /* !LIBSA_NO_FS_WRITE */
877
878 #ifndef LIBSA_NO_FS_SEEK
879 __compactcall off_t
880 ufs_seek(struct open_file *f, off_t offset, int where)
881 {
882 struct file *fp = (struct file *)f->f_fsdata;
883
884 switch (where) {
885 case SEEK_SET:
886 fp->f_seekp = offset;
887 break;
888 case SEEK_CUR:
889 fp->f_seekp += offset;
890 break;
891 case SEEK_END:
892 fp->f_seekp = fp->f_di.di_size - offset;
893 break;
894 default:
895 return -1;
896 }
897 return fp->f_seekp;
898 }
899 #endif /* !LIBSA_NO_FS_SEEK */
900
901 __compactcall int
902 ufs_stat(struct open_file *f, struct stat *sb)
903 {
904 struct file *fp = (struct file *)f->f_fsdata;
905
906 /* only important stuff */
907 memset(sb, 0, sizeof *sb);
908 sb->st_mode = fp->f_di.di_mode;
909 sb->st_uid = fp->f_di.di_uid;
910 sb->st_gid = fp->f_di.di_gid;
911 sb->st_size = fp->f_di.di_size;
912 return 0;
913 }
914
915 #if defined(LIBSA_ENABLE_LS_OP)
916 __compactcall void
917 ufs_ls(struct open_file *f, const char *pattern)
918 {
919 struct file *fp = (struct file *)f->f_fsdata;
920 char *buf;
921 size_t buf_size;
922 entry_t *names = 0, *n, **np;
923
924 fp->f_seekp = 0;
925 while (fp->f_seekp < (off_t)fp->f_di.di_size) {
926 struct direct *dp, *edp;
927 int rc = buf_read_file(f, &buf, &buf_size);
928 if (rc)
929 goto out;
930 /* some firmware might use block size larger than DEV_BSIZE */
931 if (buf_size < DIRBLKSIZ)
932 goto out;
933
934 dp = (struct direct *)buf;
935 edp = (struct direct *)(buf + buf_size);
936
937 for (; dp < edp; dp = (void *)((char *)dp + dp->d_reclen)) {
938 const char *t;
939 if (dp->d_ino == 0)
940 continue;
941
942 if (dp->d_type >= NELEM(typestr) ||
943 !(t = typestr[dp->d_type])) {
944 /*
945 * This does not handle "old"
946 * filesystems properly. On little
947 * endian machines, we get a bogus
948 * type name if the namlen matches a
949 * valid type identifier. We could
950 * check if we read namlen "0" and
951 * handle this case specially, if
952 * there were a pressing need...
953 */
954 printf("bad dir entry\n");
955 goto out;
956 }
957 if (pattern && !fn_match(dp->d_name, pattern))
958 continue;
959 n = alloc(sizeof *n + strlen(dp->d_name));
960 if (!n) {
961 printf("%d: %s (%s)\n",
962 dp->d_ino, dp->d_name, t);
963 continue;
964 }
965 n->e_ino = dp->d_ino;
966 n->e_type = dp->d_type;
967 strcpy(n->e_name, dp->d_name);
968 for (np = &names; *np; np = &(*np)->e_next) {
969 if (strcmp(n->e_name, (*np)->e_name) < 0)
970 break;
971 }
972 n->e_next = *np;
973 *np = n;
974 }
975 fp->f_seekp += buf_size;
976 }
977
978 if (names) {
979 entry_t *p_names = names;
980 do {
981 n = p_names;
982 printf("%d: %s (%s)\n",
983 n->e_ino, n->e_name, typestr[n->e_type]);
984 p_names = n->e_next;
985 } while (p_names);
986 } else {
987 printf("not found\n");
988 }
989 out:
990 if (names) {
991 do {
992 n = names;
993 names = n->e_next;
994 dealloc(n, 0);
995 } while (names);
996 }
997 }
998 #endif /* LIBSA_ENABLE_LS_OP */
999
1000 #ifdef LIBSA_FFSv1
1001 /*
1002 * Sanity checks for old file systems.
1003 *
1004 * XXX - goes away some day.
1005 * Stripped of stuff libsa doesn't need.....
1006 */
1007 static void
1008 ffs_oldfscompat(struct fs *fs)
1009 {
1010
1011 #ifdef COMPAT_UFS
1012 /*
1013 * Newer Solaris versions have a slightly incompatible
1014 * superblock - so always calculate this values on the fly, which
1015 * is good enough for libsa purposes
1016 */
1017 if (fs->fs_magic == FS_UFS1_MAGIC
1018 #ifndef COMPAT_SOLARIS_UFS
1019 && fs->fs_old_inodefmt < FS_44INODEFMT
1020 #endif
1021 ) {
1022 fs->fs_qbmask = ~fs->fs_bmask;
1023 fs->fs_qfmask = ~fs->fs_fmask;
1024 }
1025 #endif
1026 }
1027 #endif
1028