readufs_ffs.c revision 1.15 1 /* $NetBSD: readufs_ffs.c,v 1.15 2022/11/17 06:40:39 chs Exp $ */
2 /* from Id: readufs_ffs.c,v 1.6 2003/04/08 09:19:32 itohy Exp */
3
4 /*
5 * FS specific support for 4.2BSD Fast Filesystem
6 *
7 * Written in 1999, 2002, 2003 by ITOH Yasufumi.
8 * Public domain.
9 *
10 * Intended to be used for boot programs (first stage).
11 * DON'T ADD ANY FANCY FEATURE. THIS SHALL BE COMPACT.
12 */
13
14 #include "readufs.h"
15
16 #include <ufs/ffs/fs.h>
17
18 static int get_ffs_inode(ino32_t ino, union ufs_dinode *dibuf);
19
20 #define fsi (*ufsinfo)
21 #define fsi_ffs fsi.fs_u.u_ffs
22
23 /*
24 * Read and check superblock.
25 * If it is an FFS, save information from the superblock.
26 */
27 int
28 try_ffs(void)
29 {
30 union {
31 struct fs sblk;
32 unsigned char pad[SBLOCKSIZE];
33 } buf;
34 struct ufs_info *ufsinfo = &ufs_info;
35 static const int sblocs[] = SBLOCKSEARCH;
36 const int *sbl;
37 int magic;
38
39 #ifdef DEBUG_WITH_STDIO
40 printf("trying FFS\n");
41 #endif
42 /* read FFS superblock */
43 for (sbl = sblocs; ; sbl++) {
44 if (*sbl == -1)
45 return 1;
46
47 RAW_READ(&buf, (daddr_t) btodb(*sbl), SBLOCKSIZE);
48
49 magic = buf.sblk.fs_magic;
50 #ifdef DEBUG_WITH_STDIO
51 printf("FFS: sblk: pos %d magic 0x%x\n", btodb(*sbl), magic);
52 #endif
53 #ifdef USE_UFS1
54 if (magic == FS_UFS1_MAGIC
55 && !(buf.sblk.fs_old_flags & FS_FLAGS_UPDATED)) {
56 if (*sbl == SBLOCK_UFS2)
57 /* might be an alternate suberblock */
58 continue;
59 break;
60 }
61 #endif
62 if (*sbl != buf.sblk.fs_sblockloc)
63 /* must be an alternate suberblock */
64 continue;
65
66 #ifdef USE_UFS1
67 if (magic == FS_UFS1_MAGIC) {
68 break;
69 }
70 #endif
71 #ifdef USE_UFS2
72 if (magic == FS_UFS2_MAGIC || magic == FS_UFS2EA_MAGIC) {
73 #ifdef USE_UFS1
74 fsi.ufstype = UFSTYPE_UFS2;
75 #endif
76 break;
77 }
78 #endif
79 }
80
81 /*
82 * XXX <ufs/ffs/fs.h> always uses fs_magic
83 * (UFS1 only or UFS2 only is impossible)
84 */
85 fsi_ffs.magic = magic;
86 #ifdef DEBUG_WITH_STDIO
87 printf("FFS: detected UFS%d format\n",
88 (magic == FS_UFS2_MAGIC || magic == FS_UFS2EA_MAGIC) + 1);
89 #endif
90
91 /* This partition looks like an FFS. */
92 fsi.fstype = UFSTYPE_FFS;
93 fsi.get_inode = get_ffs_inode;
94
95 /* Get information from the superblock. */
96 fsi.bsize = buf.sblk.fs_bsize;
97 fsi.fsbtodb = buf.sblk.fs_fsbtodb;
98 fsi.nindir = buf.sblk.fs_nindir;
99
100 fsi_ffs.iblkno = buf.sblk.fs_iblkno;
101 fsi_ffs.old_cgoffset = buf.sblk.fs_old_cgoffset;
102 fsi_ffs.old_cgmask = buf.sblk.fs_old_cgmask;
103 fsi_ffs.fragshift = buf.sblk.fs_fragshift;
104 fsi_ffs.inopb = buf.sblk.fs_inopb;
105 fsi_ffs.ipg = buf.sblk.fs_ipg;
106 fsi_ffs.fpg = buf.sblk.fs_fpg;
107
108 return 0;
109 }
110
111 /* for inode macros */
112 #define fs_ipg fs_u.u_ffs.ipg
113 #define fs_iblkno fs_u.u_ffs.iblkno
114 #define fs_old_cgoffset fs_u.u_ffs.old_cgoffset
115 #define fs_old_cgmask fs_u.u_ffs.old_cgmask
116 #define fs_fpg fs_u.u_ffs.fpg
117 #define fs_magic fs_u.u_ffs.magic
118 #define fs_inopb fs_u.u_ffs.inopb
119 #define fs_fragshift fs_u.u_ffs.fragshift
120 #define fs_fsbtodb fsbtodb
121
122 /*
123 * Get inode from disk.
124 */
125 static int
126 get_ffs_inode(ino32_t ino, union ufs_dinode *dibuf)
127 {
128 struct ufs_info *ufsinfo = &ufs_info;
129 union ufs_dinode *buf = alloca((size_t) fsi.bsize);
130 union ufs_dinode *di;
131 unsigned ioff;
132
133 RAW_READ(buf, FFS_FSBTODB(&fsi, ino_to_fsba(&fsi, ino)),
134 (size_t) fsi.bsize);
135
136 ioff = ino_to_fsbo(&fsi, ino);
137
138 #if defined(USE_UFS1) && defined(USE_UFS2)
139 if (ufsinfo->ufstype == UFSTYPE_UFS1)
140 di = (void *) &(&buf->di1)[ioff];
141 else {
142 di = (void *) &(&buf->di2)[ioff];
143
144 /* XXX for DI_SIZE() macro */
145 di->di1.di_size = di->di2.di_size;
146 }
147 #else
148 di = &buf[ioff];
149 #endif
150
151 #ifdef DEBUG_WITH_STDIO
152 printf("FFS: dinode(%d): mode 0%o, nlink %d, size %u\n",
153 ino, di->di_common.di_mode, di->di_common.di_nlink,
154 (unsigned) DI_SIZE(di));
155 #endif
156
157 if (di->di_common.di_mode == 0)
158 return 1; /* unused inode (file is not found) */
159
160 *dibuf = *di;
161
162 return 0;
163 }
164