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