xref: /openbsd/sys/arch/landisk/stand/xxboot/ufs12.c (revision 6d62b6ec)
1 /*	$OpenBSD: ufs12.c,v 1.1 2022/09/02 10:15:35 miod Exp $	*/
2 /*	$NetBSD: ufs.c,v 1.16 1996/09/30 16:01:22 ws Exp $	*/
3 
4 /*-
5  * Copyright (c) 1993
6  *	The Regents of the University of California.  All rights reserved.
7  *
8  * This code is derived from software contributed to Berkeley by
9  * The Mach Operating System project at Carnegie-Mellon University.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions
13  * are met:
14  * 1. Redistributions of source code must retain the above copyright
15  *    notice, this list of conditions and the following disclaimer.
16  * 2. Redistributions in binary form must reproduce the above copyright
17  *    notice, this list of conditions and the following disclaimer in the
18  *    documentation and/or other materials provided with the distribution.
19  * 3. Neither the name of the University nor the names of its contributors
20  *    may be used to endorse or promote products derived from this software
21  *    without specific prior written permission.
22  *
23  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33  * SUCH DAMAGE.
34  *
35  *
36  * Copyright (c) 1990, 1991 Carnegie Mellon University
37  * All Rights Reserved.
38  *
39  * Author: David Golub
40  *
41  * Permission to use, copy, modify and distribute this software and its
42  * documentation is hereby granted, provided that both the copyright
43  * notice and this permission notice appear in all copies of the
44  * software, derivative works or modified versions, and any portions
45  * thereof, and that both notices appear in supporting documentation.
46  *
47  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
48  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
49  * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
50  *
51  * Carnegie Mellon requests users of this software to return to
52  *
53  *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
54  *  School of Computer Science
55  *  Carnegie Mellon University
56  *  Pittsburgh PA 15213-3890
57  *
58  * any improvements or extensions that they make and grant Carnegie the
59  * rights to redistribute these changes.
60  */
61 
62 /*
63  *	Stand-alone file reading package.
64  */
65 
66 #include <sys/param.h>
67 #include <sys/time.h>
68 #include <sys/stat.h>
69 #include <ufs/ffs/fs.h>
70 #include <ufs/ufs/dinode.h>
71 #include <ufs/ufs/dir.h>
72 #include <lib/libkern/libkern.h>
73 
74 #include <lib/libsa/stand.h>
75 #include "ufs12.h"
76 
77 /*
78  * In-core open file.
79  */
80 struct file {
81 	int		f_is2;		/* 0 if ufs1, nonzero if ufs2 */
82 	off_t		f_seekp;	/* seek pointer */
83 	struct fs	*f_fs;		/* pointer to super-block */
84 	union {
85 		struct ufs1_dinode i1;
86 		struct ufs2_dinode i2;
87 	}		f_di;		/* copy of on-disk inode */
88 	ufsino_t	f_ino;		/* our inode number */
89 	int		f_nindir[NIADDR];
90 					/* number of blocks mapped by
91 					   indirect block at level i */
92 	char		*f_blk[NIADDR];	/* buffer for indirect block at
93 					   level i */
94 	size_t		f_blksize[NIADDR];
95 					/* size of buffer */
96 	daddr_t		f_blkno[NIADDR];/* disk address of block in buffer */
97 	char		*f_buf;		/* buffer for data block */
98 	size_t		f_buf_size;	/* size of data block */
99 	daddr_t		f_buf_blkno;	/* block number of data block */
100 };
101 
102 static int	read_inode(ufsino_t, struct open_file *);
103 #if 0
104 static int	chmod_inode(ufsino_t, struct open_file *, mode_t);
105 #endif
106 static int	block_map(struct open_file *, daddr_t, daddr_t *);
107 static int	buf_read_file(struct open_file *, char **, size_t *);
108 static int	search_directory(char *, struct open_file *, ufsino_t *);
109 static int	ufs12_close_internal(struct file *);
110 #ifdef COMPAT_UFS
111 static void	ffs_oldfscompat(struct fs *);
112 #endif
113 
114 /*
115  * Read a new inode into a file structure.
116  */
117 static int
read_inode(ufsino_t inumber,struct open_file * f)118 read_inode(ufsino_t inumber, struct open_file *f)
119 {
120 	struct file *fp = (struct file *)f->f_fsdata;
121 	struct fs *fs = fp->f_fs;
122 	char *buf;
123 	size_t rsize;
124 	int rc;
125 
126 	/*
127 	 * Read inode and save it.
128 	 */
129 	buf = alloc(fs->fs_bsize);
130 	twiddle();
131 	rc = (f->f_dev->dv_strategy)(f->f_devdata, F_READ,
132 	    fsbtodb(fs, ino_to_fsba(fs, inumber)), fs->fs_bsize, buf, &rsize);
133 	if (rc)
134 		goto out;
135 	if (rsize != (size_t)fs->fs_bsize) {
136 		rc = EIO;
137 		goto out;
138 	}
139 
140 	if (fp->f_is2) {
141 		struct ufs2_dinode *dp;
142 
143 		dp = (struct ufs2_dinode *)buf;
144 		fp->f_di.i2 = dp[ino_to_fsbo(fs, inumber)];
145 	} else {
146 		struct ufs1_dinode *dp;
147 
148 		dp = (struct ufs1_dinode *)buf;
149 		fp->f_di.i1 = dp[ino_to_fsbo(fs, inumber)];
150 	}
151 
152 	/*
153 	 * Clear out the old buffers
154 	 */
155 	{
156 		int level;
157 
158 		for (level = 0; level < NIADDR; level++)
159 			fp->f_blkno[level] = -1;
160 		fp->f_buf_blkno = -1;
161 		fp->f_seekp = 0;
162 	}
163 out:
164 	free(buf, fs->fs_bsize);
165 	return (rc);
166 }
167 
168 #if 0
169 /*
170  * Read a new inode into a file structure.
171  */
172 static int
173 chmod_inode(ufsino_t inumber, struct open_file *f, mode_t mode)
174 {
175 	struct file *fp = (struct file *)f->f_fsdata;
176 	struct fs *fs = fp->f_fs;
177 	char *buf;
178 	size_t rsize;
179 	int rc;
180 
181 	/*
182 	 * Read inode and save it.
183 	 */
184 	buf = alloc(fs->fs_bsize);
185 	twiddle();
186 	rc = (f->f_dev->dv_strategy)(f->f_devdata, F_READ,
187 	    fsbtodb(fs, ino_to_fsba(fs, inumber)), fs->fs_bsize, buf, &rsize);
188 	if (rc)
189 		goto out;
190 	if (rsize != (size_t)fs->fs_bsize) {
191 		rc = EIO;
192 		goto out;
193 	}
194 
195 	if (fp->f_is2) {
196 		struct ufs2_dinode *dp;
197 
198 		dp = &((struct ufs2_dinode *)buf)[ino_to_fsbo(fs, inumber)];
199 		dp->di_mode = mode;
200 	} else {
201 		struct ufs1_dinode *dp;
202 
203 		dp = &((struct ufs1_dinode *)buf)[ino_to_fsbo(fs, inumber)];
204 		dp->di_mode = mode;
205 	}
206 
207 	twiddle();
208 	rc = (f->f_dev->dv_strategy)(f->f_devdata, F_WRITE,
209 	    fsbtodb(fs, ino_to_fsba(fs, inumber)), fs->fs_bsize, buf, NULL);
210 
211 out:
212 	free(buf, fs->fs_bsize);
213 	return (rc);
214 }
215 #endif
216 
217 /*
218  * Given an offset in a file, find the disk block number that
219  * contains that block.
220  */
221 static int
block_map(struct open_file * f,daddr_t file_block,daddr_t * disk_block_p)222 block_map(struct open_file *f, daddr_t file_block, daddr_t *disk_block_p)
223 {
224 	struct file *fp = (struct file *)f->f_fsdata;
225 	daddr_t ind_block_num, *ind_p;
226 	struct fs *fs = fp->f_fs;
227 	int level, idx, rc;
228 
229 	/*
230 	 * Index structure of an inode:
231 	 *
232 	 * di_db[0..NDADDR-1]	hold block numbers for blocks
233 	 *			0..NDADDR-1
234 	 *
235 	 * di_ib[0]		index block 0 is the single indirect block
236 	 *			holds block numbers for blocks
237 	 *			NDADDR .. NDADDR + NINDIR(fs)-1
238 	 *
239 	 * di_ib[1]		index block 1 is the double indirect block
240 	 *			holds block numbers for INDEX blocks for blocks
241 	 *			NDADDR + NINDIR(fs) ..
242 	 *			NDADDR + NINDIR(fs) + NINDIR(fs)**2 - 1
243 	 *
244 	 * di_ib[2]		index block 2 is the triple indirect block
245 	 *			holds block numbers for double-indirect
246 	 *			blocks for blocks
247 	 *			NDADDR + NINDIR(fs) + NINDIR(fs)**2 ..
248 	 *			NDADDR + NINDIR(fs) + NINDIR(fs)**2
249 	 *				+ NINDIR(fs)**3 - 1
250 	 */
251 
252 	if (file_block < NDADDR) {
253 		/* Direct block. */
254 		if (fp->f_is2)
255 			*disk_block_p = fp->f_di.i2.di_db[file_block];
256 		else
257 			*disk_block_p = fp->f_di.i1.di_db[file_block];
258 		return (0);
259 	}
260 
261 	file_block -= NDADDR;
262 
263 	/*
264 	 * nindir[0] = NINDIR
265 	 * nindir[1] = NINDIR**2
266 	 * nindir[2] = NINDIR**3
267 	 *	etc
268 	 */
269 	for (level = 0; level < NIADDR; level++) {
270 		if (file_block < fp->f_nindir[level])
271 			break;
272 		file_block -= fp->f_nindir[level];
273 	}
274 	if (level == NIADDR) {
275 		/* Block number too high */
276 		return (EFBIG);
277 	}
278 
279 	if (fp->f_is2)
280 		ind_block_num = fp->f_di.i2.di_ib[level];
281 	else
282 		ind_block_num = fp->f_di.i1.di_ib[level];
283 
284 	for (; level >= 0; level--) {
285 		if (ind_block_num == 0) {
286 			*disk_block_p = 0;	/* missing */
287 			return (0);
288 		}
289 
290 		if (fp->f_blkno[level] != ind_block_num) {
291 			if (fp->f_blk[level] == NULL)
292 				fp->f_blk[level] =
293 				    alloc(fs->fs_bsize);
294 			twiddle();
295 			rc = (f->f_dev->dv_strategy)(f->f_devdata, F_READ,
296 			    fsbtodb(fp->f_fs, ind_block_num), fs->fs_bsize,
297 			    fp->f_blk[level], &fp->f_blksize[level]);
298 			if (rc)
299 				return (rc);
300 			if (fp->f_blksize[level] != (size_t)fs->fs_bsize)
301 				return (EIO);
302 			fp->f_blkno[level] = ind_block_num;
303 		}
304 
305 		ind_p = (daddr_t *)fp->f_blk[level];
306 
307 		if (level > 0) {
308 			idx = file_block / fp->f_nindir[level - 1];
309 			file_block %= fp->f_nindir[level - 1];
310 		} else
311 			idx = file_block;
312 
313 		ind_block_num = ind_p[idx];
314 	}
315 
316 	*disk_block_p = ind_block_num;
317 	return (0);
318 }
319 
320 /*
321  * Read a portion of a file into an internal buffer.  Return
322  * the location in the buffer and the amount in the buffer.
323  */
324 static int
buf_read_file(struct open_file * f,char ** buf_p,size_t * size_p)325 buf_read_file(struct open_file *f, char **buf_p, size_t *size_p)
326 {
327 	struct file *fp = (struct file *)f->f_fsdata;
328 	struct fs *fs = fp->f_fs;
329 	daddr_t file_block, disk_block;
330 	size_t block_size;
331 	long off;
332 	int rc;
333 	u_int64_t fsize;
334 
335 	off = blkoff(fs, fp->f_seekp);
336 	file_block = lblkno(fs, fp->f_seekp);
337 	if (fp->f_is2)
338 		block_size = dblksize(fs, &fp->f_di.i2, (u_int64_t)file_block);
339 	else
340 		block_size = dblksize(fs, &fp->f_di.i1, (u_int64_t)file_block);
341 
342 	if (file_block != fp->f_buf_blkno) {
343 		rc = block_map(f, file_block, &disk_block);
344 		if (rc)
345 			return (rc);
346 
347 		if (fp->f_buf == NULL)
348 			fp->f_buf = alloc(fs->fs_bsize);
349 
350 		if (disk_block == 0) {
351 			bzero(fp->f_buf, block_size);
352 			fp->f_buf_size = block_size;
353 		} else {
354 			twiddle();
355 			rc = (f->f_dev->dv_strategy)(f->f_devdata, F_READ,
356 			    fsbtodb(fs, disk_block),
357 			    block_size, fp->f_buf, &fp->f_buf_size);
358 			if (rc)
359 				return (rc);
360 		}
361 
362 		fp->f_buf_blkno = file_block;
363 	}
364 
365 	/*
366 	 * Return address of byte in buffer corresponding to
367 	 * offset, and size of remainder of buffer after that
368 	 * byte.
369 	 */
370 	*buf_p = fp->f_buf + off;
371 	*size_p = block_size - off;
372 
373 	/*
374 	 * But truncate buffer at end of file.
375 	 */
376 	if (fp->f_is2)
377 		fsize = fp->f_di.i2.di_size;
378 	else
379 		fsize = fp->f_di.i1.di_size;
380 	if (*size_p > fsize - fp->f_seekp)
381 		*size_p = fsize - fp->f_seekp;
382 
383 	return (0);
384 }
385 
386 /*
387  * Search a directory for a name and return its
388  * i_number.
389  */
390 static int
search_directory(char * name,struct open_file * f,ufsino_t * inumber_p)391 search_directory(char *name, struct open_file *f, ufsino_t *inumber_p)
392 {
393 	struct file *fp = (struct file *)f->f_fsdata;
394 	int namlen, length, rc;
395 	struct direct *dp, *edp;
396 	size_t buf_size;
397 	char *buf;
398 	u_int64_t fsize;
399 
400 	length = strlen(name);
401 
402 	fp->f_seekp = 0;
403 	if (fp->f_is2)
404 		fsize = fp->f_di.i2.di_size;
405 	else
406 		fsize = fp->f_di.i1.di_size;
407 	while ((u_int64_t)fp->f_seekp < fsize) {
408 		rc = buf_read_file(f, &buf, &buf_size);
409 		if (rc)
410 			return (rc);
411 
412 		dp = (struct direct *)buf;
413 		edp = (struct direct *)(buf + buf_size);
414 		while (dp < edp) {
415 			if (dp->d_ino == 0)
416 				goto next;
417 #if BYTE_ORDER == LITTLE_ENDIAN
418 			if (fp->f_fs->fs_maxsymlinklen <= 0)
419 				namlen = dp->d_type;
420 			else
421 #endif
422 				namlen = dp->d_namlen;
423 			if (namlen == length &&
424 			    !strcmp(name, dp->d_name)) {
425 				/* found entry */
426 				*inumber_p = dp->d_ino;
427 				return (0);
428 			}
429 		next:
430 			dp = (struct direct *)((char *)dp + dp->d_reclen);
431 		}
432 		fp->f_seekp += buf_size;
433 	}
434 	return (ENOENT);
435 }
436 
437 /*
438  * Open a file.
439  */
440 int
ufs12_open(char * path,struct open_file * f)441 ufs12_open(char *path, struct open_file *f)
442 {
443 	char namebuf[MAXPATHLEN+1], *cp, *ncp, *buf = NULL;
444 	ufsino_t inumber, parent_inumber;
445 	int rc, c, nlinks = 0;
446 	struct file *fp;
447 	size_t buf_size;
448 	struct fs *fs;
449 	u_int16_t mode;
450 
451 	/* allocate file system specific data structure */
452 	fp = alloc(sizeof(struct file));
453 	bzero(fp, sizeof(struct file));
454 	f->f_fsdata = (void *)fp;
455 
456 	/* allocate space and read super block */
457 	fs = alloc(SBSIZE);
458 	fp->f_fs = fs;
459 	fp->f_is2 = 0;
460 	twiddle();
461 	rc = (f->f_dev->dv_strategy)(f->f_devdata, F_READ,
462 	    SBLOCK, SBSIZE, (char *)fs, &buf_size);
463 	if (rc)
464 		goto out;
465 
466 	if (buf_size != SBSIZE || fs->fs_magic != FS_MAGIC ||
467 	    (size_t)fs->fs_bsize > MAXBSIZE ||
468 	    (size_t)fs->fs_bsize < sizeof(struct fs)) {
469 		/* try ufs2 */
470 		rc = (f->f_dev->dv_strategy)(f->f_devdata, F_READ,
471 		    SBLOCK_UFS2 / DEV_BSIZE, SBSIZE, (char *)fs, &buf_size);
472 		if (rc)
473 			goto out;
474 
475 		if (buf_size != SBSIZE || fs->fs_magic != FS_UFS2_MAGIC ||
476 		    (u_int64_t)fs->fs_bsize > MAXBSIZE ||
477 		    (u_int64_t)fs->fs_bsize < sizeof(struct fs)) {
478 			rc = EINVAL;
479 			goto out;
480 		}
481 		fp->f_is2 = 1;
482 	}
483 #ifdef COMPAT_UFS
484 	ffs_oldfscompat(fs);
485 #endif
486 
487 	/*
488 	 * Calculate indirect block levels.
489 	 */
490 	{
491 		int mult;
492 		int level;
493 
494 		mult = 1;
495 		for (level = 0; level < NIADDR; level++) {
496 			mult *= NINDIR(fs);
497 			fp->f_nindir[level] = mult;
498 		}
499 	}
500 
501 	inumber = ROOTINO;
502 	if ((rc = read_inode(inumber, f)) != 0)
503 		goto out;
504 
505 	cp = path;
506 	while (*cp) {
507 
508 		/*
509 		 * Remove extra separators
510 		 */
511 		while (*cp == '/')
512 			cp++;
513 		if (*cp == '\0')
514 			break;
515 
516 		/*
517 		 * Check that current node is a directory.
518 		 */
519 		if (fp->f_is2)
520 			mode = fp->f_di.i2.di_mode;
521 		else
522 			mode = fp->f_di.i1.di_mode;
523 		if ((mode & IFMT) != IFDIR) {
524 			rc = ENOTDIR;
525 			goto out;
526 		}
527 
528 		/*
529 		 * Get next component of path name.
530 		 */
531 		{
532 			int len = 0;
533 
534 			ncp = cp;
535 			while ((c = *cp) != '\0' && c != '/') {
536 				if (++len > MAXNAMLEN) {
537 					rc = ENOENT;
538 					goto out;
539 				}
540 				cp++;
541 			}
542 			*cp = '\0';
543 		}
544 
545 		/*
546 		 * Look up component in current directory.
547 		 * Save directory inumber in case we find a
548 		 * symbolic link.
549 		 */
550 		parent_inumber = inumber;
551 		rc = search_directory(ncp, f, &inumber);
552 		*cp = c;
553 		if (rc)
554 			goto out;
555 
556 		/*
557 		 * Open next component.
558 		 */
559 		if ((rc = read_inode(inumber, f)) != 0)
560 			goto out;
561 
562 		/*
563 		 * Check for symbolic link.
564 		 */
565 		if (fp->f_is2)
566 			mode = fp->f_di.i2.di_mode;
567 		else
568 			mode = fp->f_di.i1.di_mode;
569 		if ((mode & IFMT) == IFLNK) {
570 			u_int64_t link_len;
571 			size_t len;
572 
573 			if (fp->f_is2)
574 				link_len = fp->f_di.i2.di_size;
575 			else
576 				link_len = fp->f_di.i1.di_size;
577 			len = strlen(cp);
578 
579 			if (link_len + len > MAXPATHLEN ||
580 			    ++nlinks > MAXSYMLINKS) {
581 				rc = ENOENT;
582 				goto out;
583 			}
584 
585 			bcopy(cp, &namebuf[link_len], len + 1);
586 
587 			if (link_len < (u_int64_t)fs->fs_maxsymlinklen) {
588 				if (fp->f_is2) {
589 					bcopy(fp->f_di.i2.di_shortlink, namebuf,
590 					    link_len);
591 				} else {
592 					bcopy(fp->f_di.i1.di_shortlink, namebuf,
593 					    link_len);
594 				}
595 			} else {
596 				/*
597 				 * Read file for symbolic link
598 				 */
599 				daddr_t disk_block;
600 				fs = fp->f_fs;
601 
602 				if (!buf)
603 					buf = alloc(fs->fs_bsize);
604 				rc = block_map(f, (daddr_t)0, &disk_block);
605 				if (rc)
606 					goto out;
607 
608 				twiddle();
609 				rc = (f->f_dev->dv_strategy)(f->f_devdata,
610 				    F_READ, fsbtodb(fs, disk_block),
611 				    fs->fs_bsize, buf, &buf_size);
612 				if (rc)
613 					goto out;
614 
615 				bcopy(buf, namebuf, link_len);
616 			}
617 
618 			/*
619 			 * If relative pathname, restart at parent directory.
620 			 * If absolute pathname, restart at root.
621 			 */
622 			cp = namebuf;
623 			if (*cp != '/')
624 				inumber = parent_inumber;
625 			else
626 				inumber = ROOTINO;
627 
628 			if ((rc = read_inode(inumber, f)) != 0)
629 				goto out;
630 		}
631 	}
632 
633 	/*
634 	 * Found terminal component.
635 	 */
636 	fp->f_ino = inumber;
637 	rc = 0;
638 out:
639 	if (buf)
640 		free(buf, fs->fs_bsize);
641 	if (rc)
642 		(void)ufs12_close_internal(fp);
643 
644 	return (rc);
645 }
646 
647 int
ufs12_close(struct open_file * f)648 ufs12_close(struct open_file *f)
649 {
650 	struct file *fp = (struct file *)f->f_fsdata;
651 
652 	f->f_fsdata = NULL;
653 	if (fp == NULL)
654 		return (0);
655 
656 	return (ufs12_close_internal(fp));
657 }
658 
659 static int
ufs12_close_internal(struct file * fp)660 ufs12_close_internal(struct file *fp)
661 {
662 	int level;
663 
664 	for (level = 0; level < NIADDR; level++) {
665 		if (fp->f_blk[level])
666 			free(fp->f_blk[level], fp->f_fs->fs_bsize);
667 	}
668 	if (fp->f_buf)
669 		free(fp->f_buf, fp->f_fs->fs_bsize);
670 	free(fp->f_fs, SBSIZE);
671 	free(fp, sizeof(struct file));
672 	return (0);
673 }
674 
675 /*
676  * Copy a portion of a file into kernel memory.
677  * Cross block boundaries when necessary.
678  */
679 int
ufs12_read(struct open_file * f,void * start,size_t size,size_t * resid)680 ufs12_read(struct open_file *f, void *start, size_t size, size_t *resid)
681 {
682 	struct file *fp = (struct file *)f->f_fsdata;
683 	char *buf, *addr = start;
684 	size_t csize, buf_size;
685 	u_int64_t fsize;
686 	int rc = 0;
687 
688 	while (size != 0) {
689 		if (fp->f_is2)
690 			fsize = fp->f_di.i2.di_size;
691 		else
692 			fsize = fp->f_di.i1.di_size;
693 		if ((u_int64_t)fp->f_seekp >= fsize)
694 			break;
695 
696 		rc = buf_read_file(f, &buf, &buf_size);
697 		if (rc)
698 			break;
699 
700 		csize = size;
701 		if (csize > buf_size)
702 			csize = buf_size;
703 
704 		bcopy(buf, addr, csize);
705 
706 		fp->f_seekp += csize;
707 		addr += csize;
708 		size -= csize;
709 	}
710 	if (resid)
711 		*resid = size;
712 	return (rc);
713 }
714 
715 /*
716  * Not implemented.
717  */
718 int
ufs12_write(struct open_file * f,void * start,size_t size,size_t * resid)719 ufs12_write(struct open_file *f, void *start, size_t size, size_t *resid)
720 {
721 
722 	return (EROFS);
723 }
724 
725 off_t
ufs12_seek(struct open_file * f,off_t offset,int where)726 ufs12_seek(struct open_file *f, off_t offset, int where)
727 {
728 	struct file *fp = (struct file *)f->f_fsdata;
729 	u_int64_t fsize;
730 
731 	switch (where) {
732 	case SEEK_SET:
733 		fp->f_seekp = offset;
734 		break;
735 	case SEEK_CUR:
736 		fp->f_seekp += offset;
737 		break;
738 	case SEEK_END:
739 		if (fp->f_is2)
740 			fsize = fp->f_di.i2.di_size;
741 		else
742 			fsize = fp->f_di.i1.di_size;
743 		fp->f_seekp = fsize - offset;
744 		break;
745 	default:
746 		return (-1);
747 	}
748 	return (fp->f_seekp);
749 }
750 
751 int
ufs12_stat(struct open_file * f,struct stat * sb)752 ufs12_stat(struct open_file *f, struct stat *sb)
753 {
754 	struct file *fp = (struct file *)f->f_fsdata;
755 
756 	/* only important stuff */
757 	if (fp->f_is2) {
758 		sb->st_mode = fp->f_di.i2.di_mode;
759 		sb->st_uid = fp->f_di.i2.di_uid;
760 		sb->st_gid = fp->f_di.i2.di_gid;
761 		sb->st_size = fp->f_di.i2.di_size;
762 	} else {
763 		sb->st_mode = fp->f_di.i1.di_mode;
764 		sb->st_uid = fp->f_di.i1.di_uid;
765 		sb->st_gid = fp->f_di.i1.di_gid;
766 		sb->st_size = fp->f_di.i1.di_size;
767 	}
768 	return (0);
769 }
770 
771 int
ufs12_fchmod(struct open_file * f,mode_t mode)772 ufs12_fchmod(struct open_file *f, mode_t mode)
773 {
774 #if 0
775 	struct file *fp = (struct file *)f->f_fsdata;
776 
777 	return chmod_inode(fp->f_ino, f, mode);
778 #else
779 	return EIO;
780 #endif
781 }
782 
783 #ifndef	NO_READDIR
784 int
ufs12_readdir(struct open_file * f,char * name)785 ufs12_readdir(struct open_file *f, char *name)
786 {
787 #if 0
788 	struct file *fp = (struct file *)f->f_fsdata;
789 	struct direct *dp, *edp;
790 	size_t buf_size;
791 	int rc, namlen;
792 	char *buf;
793 	u_int64_t fsize;
794 
795 	if (name == NULL)
796 		fp->f_seekp = 0;
797 	else {
798 			/* end of dir */
799 		if (fp->f_is2)
800 			fsize = fp->f_di.i2.di_size;
801 		else
802 			fsize = fp->f_di.i1.di_size;
803 		if ((u_int64_t)fp->f_seekp >= fsize) {
804 			*name = '\0';
805 			return -1;
806 		}
807 
808 		do {
809 			if ((rc = buf_read_file(f, &buf, &buf_size)) != 0)
810 				return rc;
811 
812 			dp = (struct direct *)buf;
813 			edp = (struct direct *)(buf + buf_size);
814 			while (dp < edp && dp->d_ino == 0)
815 				dp = (struct direct *)((char *)dp + dp->d_reclen);
816 			fp->f_seekp += buf_size -
817 			    ((u_int8_t *)edp - (u_int8_t *)dp);
818 		} while (dp >= edp);
819 
820 #if BYTE_ORDER == LITTLE_ENDIAN
821 		if (fp->f_fs->fs_maxsymlinklen <= 0)
822 			namlen = dp->d_type;
823 		else
824 #endif
825 			namlen = dp->d_namlen;
826 		strncpy(name, dp->d_name, namlen + 1);
827 
828 		fp->f_seekp += dp->d_reclen;
829 	}
830 
831 	return 0;
832 #else
833 	return EIO;
834 #endif
835 }
836 #endif
837 
838 #ifdef COMPAT_UFS
839 /*
840  * Sanity checks for old file systems.
841  *
842  * XXX - goes away some day.
843  */
844 static void
ffs_oldfscompat(struct fs * fs)845 ffs_oldfscompat(struct fs *fs)
846 {
847 	int i;
848 
849 	fs->fs_npsect = max(fs->fs_npsect, fs->fs_nsect);	/* XXX */
850 	fs->fs_interleave = max(fs->fs_interleave, 1);		/* XXX */
851 	if (fs->fs_postblformat == FS_42POSTBLFMT)		/* XXX */
852 		fs->fs_nrpos = 8;				/* XXX */
853 	if (fs->fs_inodefmt < FS_44INODEFMT) {			/* XXX */
854 		quad_t sizepb = fs->fs_bsize;			/* XXX */
855 								/* XXX */
856 		fs->fs_maxfilesize = fs->fs_bsize * NDADDR - 1;	/* XXX */
857 		for (i = 0; i < NIADDR; i++) {			/* XXX */
858 			sizepb *= NINDIR(fs);			/* XXX */
859 			fs->fs_maxfilesize += sizepb;		/* XXX */
860 		}						/* XXX */
861 		fs->fs_qbmask = ~fs->fs_bmask;			/* XXX */
862 		fs->fs_qfmask = ~fs->fs_fmask;			/* XXX */
863 	}							/* XXX */
864 }
865 #endif
866