ufs.c revision 1.62 1 /* $NetBSD: ufs.c,v 1.62 2013/06/23 02:06:05 dholland 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
140 #ifndef FSBTODB
141 #define FSBTODB(fs, indp) FFS_FSBTODB(fs, indp)
142 #endif
143 #ifndef UFS_NINDIR
144 #define UFS_NINDIR FFS_NINDIR
145 #endif
146 #ifndef ufs_blkoff
147 #define ufs_blkoff ffs_blkoff
148 #endif
149
150 /*
151 * To avoid having a lot of filesystem-block sized buffers lurking (which
152 * could be 32k) we only keep a few entries of the indirect block map.
153 * With 8k blocks, 2^8 blocks is ~500k so we reread the indirect block
154 * ~13 times pulling in a 6M kernel.
155 * The cache size must be smaller than the smallest filesystem block,
156 * so LN2_IND_CACHE_SZ <= 9 (UFS2 and 4k blocks).
157 */
158 #define LN2_IND_CACHE_SZ 6
159 #define IND_CACHE_SZ (1 << LN2_IND_CACHE_SZ)
160 #define IND_CACHE_MASK (IND_CACHE_SZ - 1)
161
162 /*
163 * In-core open file.
164 */
165 struct file {
166 off_t f_seekp; /* seek pointer */
167 struct fs *f_fs; /* pointer to super-block */
168 struct ufs_dinode f_di; /* copy of on-disk inode */
169 uint f_nishift; /* for blocks in indirect block */
170 indp_t f_ind_cache_block;
171 indp_t f_ind_cache[IND_CACHE_SZ];
172
173 char *f_buf; /* buffer for data block */
174 size_t f_buf_size; /* size of data block */
175 daddr_t f_buf_blkno; /* block number of data block */
176 };
177
178 static int read_inode(ino32_t, struct open_file *);
179 static int block_map(struct open_file *, indp_t, indp_t *);
180 static int buf_read_file(struct open_file *, char **, size_t *);
181 static int search_directory(const char *, int, struct open_file *, ino32_t *);
182 #ifdef LIBSA_FFSv1
183 static void ffs_oldfscompat(struct fs *);
184 #endif
185 #ifdef LIBSA_FFSv2
186 static int ffs_find_superblock(struct open_file *, struct fs *);
187 #endif
188
189 #if defined(LIBSA_ENABLE_LS_OP)
190
191 #define NELEM(x) (sizeof (x) / sizeof(*x))
192
193 typedef struct entry_t entry_t;
194 struct entry_t {
195 entry_t *e_next;
196 ino32_t e_ino;
197 uint8_t e_type;
198 char e_name[1];
199 };
200
201 static const char *const typestr[] = {
202 "unknown",
203 "FIFO",
204 "CHR",
205 0,
206 "DIR",
207 0,
208 "BLK",
209 0,
210 "REG",
211 0,
212 "LNK",
213 0,
214 "SOCK",
215 0,
216 "WHT"
217 };
218 #endif /* LIBSA_ENABLE_LS_OP */
219
220 #ifdef LIBSA_LFS
221 /*
222 * Find an inode's block. Look it up in the ifile. Whee!
223 */
224 static int
225 find_inode_sector(ino32_t inumber, struct open_file *f, daddr_t *isp)
226 {
227 struct file *fp = (struct file *)f->f_fsdata;
228 struct fs *fs = fp->f_fs;
229 daddr_t ifileent_blkno;
230 char *ent_in_buf;
231 size_t buf_after_ent;
232 int rc;
233
234 rc = read_inode(fs->lfs_ifile, f);
235 if (rc)
236 return rc;
237
238 ifileent_blkno =
239 (inumber / fs->lfs_ifpb) + fs->lfs_cleansz + fs->lfs_segtabsz;
240 fp->f_seekp = (off_t)ifileent_blkno * fs->fs_bsize +
241 (inumber % fs->lfs_ifpb) * sizeof (IFILE_Vx);
242 rc = buf_read_file(f, &ent_in_buf, &buf_after_ent);
243 if (rc)
244 return rc;
245 /* make sure something's not badly wrong, but don't panic. */
246 if (buf_after_ent < sizeof (IFILE_Vx))
247 return EINVAL;
248
249 *isp = FSBTODB(fs, ((IFILE_Vx *)ent_in_buf)->if_daddr);
250 if (*isp == LFS_UNUSED_DADDR) /* again, something badly wrong */
251 return EINVAL;
252 return 0;
253 }
254 #endif
255
256 /*
257 * Read a new inode into a file structure.
258 */
259 static int
260 read_inode(ino32_t inumber, struct open_file *f)
261 {
262 struct file *fp = (struct file *)f->f_fsdata;
263 struct fs *fs = fp->f_fs;
264 char *buf;
265 size_t rsize;
266 int rc;
267 daddr_t inode_sector;
268 #ifdef LIBSA_LFS
269 struct ufs_dinode *dip;
270 int cnt;
271 #endif
272
273 #ifdef LIBSA_LFS
274 if (inumber == fs->lfs_ifile)
275 inode_sector = FSBTODB(fs, fs->lfs_idaddr);
276 else if ((rc = find_inode_sector(inumber, f, &inode_sector)) != 0)
277 return rc;
278 #else
279 inode_sector = FSBTODB(fs, ino_to_fsba(fs, inumber));
280 #endif
281
282 /*
283 * Read inode and save it.
284 */
285 buf = fp->f_buf;
286 twiddle();
287 rc = DEV_STRATEGY(f->f_dev)(f->f_devdata, F_READ,
288 inode_sector, fs->fs_bsize, buf, &rsize);
289 if (rc)
290 return rc;
291 if (rsize != fs->fs_bsize)
292 return EIO;
293
294 #ifdef LIBSA_LFS
295 cnt = INOPBx(fs);
296 dip = (struct ufs_dinode *)buf + (cnt - 1);
297 for (; dip->di_inumber != inumber; --dip) {
298 /* kernel code panics, but boot blocks which panic are Bad. */
299 if (--cnt == 0)
300 return EINVAL;
301 }
302 fp->f_di = *dip;
303 #else
304 fp->f_di = ((struct ufs_dinode *)buf)[ino_to_fsbo(fs, inumber)];
305 #endif
306
307 /*
308 * Clear out the old buffers
309 */
310 fp->f_ind_cache_block = ~0;
311 fp->f_buf_blkno = -1;
312 return rc;
313 }
314
315 /*
316 * Given an offset in a file, find the disk block number that
317 * contains that block.
318 */
319 static int
320 block_map(struct open_file *f, indp_t file_block, indp_t *disk_block_p)
321 {
322 struct file *fp = (struct file *)f->f_fsdata;
323 struct fs *fs = fp->f_fs;
324 uint level;
325 indp_t ind_cache;
326 indp_t ind_block_num;
327 size_t rsize;
328 int rc;
329 indp_t *buf = (void *)fp->f_buf;
330
331 /*
332 * Index structure of an inode:
333 *
334 * di_db[0..UFS_NDADDR-1] hold block numbers for blocks
335 * 0..UFS_NDADDR-1
336 *
337 * di_ib[0] index block 0 is the single indirect block
338 * holds block numbers for blocks
339 * UFS_NDADDR .. UFS_NDADDR + UFS_NINDIR(fs)-1
340 *
341 * di_ib[1] index block 1 is the double indirect block
342 * holds block numbers for INDEX blocks for blocks
343 * UFS_NDADDR + UFS_NINDIR(fs) ..
344 * UFS_NDADDR + UFS_NINDIR(fs) + UFS_NINDIR(fs)**2 - 1
345 *
346 * di_ib[2] index block 2 is the triple indirect block
347 * holds block numbers for double-indirect
348 * blocks for blocks
349 * UFS_NDADDR + UFS_NINDIR(fs) + UFS_NINDIR(fs)**2 ..
350 * UFS_NDADDR + UFS_NINDIR(fs) + UFS_NINDIR(fs)**2
351 * + UFS_NINDIR(fs)**3 - 1
352 */
353
354 if (file_block < UFS_NDADDR) {
355 /* Direct block. */
356 *disk_block_p = fp->f_di.di_db[file_block];
357 return 0;
358 }
359
360 file_block -= UFS_NDADDR;
361
362 ind_cache = file_block >> LN2_IND_CACHE_SZ;
363 if (ind_cache == fp->f_ind_cache_block) {
364 *disk_block_p = fp->f_ind_cache[file_block & IND_CACHE_MASK];
365 return 0;
366 }
367
368 for (level = 0;;) {
369 level += fp->f_nishift;
370 if (file_block < (indp_t)1 << level)
371 break;
372 if (level > UFS_NIADDR * fp->f_nishift)
373 /* Block number too high */
374 return EFBIG;
375 file_block -= (indp_t)1 << level;
376 }
377
378 ind_block_num = fp->f_di.di_ib[level / fp->f_nishift - 1];
379
380 for (;;) {
381 level -= fp->f_nishift;
382 if (ind_block_num == 0) {
383 *disk_block_p = 0; /* missing */
384 return 0;
385 }
386
387 twiddle();
388 /*
389 * If we were feeling brave, we could work out the number
390 * of the disk sector and read a single disk sector instead
391 * of a filesystem block.
392 * However we don't do this very often anyway...
393 */
394 rc = DEV_STRATEGY(f->f_dev)(f->f_devdata, F_READ,
395 FSBTODB(fp->f_fs, ind_block_num), fs->fs_bsize,
396 buf, &rsize);
397 if (rc)
398 return rc;
399 if (rsize != fs->fs_bsize)
400 return EIO;
401 ind_block_num = buf[file_block >> level];
402 if (level == 0)
403 break;
404 file_block &= (1 << level) - 1;
405 }
406
407 /* Save the part of the block that contains this sector */
408 memcpy(fp->f_ind_cache, &buf[file_block & ~IND_CACHE_MASK],
409 IND_CACHE_SZ * sizeof fp->f_ind_cache[0]);
410 fp->f_ind_cache_block = ind_cache;
411
412 *disk_block_p = ind_block_num;
413
414 return 0;
415 }
416
417 /*
418 * Read a portion of a file into an internal buffer.
419 * Return the location in the buffer and the amount in the buffer.
420 */
421 static int
422 buf_read_file(struct open_file *f, char **buf_p, size_t *size_p)
423 {
424 struct file *fp = (struct file *)f->f_fsdata;
425 struct fs *fs = fp->f_fs;
426 long off;
427 indp_t file_block;
428 indp_t disk_block;
429 size_t block_size;
430 int rc;
431
432 off = ufs_blkoff(fs, fp->f_seekp);
433 file_block = lblkno(fs, fp->f_seekp);
434 #ifdef LIBSA_LFS
435 block_size = dblksize(fs, &fp->f_di, file_block);
436 #else
437 block_size = ffs_sblksize(fs, (int64_t)fp->f_di.di_size, file_block);
438 #endif
439
440 if (file_block != fp->f_buf_blkno) {
441 rc = block_map(f, file_block, &disk_block);
442 if (rc)
443 return rc;
444
445 if (disk_block == 0) {
446 memset(fp->f_buf, 0, block_size);
447 fp->f_buf_size = block_size;
448 } else {
449 twiddle();
450 rc = DEV_STRATEGY(f->f_dev)(f->f_devdata, F_READ,
451 FSBTODB(fs, disk_block),
452 block_size, fp->f_buf, &fp->f_buf_size);
453 if (rc)
454 return rc;
455 }
456
457 fp->f_buf_blkno = file_block;
458 }
459
460 /*
461 * Return address of byte in buffer corresponding to
462 * offset, and size of remainder of buffer after that
463 * byte.
464 */
465 *buf_p = fp->f_buf + off;
466 *size_p = block_size - off;
467
468 /*
469 * But truncate buffer at end of file.
470 */
471 if (*size_p > fp->f_di.di_size - fp->f_seekp)
472 *size_p = fp->f_di.di_size - fp->f_seekp;
473
474 return 0;
475 }
476
477 /*
478 * Search a directory for a name and return its
479 * inode number.
480 */
481 static int
482 search_directory(const char *name, int length, struct open_file *f,
483 ino32_t *inumber_p)
484 {
485 struct file *fp = (struct file *)f->f_fsdata;
486 struct direct *dp;
487 struct direct *edp;
488 char *buf;
489 size_t buf_size;
490 int namlen;
491 int rc;
492
493 fp->f_seekp = 0;
494 while (fp->f_seekp < (off_t)fp->f_di.di_size) {
495 rc = buf_read_file(f, &buf, &buf_size);
496 if (rc)
497 return rc;
498
499 dp = (struct direct *)buf;
500 edp = (struct direct *)(buf + buf_size);
501 for (;dp < edp; dp = (void *)((char *)dp + dp->d_reclen)) {
502 if (dp->d_reclen <= 0)
503 break;
504 if (dp->d_ino == (ino32_t)0)
505 continue;
506 #if BYTE_ORDER == LITTLE_ENDIAN
507 if (fp->f_fs->fs_maxsymlinklen <= 0)
508 namlen = dp->d_type;
509 else
510 #endif
511 namlen = dp->d_namlen;
512 if (namlen == length &&
513 !memcmp(name, dp->d_name, length)) {
514 /* found entry */
515 *inumber_p = dp->d_ino;
516 return 0;
517 }
518 }
519 fp->f_seekp += buf_size;
520 }
521 return ENOENT;
522 }
523
524 #ifdef LIBSA_FFSv2
525
526 daddr_t sblock_try[] = SBLOCKSEARCH;
527
528 static int
529 ffs_find_superblock(struct open_file *f, struct fs *fs)
530 {
531 int i, rc;
532 size_t buf_size;
533
534 for (i = 0; sblock_try[i] != -1; i++) {
535 rc = DEV_STRATEGY(f->f_dev)(f->f_devdata, F_READ,
536 sblock_try[i] / DEV_BSIZE, SBLOCKSIZE, fs, &buf_size);
537 if (rc != 0 || buf_size != SBLOCKSIZE)
538 return rc;
539 if (fs->fs_sblockloc != sblock_try[i])
540 /* an alternate superblock - try again */
541 continue;
542 if (fs->fs_magic == FS_UFS2_MAGIC) {
543 return 0;
544 }
545 }
546 return EINVAL;
547 }
548
549 #endif
550
551 /*
552 * Open a file.
553 */
554 __compactcall int
555 ufs_open(const char *path, struct open_file *f)
556 {
557 #ifndef LIBSA_FS_SINGLECOMPONENT
558 const char *cp, *ncp;
559 int c;
560 #endif
561 ino32_t inumber;
562 struct file *fp;
563 struct fs *fs;
564 int rc;
565 #ifndef LIBSA_NO_FS_SYMLINK
566 ino32_t parent_inumber;
567 int nlinks = 0;
568 char namebuf[MAXPATHLEN+1];
569 char *buf;
570 #endif
571
572 /* allocate file system specific data structure */
573 fp = alloc(sizeof(struct file));
574 memset(fp, 0, sizeof(struct file));
575 f->f_fsdata = (void *)fp;
576
577 /* allocate space and read super block */
578 fs = alloc(SBLOCKSIZE);
579 fp->f_fs = fs;
580 twiddle();
581
582 #ifdef LIBSA_FFSv2
583 rc = ffs_find_superblock(f, fs);
584 if (rc)
585 goto out;
586 #else
587 {
588 size_t buf_size;
589 rc = DEV_STRATEGY(f->f_dev)(f->f_devdata, F_READ,
590 SBLOCKOFFSET / DEV_BSIZE, SBLOCKSIZE, fs, &buf_size);
591 if (rc)
592 goto out;
593 if (buf_size != SBLOCKSIZE ||
594 #ifdef LIBSA_FFS
595 fs->lfs_version != REQUIRED_LFS_VERSION ||
596 #endif
597 fs->fs_magic != FS_MAGIC) {
598 rc = EINVAL;
599 goto out;
600 }
601 }
602 #if defined(LIBSA_LFS) && REQUIRED_LFS_VERSION == 2
603 /*
604 * XXX We should check the second superblock and use the eldest
605 * of the two. See comments near the top of lfs_mountfs()
606 * in sys/ufs/lfs/lfs_vfsops.c.
607 * This may need a LIBSA_LFS_SMALL check as well.
608 */
609 #endif
610 #endif
611
612 #ifdef LIBSA_FFSv1
613 ffs_oldfscompat(fs);
614 #endif
615
616 if (fs->fs_bsize > MAXBSIZE ||
617 (size_t)fs->fs_bsize < sizeof(struct fs)) {
618 rc = EINVAL;
619 goto out;
620 }
621
622 /*
623 * Calculate indirect block levels.
624 */
625 {
626 indp_t mult;
627 int ln2;
628
629 /*
630 * We note that the number of indirect blocks is always
631 * a power of 2. This lets us use shifts and masks instead
632 * of divide and remainder and avoinds pulling in the
633 * 64bit division routine into the boot code.
634 */
635 mult = UFS_NINDIR(fs);
636 #ifdef DEBUG
637 if (mult & (mult - 1)) {
638 /* Hummm was't a power of 2 */
639 rc = EINVAL;
640 goto out;
641 }
642 #endif
643 for (ln2 = 0; mult != 1; ln2++)
644 mult >>= 1;
645
646 fp->f_nishift = ln2;
647 }
648
649 /* alloc a block sized buffer used for all fs transfers */
650 fp->f_buf = alloc(fs->fs_bsize);
651 inumber = UFS_ROOTINO;
652 if ((rc = read_inode(inumber, f)) != 0)
653 goto out;
654
655 #ifndef LIBSA_FS_SINGLECOMPONENT
656 cp = path;
657 while (*cp) {
658
659 /*
660 * Remove extra separators
661 */
662 while (*cp == '/')
663 cp++;
664 if (*cp == '\0')
665 break;
666
667 /*
668 * Check that current node is a directory.
669 */
670 if ((fp->f_di.di_mode & IFMT) != IFDIR) {
671 rc = ENOTDIR;
672 goto out;
673 }
674
675 /*
676 * Get next component of path name.
677 */
678 ncp = cp;
679 while ((c = *cp) != '\0' && c != '/')
680 cp++;
681
682 /*
683 * Look up component in current directory.
684 * Save directory inumber in case we find a
685 * symbolic link.
686 */
687 #ifndef LIBSA_NO_FS_SYMLINK
688 parent_inumber = inumber;
689 #endif
690 rc = search_directory(ncp, cp - ncp, f, &inumber);
691 if (rc)
692 goto out;
693
694 /*
695 * Open next component.
696 */
697 if ((rc = read_inode(inumber, f)) != 0)
698 goto out;
699
700 #ifndef LIBSA_NO_FS_SYMLINK
701 /*
702 * Check for symbolic link.
703 */
704 if ((fp->f_di.di_mode & IFMT) == IFLNK) {
705 int link_len = fp->f_di.di_size;
706 int len;
707
708 len = strlen(cp);
709
710 if (link_len + len > MAXPATHLEN ||
711 ++nlinks > MAXSYMLINKS) {
712 rc = ENOENT;
713 goto out;
714 }
715
716 memmove(&namebuf[link_len], cp, len + 1);
717
718 if (link_len < fs->fs_maxsymlinklen) {
719 memcpy(namebuf, fp->f_di.di_db, link_len);
720 } else {
721 /*
722 * Read file for symbolic link
723 */
724 size_t buf_size;
725 indp_t disk_block;
726
727 buf = fp->f_buf;
728 rc = block_map(f, (indp_t)0, &disk_block);
729 if (rc)
730 goto out;
731
732 twiddle();
733 rc = DEV_STRATEGY(f->f_dev)(f->f_devdata,
734 F_READ, FSBTODB(fs, disk_block),
735 fs->fs_bsize, buf, &buf_size);
736 if (rc)
737 goto out;
738
739 memcpy(namebuf, buf, link_len);
740 }
741
742 /*
743 * If relative pathname, restart at parent directory.
744 * If absolute pathname, restart at root.
745 */
746 cp = namebuf;
747 if (*cp != '/')
748 inumber = parent_inumber;
749 else
750 inumber = (ino32_t)UFS_ROOTINO;
751
752 if ((rc = read_inode(inumber, f)) != 0)
753 goto out;
754 }
755 #endif /* !LIBSA_NO_FS_SYMLINK */
756 }
757
758 /*
759 * Found terminal component.
760 */
761 rc = 0;
762
763 #else /* !LIBSA_FS_SINGLECOMPONENT */
764
765 /* look up component in the current (root) directory */
766 rc = search_directory(path, strlen(path), f, &inumber);
767 if (rc)
768 goto out;
769
770 /* open it */
771 rc = read_inode(inumber, f);
772
773 #endif /* !LIBSA_FS_SINGLECOMPONENT */
774
775 fp->f_seekp = 0; /* reset seek pointer */
776
777 out:
778 if (rc)
779 ufs_close(f);
780 #ifdef FSMOD /* Only defined for lfs */
781 else
782 fsmod = FSMOD;
783 #endif
784 return rc;
785 }
786
787 __compactcall int
788 ufs_close(struct open_file *f)
789 {
790 struct file *fp = (struct file *)f->f_fsdata;
791
792 f->f_fsdata = NULL;
793 if (fp == NULL)
794 return 0;
795
796 if (fp->f_buf)
797 dealloc(fp->f_buf, fp->f_fs->fs_bsize);
798 dealloc(fp->f_fs, SBLOCKSIZE);
799 dealloc(fp, sizeof(struct file));
800 return 0;
801 }
802
803 /*
804 * Copy a portion of a file into kernel memory.
805 * Cross block boundaries when necessary.
806 */
807 __compactcall int
808 ufs_read(struct open_file *f, void *start, size_t size, size_t *resid)
809 {
810 struct file *fp = (struct file *)f->f_fsdata;
811 size_t csize;
812 char *buf;
813 size_t buf_size;
814 int rc = 0;
815 char *addr = start;
816
817 while (size != 0) {
818 if (fp->f_seekp >= (off_t)fp->f_di.di_size)
819 break;
820
821 rc = buf_read_file(f, &buf, &buf_size);
822 if (rc)
823 break;
824
825 csize = size;
826 if (csize > buf_size)
827 csize = buf_size;
828
829 memcpy(addr, buf, csize);
830
831 fp->f_seekp += csize;
832 addr += csize;
833 size -= csize;
834 }
835 if (resid)
836 *resid = size;
837 return rc;
838 }
839
840 /*
841 * Not implemented.
842 */
843 #ifndef LIBSA_NO_FS_WRITE
844 __compactcall int
845 ufs_write(struct open_file *f, void *start, size_t size, size_t *resid)
846 {
847
848 return EROFS;
849 }
850 #endif /* !LIBSA_NO_FS_WRITE */
851
852 #ifndef LIBSA_NO_FS_SEEK
853 __compactcall off_t
854 ufs_seek(struct open_file *f, off_t offset, int where)
855 {
856 struct file *fp = (struct file *)f->f_fsdata;
857
858 switch (where) {
859 case SEEK_SET:
860 fp->f_seekp = offset;
861 break;
862 case SEEK_CUR:
863 fp->f_seekp += offset;
864 break;
865 case SEEK_END:
866 fp->f_seekp = fp->f_di.di_size - offset;
867 break;
868 default:
869 return -1;
870 }
871 return fp->f_seekp;
872 }
873 #endif /* !LIBSA_NO_FS_SEEK */
874
875 __compactcall int
876 ufs_stat(struct open_file *f, struct stat *sb)
877 {
878 struct file *fp = (struct file *)f->f_fsdata;
879
880 /* only important stuff */
881 memset(sb, 0, sizeof *sb);
882 sb->st_mode = fp->f_di.di_mode;
883 sb->st_uid = fp->f_di.di_uid;
884 sb->st_gid = fp->f_di.di_gid;
885 sb->st_size = fp->f_di.di_size;
886 return 0;
887 }
888
889 #if defined(LIBSA_ENABLE_LS_OP)
890 __compactcall void
891 ufs_ls(struct open_file *f, const char *pattern)
892 {
893 struct file *fp = (struct file *)f->f_fsdata;
894 char *buf;
895 size_t buf_size;
896 entry_t *names = 0, *n, **np;
897
898 fp->f_seekp = 0;
899 while (fp->f_seekp < (off_t)fp->f_di.di_size) {
900 struct direct *dp, *edp;
901 int rc = buf_read_file(f, &buf, &buf_size);
902 if (rc)
903 goto out;
904 /* some firmware might use block size larger than DEV_BSIZE */
905 if (buf_size < UFS_DIRBLKSIZ)
906 goto out;
907
908 dp = (struct direct *)buf;
909 edp = (struct direct *)(buf + buf_size);
910
911 for (; dp < edp; dp = (void *)((char *)dp + dp->d_reclen)) {
912 const char *t;
913 if (dp->d_ino == 0)
914 continue;
915
916 if (dp->d_type >= NELEM(typestr) ||
917 !(t = typestr[dp->d_type])) {
918 /*
919 * This does not handle "old"
920 * filesystems properly. On little
921 * endian machines, we get a bogus
922 * type name if the namlen matches a
923 * valid type identifier. We could
924 * check if we read namlen "0" and
925 * handle this case specially, if
926 * there were a pressing need...
927 */
928 printf("bad dir entry\n");
929 goto out;
930 }
931 if (pattern && !fnmatch(dp->d_name, pattern))
932 continue;
933 n = alloc(sizeof *n + strlen(dp->d_name));
934 if (!n) {
935 printf("%d: %s (%s)\n",
936 dp->d_ino, dp->d_name, t);
937 continue;
938 }
939 n->e_ino = dp->d_ino;
940 n->e_type = dp->d_type;
941 strcpy(n->e_name, dp->d_name);
942 for (np = &names; *np; np = &(*np)->e_next) {
943 if (strcmp(n->e_name, (*np)->e_name) < 0)
944 break;
945 }
946 n->e_next = *np;
947 *np = n;
948 }
949 fp->f_seekp += buf_size;
950 }
951
952 if (names) {
953 entry_t *p_names = names;
954 do {
955 n = p_names;
956 printf("%d: %s (%s)\n",
957 n->e_ino, n->e_name, typestr[n->e_type]);
958 p_names = n->e_next;
959 } while (p_names);
960 } else {
961 printf("not found\n");
962 }
963 out:
964 if (names) {
965 do {
966 n = names;
967 names = n->e_next;
968 dealloc(n, 0);
969 } while (names);
970 }
971 }
972 #endif /* LIBSA_ENABLE_LS_OP */
973
974 #ifdef LIBSA_FFSv1
975 /*
976 * Sanity checks for old file systems.
977 *
978 * XXX - goes away some day.
979 * Stripped of stuff libsa doesn't need.....
980 */
981 static void
982 ffs_oldfscompat(struct fs *fs)
983 {
984
985 #ifdef COMPAT_UFS
986 /*
987 * Newer Solaris versions have a slightly incompatible
988 * superblock - so always calculate this values on the fly, which
989 * is good enough for libsa purposes
990 */
991 if (fs->fs_magic == FS_UFS1_MAGIC
992 #ifndef COMPAT_SOLARIS_UFS
993 && fs->fs_old_inodefmt < FS_44INODEFMT
994 #endif
995 ) {
996 fs->fs_qbmask = ~fs->fs_bmask;
997 fs->fs_qfmask = ~fs->fs_fmask;
998 }
999 #endif
1000 }
1001 #endif
1002