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