| @@ -1,975 +1,1062 @@ | | | @@ -1,975 +1,1062 @@ |
1 | /* $NetBSD: ufs.c,v 1.79 2021/05/12 08:45:28 mrg Exp $ */ | | 1 | /* $NetBSD: ufs.c,v 1.80 2021/05/27 06:54:44 mrg Exp $ */ |
2 | | | 2 | |
3 | /*- | | 3 | /*- |
4 | * Copyright (c) 1993 | | 4 | * Copyright (c) 1993 |
5 | * The Regents of the University of California. All rights reserved. | | 5 | * The Regents of the University of California. All rights reserved. |
6 | * | | 6 | * |
7 | * This code is derived from software contributed to Berkeley by | | 7 | * This code is derived from software contributed to Berkeley by |
8 | * The Mach Operating System project at Carnegie-Mellon University. | | 8 | * The Mach Operating System project at Carnegie-Mellon University. |
9 | * | | 9 | * |
10 | * Redistribution and use in source and binary forms, with or without | | 10 | * Redistribution and use in source and binary forms, with or without |
11 | * modification, are permitted provided that the following conditions | | 11 | * modification, are permitted provided that the following conditions |
12 | * are met: | | 12 | * are met: |
13 | * 1. Redistributions of source code must retain the above copyright | | 13 | * 1. Redistributions of source code must retain the above copyright |
14 | * notice, this list of conditions and the following disclaimer. | | 14 | * notice, this list of conditions and the following disclaimer. |
15 | * 2. Redistributions in binary form must reproduce the above copyright | | 15 | * 2. Redistributions in binary form must reproduce the above copyright |
16 | * notice, this list of conditions and the following disclaimer in the | | 16 | * notice, this list of conditions and the following disclaimer in the |
17 | * documentation and/or other materials provided with the distribution. | | 17 | * documentation and/or other materials provided with the distribution. |
18 | * 3. Neither the name of the University nor the names of its contributors | | 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 | | 19 | * may be used to endorse or promote products derived from this software |
20 | * without specific prior written permission. | | 20 | * without specific prior written permission. |
21 | * | | 21 | * |
22 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND | | 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 | | 23 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
24 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | | 24 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
25 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE | | 25 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE |
26 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | | 26 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
27 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | | 27 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
28 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | | 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 | | 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 | | 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 | | 31 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
32 | * SUCH DAMAGE. | | 32 | * SUCH DAMAGE. |
33 | * | | 33 | * |
34 | * | | 34 | * |
35 | * Copyright (c) 1990, 1991 Carnegie Mellon University | | 35 | * Copyright (c) 1990, 1991 Carnegie Mellon University |
36 | * All Rights Reserved. | | 36 | * All Rights Reserved. |
37 | * | | 37 | * |
38 | * Author: David Golub | | 38 | * Author: David Golub |
39 | * | | 39 | * |
40 | * Permission to use, copy, modify and distribute this software and its | | 40 | * Permission to use, copy, modify and distribute this software and its |
41 | * documentation is hereby granted, provided that both the copyright | | 41 | * documentation is hereby granted, provided that both the copyright |
42 | * notice and this permission notice appear in all copies of the | | 42 | * notice and this permission notice appear in all copies of the |
43 | * software, derivative works or modified versions, and any portions | | 43 | * software, derivative works or modified versions, and any portions |
44 | * thereof, and that both notices appear in supporting documentation. | | 44 | * thereof, and that both notices appear in supporting documentation. |
45 | * | | 45 | * |
46 | * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" | | 46 | * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" |
47 | * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR | | 47 | * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR |
48 | * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. | | 48 | * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. |
49 | * | | 49 | * |
50 | * Carnegie Mellon requests users of this software to return to | | 50 | * Carnegie Mellon requests users of this software to return to |
51 | * | | 51 | * |
52 | * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU | | 52 | * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU |
53 | * School of Computer Science | | 53 | * School of Computer Science |
54 | * Carnegie Mellon University | | 54 | * Carnegie Mellon University |
55 | * Pittsburgh PA 15213-3890 | | 55 | * Pittsburgh PA 15213-3890 |
56 | * | | 56 | * |
57 | * any improvements or extensions that they make and grant Carnegie the | | 57 | * any improvements or extensions that they make and grant Carnegie the |
58 | * rights to redistribute these changes. | | 58 | * rights to redistribute these changes. |
59 | */ | | 59 | */ |
60 | | | 60 | |
61 | /* | | 61 | /* |
62 | * Stand-alone file reading package for UFS and LFS filesystems. | | 62 | * Stand-alone file reading package for UFS and LFS filesystems. |
63 | */ | | 63 | */ |
64 | | | 64 | |
65 | #include <sys/param.h> | | 65 | #include <sys/param.h> |
66 | #include <sys/time.h> | | 66 | #include <sys/time.h> |
67 | #include <ufs/ufs/dinode.h> | | 67 | #include <ufs/ufs/dinode.h> |
68 | #include <ufs/ufs/dir.h> | | 68 | #include <ufs/ufs/dir.h> |
69 | #ifdef LIBSA_LFS | | 69 | #ifdef LIBSA_LFS |
70 | #include <sys/queue.h> | | 70 | #include <sys/queue.h> |
71 | #include <sys/condvar.h> | | 71 | #include <sys/condvar.h> |
72 | #include <sys/mount.h> /* XXX for MNAMELEN */ | | 72 | #include <sys/mount.h> /* XXX for MNAMELEN */ |
73 | #include <ufs/lfs/lfs.h> | | 73 | #include <ufs/lfs/lfs.h> |
74 | #else | | 74 | #else |
75 | #include <ufs/ffs/fs.h> | | 75 | #include <ufs/ffs/fs.h> |
76 | #endif | | 76 | #endif |
77 | #ifdef _STANDALONE | | 77 | #ifdef _STANDALONE |
78 | #include <lib/libkern/libkern.h> | | 78 | #include <lib/libkern/libkern.h> |
79 | #else | | 79 | #else |
80 | #include <string.h> | | 80 | #include <string.h> |
81 | #endif | | 81 | #endif |
82 | | | 82 | |
83 | #include "stand.h" | | 83 | #include "stand.h" |
84 | #ifdef LIBSA_LFS | | 84 | #ifdef LIBSA_LFS |
85 | #include "lfs.h" | | 85 | #include "lfs.h" |
86 | #else | | 86 | #else |
87 | #include "ufs.h" | | 87 | #include "ufs.h" |
88 | #endif | | 88 | #endif |
89 | | | 89 | |
90 | /* If this file is compiled by itself, build ufs (aka ffsv1) support */ | | 90 | /* If this file is compiled by itself, build ufs (aka ffsv1) support */ |
91 | #if !defined(LIBSA_FFSv2) && !defined(LIBSA_LFS) | | 91 | #if !defined(LIBSA_FFSv2) && !defined(LIBSA_LFS) |
92 | #define LIBSA_FFSv1 | | 92 | #define LIBSA_FFSv1 |
93 | #endif | | 93 | #endif |
94 | | | 94 | |
95 | #if defined(LIBSA_FS_SINGLECOMPONENT) && !defined(LIBSA_NO_FS_SYMLINK) | | 95 | #if defined(LIBSA_FS_SINGLECOMPONENT) && !defined(LIBSA_NO_FS_SYMLINK) |
96 | #define LIBSA_NO_FS_SYMLINK | | 96 | #define LIBSA_NO_FS_SYMLINK |
97 | #endif | | 97 | #endif |
98 | #if defined(COMPAT_UFS) && defined(LIBSA_NO_COMPAT_UFS) | | 98 | #if defined(COMPAT_UFS) && defined(LIBSA_NO_COMPAT_UFS) |
99 | #undef COMPAT_UFS | | 99 | #undef COMPAT_UFS |
100 | #endif | | 100 | #endif |
101 | | | 101 | |
102 | #ifdef LIBSA_LFS | | 102 | #ifdef LIBSA_LFS |
| | | 103 | /* Do not (yet) support FFS_EI on LFS. */ |
| | | 104 | #undef LIBSA_FFS_EI |
103 | /* | | 105 | /* |
104 | * In-core LFS superblock - just the on-disk one. | | 106 | * In-core LFS superblock - just the on-disk one. |
105 | */ | | 107 | */ |
106 | struct salfs { | | 108 | struct salfs { |
107 | union { | | 109 | union { |
108 | struct dlfs u_32; | | 110 | struct dlfs u_32; |
109 | struct dlfs64 u_64; | | 111 | struct dlfs64 u_64; |
110 | } lfs_dlfs_u; | | 112 | } lfs_dlfs_u; |
111 | unsigned lfs_is64 : 1, | | 113 | unsigned lfs_is64 : 1, |
112 | lfs_dobyteswap : 1, | | 114 | lfs_dobyteswap : 1, |
113 | lfs_hasolddirfmt : 1; | | 115 | lfs_hasolddirfmt : 1; |
114 | }; | | 116 | }; |
115 | /* Get lfs accessors that use struct salfs. */ | | 117 | /* Get lfs accessors that use struct salfs. */ |
116 | #define STRUCT_LFS struct salfs | | 118 | #define STRUCT_LFS struct salfs |
117 | #include <ufs/lfs/lfs_accessors.h> | | 119 | #include <ufs/lfs/lfs_accessors.h> |
118 | | | 120 | |
119 | /* override this to avoid a mess with the dinode accessors */ | | 121 | /* override this to avoid a mess with the dinode accessors */ |
120 | #define lfs_dino_getsize(fs, dp) ((dp)->di_size) | | 122 | #define lfs_dino_getsize(fs, dp) ((dp)->di_size) |
121 | | | 123 | |
122 | typedef struct salfs FS; | | 124 | typedef struct salfs FS; |
123 | #define fs_magic lfs_dlfs_u.u_32.dlfs_magic | | 125 | #define fs_magic lfs_dlfs_u.u_32.dlfs_magic |
124 | #define fs_maxsymlinklen lfs_dlfs_u.u_32.dlfs_maxsymlinklen | | 126 | #define fs_maxsymlinklen lfs_dlfs_u.u_32.dlfs_maxsymlinklen |
125 | #define lfs_version lfs_dlfs_u.u_32.dlfs_version | | 127 | #define lfs_version lfs_dlfs_u.u_32.dlfs_version |
126 | | | 128 | |
127 | #define FS_MAGIC LFS_MAGIC | | | |
128 | #define SBLOCKSIZE LFS_SBPAD | | 129 | #define SBLOCKSIZE LFS_SBPAD |
129 | #define SBLOCKOFFSET LFS_LABELPAD | | 130 | #define SBLOCKOFFSET LFS_LABELPAD |
130 | #else | | 131 | #else |
131 | /* NB ufs2 doesn't use the common superblock code... */ | | 132 | /* NB ufs2 doesn't use the common superblock code... */ |
132 | typedef struct fs FS; | | 133 | typedef struct fs FS; |
133 | #define FS_MAGIC FS_UFS1_MAGIC | | | |
134 | #define SBLOCKOFFSET SBLOCK_UFS1 | | 134 | #define SBLOCKOFFSET SBLOCK_UFS1 |
135 | #endif | | 135 | #endif |
136 | | | 136 | |
137 | #if defined(LIBSA_NO_TWIDDLE) | | 137 | #if defined(LIBSA_NO_TWIDDLE) |
138 | #define twiddle() | | 138 | #define twiddle() |
139 | #endif | | 139 | #endif |
140 | | | 140 | |
141 | #undef cgstart | | 141 | #undef cgstart |
142 | #if defined(LIBSA_FFSv2) | | 142 | #if defined(LIBSA_FFSv2) |
143 | #define cgstart(fc, c) cgstart_ufs2((fs), (c)) | | 143 | #define cgstart(fc, c) cgstart_ufs2((fs), (c)) |
144 | #else | | 144 | #else |
145 | #define cgstart(fc, c) cgstart_ufs1((fs), (c)) | | 145 | #define cgstart(fc, c) cgstart_ufs1((fs), (c)) |
146 | #endif | | 146 | #endif |
147 | | | 147 | |
148 | #ifndef ufs_dinode | | 148 | #ifndef ufs_dinode |
149 | #define ufs_dinode ufs1_dinode | | 149 | #define ufs_dinode ufs1_dinode |
150 | #endif | | 150 | #endif |
151 | #ifndef indp_t | | 151 | #ifndef indp_t |
152 | #define indp_t int32_t | | 152 | #define indp_t int32_t |
153 | #endif | | 153 | #endif |
154 | typedef uint32_t ino32_t; | | 154 | typedef uint32_t ino32_t; |
155 | | | 155 | |
156 | #ifndef FSBTODB | | 156 | #ifndef FSBTODB |
157 | #define FSBTODB(fs, indp) FFS_FSBTODB(fs, indp) | | 157 | #define FSBTODB(fs, indp) FFS_FSBTODB(fs, indp) |
158 | #endif | | 158 | #endif |
| | | 159 | #ifndef FS_MAGIC |
| | | 160 | #define FS_MAGIC FS_UFS1_MAGIC |
| | | 161 | #endif |
159 | #ifndef UFS_NINDIR | | 162 | #ifndef UFS_NINDIR |
160 | #define UFS_NINDIR FFS_NINDIR | | 163 | #define UFS_NINDIR FFS_NINDIR |
161 | #endif | | 164 | #endif |
162 | #ifndef ufs_blkoff | | 165 | #ifndef ufs_blkoff |
163 | #define ufs_blkoff ffs_blkoff | | 166 | #define ufs_blkoff ffs_blkoff |
164 | #endif | | 167 | #endif |
165 | #ifndef ufs_lblkno | | 168 | #ifndef ufs_lblkno |
166 | #define ufs_lblkno ffs_lblkno | | 169 | #define ufs_lblkno ffs_lblkno |
167 | #endif | | 170 | #endif |
| | | 171 | #ifndef ufs_dinode_swap |
| | | 172 | #define ufs_dinode_swap ffs_dinode1_swap |
| | | 173 | #endif |
| | | 174 | #ifndef ufs_indp_swap |
| | | 175 | #define ufs_indp_swap bswap32 |
| | | 176 | #endif |
168 | | | 177 | |
169 | /* | | 178 | /* |
170 | * To avoid having a lot of filesystem-block sized buffers lurking (which | | 179 | * To avoid having a lot of filesystem-block sized buffers lurking (which |
171 | * could be 32k) we only keep a few entries of the indirect block map. | | 180 | * could be 32k) we only keep a few entries of the indirect block map. |
172 | * With 8k blocks, 2^8 blocks is ~500k so we reread the indirect block | | 181 | * With 8k blocks, 2^8 blocks is ~500k so we reread the indirect block |
173 | * ~13 times pulling in a 6M kernel. | | 182 | * ~13 times pulling in a 6M kernel. |
174 | * The cache size must be smaller than the smallest filesystem block, | | 183 | * The cache size must be smaller than the smallest filesystem block, |
175 | * so LN2_IND_CACHE_SZ <= 9 (UFS2 and 4k blocks). | | 184 | * so LN2_IND_CACHE_SZ <= 9 (UFS2 and 4k blocks). |
176 | */ | | 185 | */ |
177 | #define LN2_IND_CACHE_SZ 6 | | 186 | #define LN2_IND_CACHE_SZ 6 |
178 | #define IND_CACHE_SZ (1 << LN2_IND_CACHE_SZ) | | 187 | #define IND_CACHE_SZ (1 << LN2_IND_CACHE_SZ) |
179 | #define IND_CACHE_MASK (IND_CACHE_SZ - 1) | | 188 | #define IND_CACHE_MASK (IND_CACHE_SZ - 1) |
180 | | | 189 | |
181 | /* | | 190 | /* |
182 | * In-core open file. | | 191 | * In-core open file. |
183 | */ | | 192 | */ |
184 | struct file { | | 193 | struct file { |
185 | off_t f_seekp; /* seek pointer */ | | 194 | off_t f_seekp; /* seek pointer */ |
186 | FS *f_fs; /* pointer to super-block */ | | 195 | FS *f_fs; /* pointer to super-block */ |
187 | struct ufs_dinode f_di; /* copy of on-disk inode */ | | 196 | struct ufs_dinode f_di; /* copy of on-disk inode */ |
188 | uint f_nishift; /* for blocks in indirect block */ | | 197 | uint f_nishift; /* for blocks in indirect block */ |
189 | indp_t f_ind_cache_block; | | 198 | indp_t f_ind_cache_block; |
190 | indp_t f_ind_cache[IND_CACHE_SZ]; | | 199 | indp_t f_ind_cache[IND_CACHE_SZ]; |
191 | | | 200 | |
192 | char *f_buf; /* buffer for data block */ | | 201 | char *f_buf; /* buffer for data block */ |
193 | size_t f_buf_size; /* size of data block */ | | 202 | size_t f_buf_size; /* size of data block */ |
194 | daddr_t f_buf_blkno; /* block number of data block */ | | 203 | daddr_t f_buf_blkno; /* block number of data block */ |
| | | 204 | #if defined(LIBSA_FFS_EI) |
| | | 205 | bool f_swapped; /* FFS is other endian */ |
| | | 206 | #endif |
195 | }; | | 207 | }; |
196 | | | 208 | |
197 | static int read_inode(ino32_t, struct open_file *); | | 209 | static int read_inode(ino32_t, struct open_file *); |
198 | static int block_map(struct open_file *, indp_t, indp_t *); | | 210 | static int block_map(struct open_file *, indp_t, indp_t *); |
199 | static int buf_read_file(struct open_file *, char **, size_t *); | | 211 | static int buf_read_file(struct open_file *, char **, size_t *); |
200 | static int search_directory(const char *, int, struct open_file *, ino32_t *); | | 212 | static int search_directory(const char *, int, struct open_file *, ino32_t *); |
201 | #ifdef LIBSA_FFSv1 | | 213 | #ifdef LIBSA_FFSv1 |
202 | static void ffs_oldfscompat(FS *); | | 214 | static void ffs_oldfscompat(FS *); |
203 | #endif | | 215 | #endif |
204 | | | 216 | |
| | | 217 | static __inline__ bool |
| | | 218 | ffs_is_magic(FS *fs) |
| | | 219 | { |
| | | 220 | return fs->fs_magic == FS_MAGIC; |
| | | 221 | } |
| | | 222 | |
| | | 223 | static __inline__ void |
| | | 224 | ffs_fix_magic_swapped(struct file *fp, FS *fs) |
| | | 225 | { |
| | | 226 | #ifdef LIBSA_FFS_EI |
| | | 227 | fp->f_swapped = fs->fs_magic == bswap32(FS_MAGIC); |
| | | 228 | if (fp->f_swapped) |
| | | 229 | { |
| | | 230 | ffs_sb_swap(fs, fs); |
| | | 231 | } |
| | | 232 | #endif |
| | | 233 | } |
| | | 234 | |
| | | 235 | #ifdef LIBSA_FFS_EI |
| | | 236 | static __inline__ bool |
| | | 237 | ffs_swapped(struct file *fp) |
| | | 238 | { |
| | | 239 | return fp->f_swapped; |
| | | 240 | } |
| | | 241 | #endif |
| | | 242 | |
| | | 243 | static __inline__ uint16_t |
| | | 244 | ffs_get_reclen(struct file *fp, struct direct *dp) |
| | | 245 | { |
| | | 246 | #ifdef LIBSA_FFS_EI |
| | | 247 | if (ffs_swapped(fp)) |
| | | 248 | return bswap16(dp->d_reclen); |
| | | 249 | #endif |
| | | 250 | return dp->d_reclen; |
| | | 251 | } |
| | | 252 | |
| | | 253 | static __inline__ uint32_t |
| | | 254 | ffs_get_ino(struct file *fp, struct direct *dp) |
| | | 255 | { |
| | | 256 | #ifdef LIBSA_FFS_EI |
| | | 257 | if (ffs_swapped(fp)) |
| | | 258 | return bswap32(dp->d_ino); |
| | | 259 | #endif |
| | | 260 | return dp->d_ino; |
| | | 261 | } |
| | | 262 | |
205 | | | 263 | |
206 | #ifdef LIBSA_LFS | | 264 | #ifdef LIBSA_LFS |
207 | /* | | 265 | /* |
208 | * Find an inode's block. Look it up in the ifile. Whee! | | 266 | * Find an inode's block. Look it up in the ifile. Whee! |
209 | */ | | 267 | */ |
210 | static int | | 268 | static int |
211 | find_inode_sector(ino32_t inumber, struct open_file *f, daddr_t *isp) | | 269 | find_inode_sector(ino32_t inumber, struct open_file *f, daddr_t *isp) |
212 | { | | 270 | { |
213 | struct file *fp = (struct file *)f->f_fsdata; | | 271 | struct file *fp = (struct file *)f->f_fsdata; |
214 | FS *fs = fp->f_fs; | | 272 | FS *fs = fp->f_fs; |
215 | daddr_t ifileent_blkno; | | 273 | daddr_t ifileent_blkno; |
216 | char *ent_in_buf; | | 274 | char *ent_in_buf; |
217 | size_t buf_after_ent; | | 275 | size_t buf_after_ent; |
218 | size_t entsize; | | 276 | size_t entsize; |
219 | int rc; | | 277 | int rc; |
220 | | | 278 | |
221 | rc = read_inode(LFS_IFILE_INUM, f); | | 279 | rc = read_inode(LFS_IFILE_INUM, f); |
222 | if (rc) | | 280 | if (rc) |
223 | return rc; | | 281 | return rc; |
224 | | | 282 | |
225 | entsize = fs->lfs_is64 ? sizeof(IFILE64) : | | 283 | entsize = fs->lfs_is64 ? sizeof(IFILE64) : |
226 | (lfs_sb_getversion(fs) > 1 ? sizeof(IFILE32) : sizeof(IFILE_V1)); | | 284 | (lfs_sb_getversion(fs) > 1 ? sizeof(IFILE32) : sizeof(IFILE_V1)); |
227 | ifileent_blkno = | | 285 | ifileent_blkno = |
228 | (inumber / lfs_sb_getifpb(fs)) + lfs_sb_getcleansz(fs) + lfs_sb_getsegtabsz(fs); | | 286 | (inumber / lfs_sb_getifpb(fs)) + lfs_sb_getcleansz(fs) + lfs_sb_getsegtabsz(fs); |
229 | fp->f_seekp = (off_t)ifileent_blkno * lfs_sb_getbsize(fs) + | | 287 | fp->f_seekp = (off_t)ifileent_blkno * lfs_sb_getbsize(fs) + |
230 | (inumber % lfs_sb_getifpb(fs)) * entsize; | | 288 | (inumber % lfs_sb_getifpb(fs)) * entsize; |
231 | rc = buf_read_file(f, &ent_in_buf, &buf_after_ent); | | 289 | rc = buf_read_file(f, &ent_in_buf, &buf_after_ent); |
232 | if (rc) | | 290 | if (rc) |
233 | return rc; | | 291 | return rc; |
234 | /* make sure something's not badly wrong, but don't panic. */ | | 292 | /* make sure something's not badly wrong, but don't panic. */ |
235 | if (buf_after_ent < entsize) | | 293 | if (buf_after_ent < entsize) |
236 | return EINVAL; | | 294 | return EINVAL; |
237 | | | 295 | |
238 | *isp = FSBTODB(fs, lfs_if_getdaddr(fs, (IFILE *)ent_in_buf)); | | 296 | *isp = FSBTODB(fs, lfs_if_getdaddr(fs, (IFILE *)ent_in_buf)); |
239 | if (*isp == LFS_UNUSED_DADDR) /* again, something badly wrong */ | | 297 | if (*isp == LFS_UNUSED_DADDR) /* again, something badly wrong */ |
240 | return EINVAL; | | 298 | return EINVAL; |
241 | return 0; | | 299 | return 0; |
242 | } | | 300 | } |
243 | #endif | | 301 | #endif |
244 | | | 302 | |
245 | /* | | 303 | /* |
246 | * Read a new inode into a file structure. | | 304 | * Read a new inode into a file structure. |
247 | */ | | 305 | */ |
248 | static int | | 306 | static int |
249 | read_inode(ino32_t inumber, struct open_file *f) | | 307 | read_inode(ino32_t inumber, struct open_file *f) |
250 | { | | 308 | { |
251 | struct file *fp = (struct file *)f->f_fsdata; | | 309 | struct file *fp = (struct file *)f->f_fsdata; |
252 | FS *fs = fp->f_fs; | | 310 | FS *fs = fp->f_fs; |
253 | char *buf; | | 311 | char *buf; |
254 | size_t rsize; | | 312 | size_t rsize; |
255 | int rc; | | 313 | int rc; |
256 | daddr_t inode_sector = 0; /* XXX: gcc */ | | 314 | daddr_t inode_sector = 0; /* XXX: gcc */ |
257 | #ifdef LIBSA_LFS | | 315 | #ifdef LIBSA_LFS |
258 | struct ufs_dinode *dip; | | 316 | struct ufs_dinode *dip; |
259 | int cnt; | | 317 | int cnt; |
260 | #endif | | 318 | #endif |
261 | | | 319 | |
262 | #ifdef LIBSA_LFS | | 320 | #ifdef LIBSA_LFS |
263 | if (inumber == LFS_IFILE_INUM) | | 321 | if (inumber == LFS_IFILE_INUM) |
264 | inode_sector = FSBTODB(fs, lfs_sb_getidaddr(fs)); | | 322 | inode_sector = FSBTODB(fs, lfs_sb_getidaddr(fs)); |
265 | else if ((rc = find_inode_sector(inumber, f, &inode_sector)) != 0) | | 323 | else if ((rc = find_inode_sector(inumber, f, &inode_sector)) != 0) |
266 | return rc; | | 324 | return rc; |
267 | #else | | 325 | #else |
268 | inode_sector = FSBTODB(fs, ino_to_fsba(fs, inumber)); | | 326 | inode_sector = FSBTODB(fs, ino_to_fsba(fs, inumber)); |
269 | #endif | | 327 | #endif |
270 | | | 328 | |
271 | /* | | 329 | /* |
272 | * Read inode and save it. | | 330 | * Read inode and save it. |
273 | */ | | 331 | */ |
274 | buf = fp->f_buf; | | 332 | buf = fp->f_buf; |
275 | twiddle(); | | 333 | twiddle(); |
276 | rc = DEV_STRATEGY(f->f_dev)(f->f_devdata, F_READ, | | 334 | rc = DEV_STRATEGY(f->f_dev)(f->f_devdata, F_READ, |
277 | inode_sector, fs->fs_bsize, buf, &rsize); | | 335 | inode_sector, fs->fs_bsize, buf, &rsize); |
278 | if (rc) | | 336 | if (rc) |
279 | return rc; | | 337 | return rc; |
280 | if (rsize != (size_t)fs->fs_bsize) | | 338 | if (rsize != (size_t)fs->fs_bsize) |
281 | return EIO; | | 339 | return EIO; |
282 | | | 340 | |
283 | #ifdef LIBSA_LFS | | 341 | #ifdef LIBSA_LFS |
284 | cnt = INOPBx(fs); | | 342 | cnt = INOPBx(fs); |
285 | dip = (struct ufs_dinode *)buf + (cnt - 1); | | 343 | dip = (struct ufs_dinode *)buf + (cnt - 1); |
286 | for (; dip->di_inumber != inumber; --dip) { | | 344 | for (; dip->di_inumber != inumber; --dip) { |
287 | /* kernel code panics, but boot blocks which panic are Bad. */ | | 345 | /* kernel code panics, but boot blocks which panic are Bad. */ |
288 | if (--cnt == 0) | | 346 | if (--cnt == 0) |
289 | return EINVAL; | | 347 | return EINVAL; |
290 | } | | 348 | } |
291 | fp->f_di = *dip; | | 349 | fp->f_di = *dip; |
292 | #else | | 350 | #else |
293 | fp->f_di = ((struct ufs_dinode *)buf)[ino_to_fsbo(fs, inumber)]; | | 351 | fp->f_di = ((struct ufs_dinode *)buf)[ino_to_fsbo(fs, inumber)]; |
| | | 352 | #ifdef LIBSA_FFS_EI |
| | | 353 | if (ffs_swapped(fp)) |
| | | 354 | ufs_dinode_swap(&fp->f_di, &fp->f_di); |
| | | 355 | #endif |
294 | #endif | | 356 | #endif |
295 | | | 357 | |
296 | /* | | 358 | /* |
297 | * Clear out the old buffers | | 359 | * Clear out the old buffers |
298 | */ | | 360 | */ |
299 | fp->f_ind_cache_block = ~0; | | 361 | fp->f_ind_cache_block = ~0; |
300 | fp->f_buf_blkno = -1; | | 362 | fp->f_buf_blkno = -1; |
301 | return rc; | | 363 | return rc; |
302 | } | | 364 | } |
303 | | | 365 | |
304 | /* | | 366 | /* |
305 | * Given an offset in a file, find the disk block number that | | 367 | * Given an offset in a file, find the disk block number that |
306 | * contains that block. | | 368 | * contains that block. |
307 | */ | | 369 | */ |
308 | static int | | 370 | static int |
309 | block_map(struct open_file *f, indp_t file_block, indp_t *disk_block_p) | | 371 | block_map(struct open_file *f, indp_t file_block, indp_t *disk_block_p) |
310 | { | | 372 | { |
311 | struct file *fp = (struct file *)f->f_fsdata; | | 373 | struct file *fp = (struct file *)f->f_fsdata; |
312 | FS *fs = fp->f_fs; | | 374 | FS *fs = fp->f_fs; |
313 | uint level; | | 375 | uint level; |
314 | indp_t ind_cache; | | 376 | indp_t ind_cache; |
315 | indp_t ind_block_num; | | 377 | indp_t ind_block_num; |
316 | size_t rsize; | | 378 | size_t rsize; |
317 | int rc; | | 379 | int rc; |
318 | indp_t *buf = (void *)fp->f_buf; | | 380 | indp_t *buf = (void *)fp->f_buf; |
319 | | | 381 | |
320 | /* | | 382 | /* |
321 | * Index structure of an inode: | | 383 | * Index structure of an inode: |
322 | * | | 384 | * |
323 | * di_db[0..UFS_NDADDR-1] hold block numbers for blocks | | 385 | * di_db[0..UFS_NDADDR-1] hold block numbers for blocks |
324 | * 0..UFS_NDADDR-1 | | 386 | * 0..UFS_NDADDR-1 |
325 | * | | 387 | * |
326 | * di_ib[0] index block 0 is the single indirect block | | 388 | * di_ib[0] index block 0 is the single indirect block |
327 | * holds block numbers for blocks | | 389 | * holds block numbers for blocks |
328 | * UFS_NDADDR .. UFS_NDADDR + UFS_NINDIR(fs)-1 | | 390 | * UFS_NDADDR .. UFS_NDADDR + UFS_NINDIR(fs)-1 |
329 | * | | 391 | * |
330 | * di_ib[1] index block 1 is the double indirect block | | 392 | * di_ib[1] index block 1 is the double indirect block |
331 | * holds block numbers for INDEX blocks for blocks | | 393 | * holds block numbers for INDEX blocks for blocks |
332 | * UFS_NDADDR + UFS_NINDIR(fs) .. | | 394 | * UFS_NDADDR + UFS_NINDIR(fs) .. |
333 | * UFS_NDADDR + UFS_NINDIR(fs) + UFS_NINDIR(fs)**2 - 1 | | 395 | * UFS_NDADDR + UFS_NINDIR(fs) + UFS_NINDIR(fs)**2 - 1 |
334 | * | | 396 | * |
335 | * di_ib[2] index block 2 is the triple indirect block | | 397 | * di_ib[2] index block 2 is the triple indirect block |
336 | * holds block numbers for double-indirect | | 398 | * holds block numbers for double-indirect |
337 | * blocks for blocks | | 399 | * blocks for blocks |
338 | * UFS_NDADDR + UFS_NINDIR(fs) + UFS_NINDIR(fs)**2 .. | | 400 | * UFS_NDADDR + UFS_NINDIR(fs) + UFS_NINDIR(fs)**2 .. |
339 | * UFS_NDADDR + UFS_NINDIR(fs) + UFS_NINDIR(fs)**2 | | 401 | * UFS_NDADDR + UFS_NINDIR(fs) + UFS_NINDIR(fs)**2 |
340 | * + UFS_NINDIR(fs)**3 - 1 | | 402 | * + UFS_NINDIR(fs)**3 - 1 |
341 | */ | | 403 | */ |
342 | | | 404 | |
343 | if (file_block < UFS_NDADDR) { | | 405 | if (file_block < UFS_NDADDR) { |
344 | /* Direct block. */ | | 406 | /* Direct block. */ |
345 | *disk_block_p = fp->f_di.di_db[file_block]; | | 407 | *disk_block_p = fp->f_di.di_db[file_block]; |
346 | return 0; | | 408 | return 0; |
347 | } | | 409 | } |
348 | | | 410 | |
349 | file_block -= UFS_NDADDR; | | 411 | file_block -= UFS_NDADDR; |
350 | | | 412 | |
351 | ind_cache = file_block >> LN2_IND_CACHE_SZ; | | 413 | ind_cache = file_block >> LN2_IND_CACHE_SZ; |
352 | if (ind_cache == fp->f_ind_cache_block) { | | 414 | if (ind_cache == fp->f_ind_cache_block) { |
353 | *disk_block_p = fp->f_ind_cache[file_block & IND_CACHE_MASK]; | | 415 | *disk_block_p = fp->f_ind_cache[file_block & IND_CACHE_MASK]; |
354 | return 0; | | 416 | return 0; |
355 | } | | 417 | } |
356 | | | 418 | |
357 | for (level = 0;;) { | | 419 | for (level = 0;;) { |
358 | level += fp->f_nishift; | | 420 | level += fp->f_nishift; |
359 | if (file_block < (indp_t)1 << level) | | 421 | if (file_block < (indp_t)1 << level) |
360 | break; | | 422 | break; |
361 | if (level > UFS_NIADDR * fp->f_nishift) | | 423 | if (level > UFS_NIADDR * fp->f_nishift) |
362 | /* Block number too high */ | | 424 | /* Block number too high */ |
363 | return EFBIG; | | 425 | return EFBIG; |
364 | file_block -= (indp_t)1 << level; | | 426 | file_block -= (indp_t)1 << level; |
365 | } | | 427 | } |
366 | | | 428 | |
367 | ind_block_num = fp->f_di.di_ib[level / fp->f_nishift - 1]; | | 429 | ind_block_num = fp->f_di.di_ib[level / fp->f_nishift - 1]; |
368 | | | 430 | |
369 | for (;;) { | | 431 | for (;;) { |
370 | level -= fp->f_nishift; | | 432 | level -= fp->f_nishift; |
371 | if (ind_block_num == 0) { | | 433 | if (ind_block_num == 0) { |
372 | *disk_block_p = 0; /* missing */ | | 434 | *disk_block_p = 0; /* missing */ |
373 | return 0; | | 435 | return 0; |
374 | } | | 436 | } |
375 | | | 437 | |
376 | twiddle(); | | 438 | twiddle(); |
377 | /* | | 439 | /* |
378 | * If we were feeling brave, we could work out the number | | 440 | * If we were feeling brave, we could work out the number |
379 | * of the disk sector and read a single disk sector instead | | 441 | * of the disk sector and read a single disk sector instead |
380 | * of a filesystem block. | | 442 | * of a filesystem block. |
381 | * However we don't do this very often anyway... | | 443 | * However we don't do this very often anyway... |
382 | */ | | 444 | */ |
383 | rc = DEV_STRATEGY(f->f_dev)(f->f_devdata, F_READ, | | 445 | rc = DEV_STRATEGY(f->f_dev)(f->f_devdata, F_READ, |
384 | FSBTODB(fp->f_fs, ind_block_num), fs->fs_bsize, | | 446 | FSBTODB(fp->f_fs, ind_block_num), fs->fs_bsize, |
385 | buf, &rsize); | | 447 | buf, &rsize); |
386 | if (rc) | | 448 | if (rc) |
387 | return rc; | | 449 | return rc; |
388 | if (rsize != (size_t)fs->fs_bsize) | | 450 | if (rsize != (size_t)fs->fs_bsize) |
389 | return EIO; | | 451 | return EIO; |
390 | ind_block_num = buf[file_block >> level]; | | 452 | #ifdef LIBSA_FFS_EI |
| | | 453 | if (ffs_swapped(fp)) |
| | | 454 | ind_block_num = ufs_indp_swap(buf[file_block >> level]); |
| | | 455 | else |
| | | 456 | #endif |
| | | 457 | ind_block_num = buf[file_block >> level]; |
391 | if (level == 0) | | 458 | if (level == 0) |
392 | break; | | 459 | break; |
393 | file_block &= (1 << level) - 1; | | 460 | file_block &= (1 << level) - 1; |
394 | } | | 461 | } |
395 | | | 462 | |
396 | /* Save the part of the block that contains this sector */ | | 463 | /* Save the part of the block that contains this sector */ |
397 | memcpy(fp->f_ind_cache, &buf[file_block & ~IND_CACHE_MASK], | | 464 | #if defined(LIBSA_FFS_EI) |
398 | IND_CACHE_SZ * sizeof fp->f_ind_cache[0]); | | 465 | if (ffs_swapped(fp)) { |
| | | 466 | size_t i; |
| | | 467 | |
| | | 468 | for (i = 0; i < IND_CACHE_SZ; i++) { |
| | | 469 | fp->f_ind_cache[i] = ufs_indp_swap( |
| | | 470 | buf[(file_block & ~IND_CACHE_MASK) + i]); |
| | | 471 | } |
| | | 472 | } else |
| | | 473 | #endif |
| | | 474 | memcpy(fp->f_ind_cache, &buf[file_block & ~IND_CACHE_MASK], |
| | | 475 | IND_CACHE_SZ * sizeof fp->f_ind_cache[0]); |
399 | fp->f_ind_cache_block = ind_cache; | | 476 | fp->f_ind_cache_block = ind_cache; |
400 | | | 477 | |
401 | *disk_block_p = ind_block_num; | | 478 | *disk_block_p = ind_block_num; |
402 | | | 479 | |
403 | return 0; | | 480 | return 0; |
404 | } | | 481 | } |
405 | | | 482 | |
406 | /* | | 483 | /* |
407 | * Read a portion of a file into an internal buffer. | | 484 | * Read a portion of a file into an internal buffer. |
408 | * Return the location in the buffer and the amount in the buffer. | | 485 | * Return the location in the buffer and the amount in the buffer. |
409 | */ | | 486 | */ |
410 | static int | | 487 | static int |
411 | buf_read_file(struct open_file *f, char **buf_p, size_t *size_p) | | 488 | buf_read_file(struct open_file *f, char **buf_p, size_t *size_p) |
412 | { | | 489 | { |
413 | struct file *fp = (struct file *)f->f_fsdata; | | 490 | struct file *fp = (struct file *)f->f_fsdata; |
414 | FS *fs = fp->f_fs; | | 491 | FS *fs = fp->f_fs; |
415 | long off; | | 492 | long off; |
416 | indp_t file_block; | | 493 | indp_t file_block; |
417 | size_t block_size; | | 494 | size_t block_size; |
418 | int rc; | | 495 | int rc; |
419 | | | 496 | |
420 | off = ufs_blkoff(fs, fp->f_seekp); | | 497 | off = ufs_blkoff(fs, fp->f_seekp); |
421 | file_block = ufs_lblkno(fs, fp->f_seekp); | | 498 | file_block = ufs_lblkno(fs, fp->f_seekp); |
422 | #ifdef LIBSA_LFS | | 499 | #ifdef LIBSA_LFS |
423 | block_size = (size_t)dblksize(fs, &fp->f_di, (uint64_t)file_block); | | 500 | block_size = (size_t)dblksize(fs, &fp->f_di, (uint64_t)file_block); |
424 | #else | | 501 | #else |
425 | block_size = (size_t)ffs_sblksize(fs, (int64_t)fp->f_di.di_size, file_block); | | 502 | block_size = (size_t)ffs_sblksize(fs, (int64_t)fp->f_di.di_size, file_block); |
426 | #endif | | 503 | #endif |
427 | | | 504 | |
428 | if (file_block != fp->f_buf_blkno) { | | 505 | if (file_block != fp->f_buf_blkno) { |
429 | indp_t disk_block = 0; /* XXX: gcc */ | | 506 | indp_t disk_block = 0; /* XXX: gcc */ |
430 | rc = block_map(f, file_block, &disk_block); | | 507 | rc = block_map(f, file_block, &disk_block); |
431 | if (rc) | | 508 | if (rc) |
432 | return rc; | | 509 | return rc; |
433 | | | 510 | |
434 | if (disk_block == 0) { | | 511 | if (disk_block == 0) { |
435 | memset(fp->f_buf, 0, block_size); | | 512 | memset(fp->f_buf, 0, block_size); |
436 | fp->f_buf_size = block_size; | | 513 | fp->f_buf_size = block_size; |
437 | } else { | | 514 | } else { |
438 | twiddle(); | | 515 | twiddle(); |
439 | rc = DEV_STRATEGY(f->f_dev)(f->f_devdata, F_READ, | | 516 | rc = DEV_STRATEGY(f->f_dev)(f->f_devdata, F_READ, |
440 | FSBTODB(fs, disk_block), | | 517 | FSBTODB(fs, disk_block), |
441 | block_size, fp->f_buf, &fp->f_buf_size); | | 518 | block_size, fp->f_buf, &fp->f_buf_size); |
442 | if (rc) | | 519 | if (rc) |
443 | return rc; | | 520 | return rc; |
444 | } | | 521 | } |
445 | | | 522 | |
446 | fp->f_buf_blkno = file_block; | | 523 | fp->f_buf_blkno = file_block; |
447 | } | | 524 | } |
448 | | | 525 | |
449 | /* | | 526 | /* |
450 | * Return address of byte in buffer corresponding to | | 527 | * Return address of byte in buffer corresponding to |
451 | * offset, and size of remainder of buffer after that | | 528 | * offset, and size of remainder of buffer after that |
452 | * byte. | | 529 | * byte. |
453 | */ | | 530 | */ |
454 | *buf_p = fp->f_buf + off; | | 531 | *buf_p = fp->f_buf + off; |
455 | *size_p = block_size - off; | | 532 | *size_p = block_size - off; |
456 | | | 533 | |
457 | /* | | 534 | /* |
458 | * But truncate buffer at end of file. | | 535 | * But truncate buffer at end of file. |
459 | */ | | 536 | */ |
460 | if (*size_p > fp->f_di.di_size - fp->f_seekp) | | 537 | if (*size_p > fp->f_di.di_size - fp->f_seekp) |
461 | *size_p = fp->f_di.di_size - fp->f_seekp; | | 538 | *size_p = fp->f_di.di_size - fp->f_seekp; |
462 | | | 539 | |
463 | return 0; | | 540 | return 0; |
464 | } | | 541 | } |
465 | | | 542 | |
466 | /* | | 543 | /* |
467 | * Search a directory for a name and return its | | 544 | * Search a directory for a name and return its |
468 | * inode number. | | 545 | * inode number. |
469 | */ | | 546 | */ |
470 | static int | | 547 | static int |
471 | search_directory(const char *name, int length, struct open_file *f, | | 548 | search_directory(const char *name, int length, struct open_file *f, |
472 | ino32_t *inumber_p) | | 549 | ino32_t *inumber_p) |
473 | { | | 550 | { |
474 | struct file *fp = (struct file *)f->f_fsdata; | | 551 | struct file *fp = (struct file *)f->f_fsdata; |
475 | struct direct *dp; | | 552 | struct direct *dp; |
476 | struct direct *edp; | | 553 | struct direct *edp; |
477 | char *buf; | | 554 | char *buf; |
478 | size_t buf_size; | | 555 | size_t buf_size; |
479 | int namlen; | | 556 | int namlen; |
480 | int rc; | | 557 | int rc; |
481 | | | 558 | |
482 | fp->f_seekp = 0; | | 559 | fp->f_seekp = 0; |
483 | while (fp->f_seekp < (off_t)fp->f_di.di_size) { | | 560 | while (fp->f_seekp < (off_t)fp->f_di.di_size) { |
484 | rc = buf_read_file(f, &buf, &buf_size); | | 561 | rc = buf_read_file(f, &buf, &buf_size); |
485 | if (rc) | | 562 | if (rc) |
486 | return rc; | | 563 | return rc; |
487 | | | 564 | |
488 | dp = (struct direct *)buf; | | 565 | dp = (struct direct *)buf; |
489 | edp = (struct direct *)(buf + buf_size); | | 566 | edp = (struct direct *)(buf + buf_size); |
490 | for (;dp < edp; dp = (void *)((char *)dp + dp->d_reclen)) { | | 567 | for (; dp < edp; |
491 | if (dp->d_reclen <= 0) | | 568 | dp = (void *)((char *)dp + ffs_get_reclen(fp, dp))) { |
| | | 569 | if (ffs_get_reclen(fp, dp) <= 0) |
492 | break; | | 570 | break; |
493 | if (dp->d_ino == (ino32_t)0) | | 571 | if (ffs_get_ino(fp, dp) == (ino32_t)0) |
494 | continue; | | 572 | continue; |
495 | #if BYTE_ORDER == LITTLE_ENDIAN | | 573 | #if BYTE_ORDER == LITTLE_ENDIAN |
496 | if (fp->f_fs->fs_maxsymlinklen <= 0) | | 574 | if (fp->f_fs->fs_maxsymlinklen <= 0) |
497 | namlen = dp->d_type; | | 575 | namlen = dp->d_type; |
498 | else | | 576 | else |
499 | #endif | | 577 | #endif |
500 | namlen = dp->d_namlen; | | 578 | namlen = dp->d_namlen; |
501 | if (namlen == length && | | 579 | if (namlen == length && |
502 | !memcmp(name, dp->d_name, length)) { | | 580 | !memcmp(name, dp->d_name, length)) { |
503 | /* found entry */ | | 581 | /* found entry */ |
504 | *inumber_p = dp->d_ino; | | 582 | *inumber_p = ffs_get_ino(fp, dp); |
505 | return 0; | | 583 | return 0; |
506 | } | | 584 | } |
507 | } | | 585 | } |
508 | fp->f_seekp += buf_size; | | 586 | fp->f_seekp += buf_size; |
509 | } | | 587 | } |
510 | return ENOENT; | | 588 | return ENOENT; |
511 | } | | 589 | } |
512 | | | 590 | |
513 | static __inline__ int | | 591 | static __inline__ int |
514 | ffs_find_superblock(struct open_file *f, FS *fs) | | 592 | ffs_find_superblock(struct open_file *f, FS *fs) |
515 | { | | 593 | { |
| | | 594 | struct file *fp = (struct file *)f->f_fsdata; |
516 | int rc; | | 595 | int rc; |
517 | size_t buf_size; | | 596 | size_t buf_size; |
518 | #ifdef LIBSA_FFSv2 | | 597 | #ifdef LIBSA_FFSv2 |
519 | static daddr_t sblock_try[] = SBLOCKSEARCH; | | 598 | static daddr_t sblock_try[] = SBLOCKSEARCH; |
520 | int i; | | 599 | int i; |
521 | | | 600 | |
522 | for (i = 0; sblock_try[i] != -1; i++) { | | 601 | for (i = 0; sblock_try[i] != -1; i++) { |
523 | rc = DEV_STRATEGY(f->f_dev)(f->f_devdata, F_READ, | | 602 | rc = DEV_STRATEGY(f->f_dev)(f->f_devdata, F_READ, |
524 | sblock_try[i] / DEV_BSIZE, SBLOCKSIZE, fs, &buf_size); | | 603 | sblock_try[i] / DEV_BSIZE, SBLOCKSIZE, fs, &buf_size); |
525 | if (rc != 0 || buf_size != SBLOCKSIZE) | | 604 | if (rc) |
526 | return rc; | | 605 | return rc; |
| | | 606 | if (buf_size != SBLOCKSIZE) |
| | | 607 | return EINVAL; |
| | | 608 | ffs_fix_magic_swapped(fp, fs); |
527 | if (fs->fs_sblockloc != sblock_try[i]) | | 609 | if (fs->fs_sblockloc != sblock_try[i]) |
528 | /* an alternate superblock - try again */ | | 610 | /* an alternate superblock - try again */ |
529 | continue; | | 611 | continue; |
530 | if (fs->fs_magic == FS_UFS2_MAGIC) { | | 612 | if (ffs_is_magic(fs)) |
531 | return 0; | | 613 | return 0; |
532 | } | | | |
533 | } | | 614 | } |
534 | return EINVAL; | | 615 | return EINVAL; |
535 | #else /* LIBSA_FFSv2 */ | | 616 | #else /* LIBSA_FFSv2 */ |
536 | rc = DEV_STRATEGY(f->f_dev)(f->f_devdata, F_READ, | | 617 | rc = DEV_STRATEGY(f->f_dev)(f->f_devdata, F_READ, |
537 | SBLOCKOFFSET / DEV_BSIZE, SBLOCKSIZE, fs, &buf_size); | | 618 | SBLOCKOFFSET / DEV_BSIZE, SBLOCKSIZE, fs, &buf_size); |
538 | if (rc) | | 619 | if (rc) |
539 | return rc; | | 620 | return rc; |
540 | if (buf_size != SBLOCKSIZE || | | 621 | if (buf_size != SBLOCKSIZE) |
| | | 622 | return EINVAL; |
| | | 623 | ffs_fix_magic_swapped(fp, fs); |
| | | 624 | |
541 | #ifdef LIBSA_LFS | | 625 | #ifdef LIBSA_LFS |
542 | fs->lfs_version != REQUIRED_LFS_VERSION || | | 626 | if (fs->lfs_version != REQUIRED_LFS_VERSION) |
| | | 627 | return EINVAL; |
543 | #endif | | 628 | #endif |
544 | fs->fs_magic != FS_MAGIC) | | 629 | if (!ffs_is_magic(fs)) |
545 | return EINVAL; | | 630 | return EINVAL; |
| | | 631 | |
546 | return 0; | | 632 | return 0; |
547 | #endif /* !LIBSA_FFSv2 */ | | 633 | #endif /* !LIBSA_FFSv2 */ |
548 | } | | 634 | } |
549 | | | 635 | |
550 | /* | | 636 | /* |
551 | * Open a file. | | 637 | * Open a file. |
552 | */ | | 638 | */ |
553 | __compactcall int | | 639 | __compactcall int |
554 | ufs_open(const char *path, struct open_file *f) | | 640 | ufs_open(const char *path, struct open_file *f) |
555 | { | | 641 | { |
556 | #ifndef LIBSA_FS_SINGLECOMPONENT | | 642 | #ifndef LIBSA_FS_SINGLECOMPONENT |
557 | const char *cp, *ncp; | | 643 | const char *cp, *ncp; |
558 | int c; | | 644 | int c; |
559 | #endif | | 645 | #endif |
560 | ino32_t inumber; | | 646 | ino32_t inumber; |
561 | struct file *fp; | | 647 | struct file *fp; |
562 | FS *fs; | | 648 | FS *fs; |
563 | int rc; | | 649 | int rc; |
564 | #ifndef LIBSA_NO_FS_SYMLINK | | 650 | #ifndef LIBSA_NO_FS_SYMLINK |
565 | ino32_t parent_inumber; | | 651 | ino32_t parent_inumber; |
566 | int nlinks = 0; | | 652 | int nlinks = 0; |
567 | char namebuf[MAXPATHLEN+1]; | | 653 | char namebuf[MAXPATHLEN+1]; |
568 | char *buf; | | 654 | char *buf; |
569 | #endif | | 655 | #endif |
570 | | | 656 | |
571 | /* allocate file system specific data structure */ | | 657 | /* allocate file system specific data structure */ |
572 | fp = alloc(sizeof(struct file)); | | 658 | fp = alloc(sizeof(struct file)); |
573 | memset(fp, 0, sizeof(struct file)); | | 659 | memset(fp, 0, sizeof(struct file)); |
574 | f->f_fsdata = (void *)fp; | | 660 | f->f_fsdata = (void *)fp; |
575 | | | 661 | |
576 | /* allocate space and read super block */ | | 662 | /* allocate space and read super block */ |
577 | fs = alloc(SBLOCKSIZE); | | 663 | fs = alloc(SBLOCKSIZE); |
578 | fp->f_fs = fs; | | 664 | fp->f_fs = fs; |
579 | twiddle(); | | 665 | twiddle(); |
580 | | | 666 | |
581 | rc = ffs_find_superblock(f, fs); | | 667 | rc = ffs_find_superblock(f, fs); |
582 | if (rc) | | 668 | if (rc) |
583 | goto out; | | 669 | goto out; |
584 | | | 670 | |
585 | #if defined(LIBSA_LFS) && REQUIRED_LFS_VERSION == 2 | | 671 | #if defined(LIBSA_LFS) && REQUIRED_LFS_VERSION == 2 |
586 | /* | | 672 | /* |
587 | * XXX We should check the second superblock and use the eldest | | 673 | * XXX We should check the second superblock and use the eldest |
588 | * of the two. See comments near the top of lfs_mountfs() | | 674 | * of the two. See comments near the top of lfs_mountfs() |
589 | * in sys/ufs/lfs/lfs_vfsops.c. | | 675 | * in sys/ufs/lfs/lfs_vfsops.c. |
590 | * This may need a LIBSA_LFS_SMALL check as well. | | 676 | * This may need a LIBSA_LFS_SMALL check as well. |
591 | */ | | 677 | */ |
592 | #endif | | 678 | #endif |
593 | #if defined(LIBSA_LFS) | | 679 | #if defined(LIBSA_LFS) |
594 | fs->lfs_is64 = 0; | | 680 | fs->lfs_is64 = 0; |
595 | fs->lfs_dobyteswap = 0; | | 681 | fs->lfs_dobyteswap = 0; |
596 | fs->lfs_hasolddirfmt = (fs->fs_maxsymlinklen <= 0); | | 682 | fs->lfs_hasolddirfmt = (fs->fs_maxsymlinklen <= 0); |
597 | #endif | | 683 | #endif |
598 | #ifdef LIBSA_FFSv1 | | 684 | #ifdef LIBSA_FFSv1 |
599 | ffs_oldfscompat(fs); | | 685 | ffs_oldfscompat(fs); |
600 | #endif | | 686 | #endif |
601 | | | 687 | |
602 | if (fs->fs_bsize > MAXBSIZE || | | 688 | if (fs->fs_bsize > MAXBSIZE || |
603 | (size_t)fs->fs_bsize < sizeof(FS)) { | | 689 | (size_t)fs->fs_bsize < sizeof(FS)) { |
604 | rc = EINVAL; | | 690 | rc = EINVAL; |
605 | goto out; | | 691 | goto out; |
606 | } | | 692 | } |
607 | | | 693 | |
608 | /* | | 694 | /* |
609 | * Calculate indirect block levels. | | 695 | * Calculate indirect block levels. |
610 | */ | | 696 | */ |
611 | { | | 697 | { |
612 | indp_t mult; | | 698 | indp_t mult; |
613 | int ln2; | | 699 | int ln2; |
614 | | | 700 | |
615 | /* | | 701 | /* |
616 | * We note that the number of indirect blocks is always | | 702 | * We note that the number of indirect blocks is always |
617 | * a power of 2. This lets us use shifts and masks instead | | 703 | * a power of 2. This lets us use shifts and masks instead |
618 | * of divide and remainder and avoinds pulling in the | | 704 | * of divide and remainder and avoinds pulling in the |
619 | * 64bit division routine into the boot code. | | 705 | * 64bit division routine into the boot code. |
620 | */ | | 706 | */ |
621 | mult = UFS_NINDIR(fs); | | 707 | mult = UFS_NINDIR(fs); |
622 | #ifdef DEBUG | | 708 | #ifdef DEBUG |
623 | if (mult & (mult - 1)) { | | 709 | if (mult & (mult - 1)) { |
624 | /* Hummm was't a power of 2 */ | | 710 | /* Hummm was't a power of 2 */ |
625 | rc = EINVAL; | | 711 | rc = EINVAL; |
626 | goto out; | | 712 | goto out; |
627 | } | | 713 | } |
628 | #endif | | 714 | #endif |
629 | for (ln2 = 0; mult != 1; ln2++) | | 715 | for (ln2 = 0; mult != 1; ln2++) |
630 | mult >>= 1; | | 716 | mult >>= 1; |
631 | | | 717 | |
632 | fp->f_nishift = ln2; | | 718 | fp->f_nishift = ln2; |
633 | } | | 719 | } |
634 | | | 720 | |
635 | /* alloc a block sized buffer used for all fs transfers */ | | 721 | /* alloc a block sized buffer used for all fs transfers */ |
636 | fp->f_buf = alloc(fs->fs_bsize); | | 722 | fp->f_buf = alloc(fs->fs_bsize); |
637 | inumber = UFS_ROOTINO; | | 723 | inumber = UFS_ROOTINO; |
638 | if ((rc = read_inode(inumber, f)) != 0) | | 724 | if ((rc = read_inode(inumber, f)) != 0) |
639 | goto out; | | 725 | goto out; |
640 | | | 726 | |
641 | #ifndef LIBSA_FS_SINGLECOMPONENT | | 727 | #ifndef LIBSA_FS_SINGLECOMPONENT |
642 | cp = path; | | 728 | cp = path; |
643 | while (*cp) { | | 729 | while (*cp) { |
644 | | | 730 | |
645 | /* | | 731 | /* |
646 | * Remove extra separators | | 732 | * Remove extra separators |
647 | */ | | 733 | */ |
648 | while (*cp == '/') | | 734 | while (*cp == '/') |
649 | cp++; | | 735 | cp++; |
650 | if (*cp == '\0') | | 736 | if (*cp == '\0') |
651 | break; | | 737 | break; |
652 | | | 738 | |
653 | /* | | 739 | /* |
654 | * Check that current node is a directory. | | 740 | * Check that current node is a directory. |
655 | */ | | 741 | */ |
656 | if ((fp->f_di.di_mode & IFMT) != IFDIR) { | | 742 | if ((fp->f_di.di_mode & IFMT) != IFDIR) { |
657 | rc = ENOTDIR; | | 743 | rc = ENOTDIR; |
658 | goto out; | | 744 | goto out; |
659 | } | | 745 | } |
660 | | | 746 | |
661 | /* | | 747 | /* |
662 | * Get next component of path name. | | 748 | * Get next component of path name. |
663 | */ | | 749 | */ |
664 | ncp = cp; | | 750 | ncp = cp; |
665 | while ((c = *cp) != '\0' && c != '/') | | 751 | while ((c = *cp) != '\0' && c != '/') |
666 | cp++; | | 752 | cp++; |
667 | | | 753 | |
668 | /* | | 754 | /* |
669 | * Look up component in current directory. | | 755 | * Look up component in current directory. |
670 | * Save directory inumber in case we find a | | 756 | * Save directory inumber in case we find a |
671 | * symbolic link. | | 757 | * symbolic link. |
672 | */ | | 758 | */ |
673 | #ifndef LIBSA_NO_FS_SYMLINK | | 759 | #ifndef LIBSA_NO_FS_SYMLINK |
674 | parent_inumber = inumber; | | 760 | parent_inumber = inumber; |
675 | #endif | | 761 | #endif |
676 | rc = search_directory(ncp, cp - ncp, f, &inumber); | | 762 | rc = search_directory(ncp, cp - ncp, f, &inumber); |
677 | if (rc) | | 763 | if (rc) |
678 | goto out; | | 764 | goto out; |
679 | | | 765 | |
680 | /* | | 766 | /* |
681 | * Open next component. | | 767 | * Open next component. |
682 | */ | | 768 | */ |
683 | if ((rc = read_inode(inumber, f)) != 0) | | 769 | if ((rc = read_inode(inumber, f)) != 0) |
684 | goto out; | | 770 | goto out; |
685 | | | 771 | |
686 | #ifndef LIBSA_NO_FS_SYMLINK | | 772 | #ifndef LIBSA_NO_FS_SYMLINK |
687 | /* | | 773 | /* |
688 | * Check for symbolic link. | | 774 | * Check for symbolic link. |
689 | */ | | 775 | */ |
690 | if ((fp->f_di.di_mode & IFMT) == IFLNK) { | | 776 | if ((fp->f_di.di_mode & IFMT) == IFLNK) { |
691 | int link_len = fp->f_di.di_size; | | 777 | int link_len = fp->f_di.di_size; |
692 | int len; | | 778 | int len; |
693 | | | 779 | |
694 | len = strlen(cp); | | 780 | len = strlen(cp); |
695 | | | 781 | |
696 | if (link_len + len > MAXPATHLEN || | | 782 | if (link_len + len > MAXPATHLEN || |
697 | ++nlinks > MAXSYMLINKS) { | | 783 | ++nlinks > MAXSYMLINKS) { |
698 | rc = ENOENT; | | 784 | rc = ENOENT; |
699 | goto out; | | 785 | goto out; |
700 | } | | 786 | } |
701 | | | 787 | |
702 | memmove(&namebuf[link_len], cp, len + 1); | | 788 | memmove(&namebuf[link_len], cp, len + 1); |
703 | | | 789 | |
704 | if (link_len < fs->fs_maxsymlinklen) { | | 790 | if (link_len < fs->fs_maxsymlinklen) { |
705 | memcpy(namebuf, fp->f_di.di_db, link_len); | | 791 | memcpy(namebuf, fp->f_di.di_db, link_len); |
706 | } else { | | 792 | } else { |
707 | /* | | 793 | /* |
708 | * Read file for symbolic link | | 794 | * Read file for symbolic link |
709 | */ | | 795 | */ |
710 | size_t buf_size; | | 796 | size_t buf_size; |
711 | indp_t disk_block; | | 797 | indp_t disk_block; |
712 | | | 798 | |
713 | buf = fp->f_buf; | | 799 | buf = fp->f_buf; |
714 | rc = block_map(f, (indp_t)0, &disk_block); | | 800 | rc = block_map(f, (indp_t)0, &disk_block); |
715 | if (rc) | | 801 | if (rc) |
716 | goto out; | | 802 | goto out; |
717 | | | 803 | |
718 | twiddle(); | | 804 | twiddle(); |
719 | rc = DEV_STRATEGY(f->f_dev)(f->f_devdata, | | 805 | rc = DEV_STRATEGY(f->f_dev)(f->f_devdata, |
720 | F_READ, FSBTODB(fs, disk_block), | | 806 | F_READ, FSBTODB(fs, disk_block), |
721 | fs->fs_bsize, buf, &buf_size); | | 807 | fs->fs_bsize, buf, &buf_size); |
722 | if (rc) | | 808 | if (rc) |
723 | goto out; | | 809 | goto out; |
724 | | | 810 | |
725 | memcpy(namebuf, buf, link_len); | | 811 | memcpy(namebuf, buf, link_len); |
726 | } | | 812 | } |
727 | | | 813 | |
728 | /* | | 814 | /* |
729 | * If relative pathname, restart at parent directory. | | 815 | * If relative pathname, restart at parent directory. |
730 | * If absolute pathname, restart at root. | | 816 | * If absolute pathname, restart at root. |
731 | */ | | 817 | */ |
732 | cp = namebuf; | | 818 | cp = namebuf; |
733 | if (*cp != '/') | | 819 | if (*cp != '/') |
734 | inumber = parent_inumber; | | 820 | inumber = parent_inumber; |
735 | else | | 821 | else |
736 | inumber = (ino32_t)UFS_ROOTINO; | | 822 | inumber = (ino32_t)UFS_ROOTINO; |
737 | | | 823 | |
738 | if ((rc = read_inode(inumber, f)) != 0) | | 824 | if ((rc = read_inode(inumber, f)) != 0) |
739 | goto out; | | 825 | goto out; |
740 | } | | 826 | } |
741 | #endif /* !LIBSA_NO_FS_SYMLINK */ | | 827 | #endif /* !LIBSA_NO_FS_SYMLINK */ |
742 | } | | 828 | } |
743 | | | 829 | |
744 | /* | | 830 | /* |
745 | * Found terminal component. | | 831 | * Found terminal component. |
746 | */ | | 832 | */ |
747 | rc = 0; | | 833 | rc = 0; |
748 | | | 834 | |
749 | #else /* !LIBSA_FS_SINGLECOMPONENT */ | | 835 | #else /* !LIBSA_FS_SINGLECOMPONENT */ |
750 | | | 836 | |
751 | /* look up component in the current (root) directory */ | | 837 | /* look up component in the current (root) directory */ |
752 | rc = search_directory(path, strlen(path), f, &inumber); | | 838 | rc = search_directory(path, strlen(path), f, &inumber); |
753 | if (rc) | | 839 | if (rc) |
754 | goto out; | | 840 | goto out; |
755 | | | 841 | |
756 | /* open it */ | | 842 | /* open it */ |
757 | rc = read_inode(inumber, f); | | 843 | rc = read_inode(inumber, f); |
758 | | | 844 | |
759 | #endif /* !LIBSA_FS_SINGLECOMPONENT */ | | 845 | #endif /* !LIBSA_FS_SINGLECOMPONENT */ |
760 | | | 846 | |
761 | fp->f_seekp = 0; /* reset seek pointer */ | | 847 | fp->f_seekp = 0; /* reset seek pointer */ |
762 | | | 848 | |
763 | out: | | 849 | out: |
764 | if (rc) | | 850 | if (rc) |
765 | ufs_close(f); | | 851 | ufs_close(f); |
766 | #ifdef FSMOD /* Only defined for lfs */ | | 852 | #ifdef FSMOD /* Only defined for lfs */ |
767 | else | | 853 | else |
768 | fsmod = FSMOD; | | 854 | fsmod = FSMOD; |
769 | #endif | | 855 | #endif |
770 | return rc; | | 856 | return rc; |
771 | } | | 857 | } |
772 | | | 858 | |
773 | __compactcall int | | 859 | __compactcall int |
774 | ufs_close(struct open_file *f) | | 860 | ufs_close(struct open_file *f) |
775 | { | | 861 | { |
776 | struct file *fp = (struct file *)f->f_fsdata; | | 862 | struct file *fp = (struct file *)f->f_fsdata; |
777 | | | 863 | |
778 | f->f_fsdata = NULL; | | 864 | f->f_fsdata = NULL; |
779 | if (fp == NULL) | | 865 | if (fp == NULL) |
780 | return 0; | | 866 | return 0; |
781 | | | 867 | |
782 | if (fp->f_buf) | | 868 | if (fp->f_buf) |
783 | dealloc(fp->f_buf, fp->f_fs->fs_bsize); | | 869 | dealloc(fp->f_buf, fp->f_fs->fs_bsize); |
784 | dealloc(fp->f_fs, SBLOCKSIZE); | | 870 | dealloc(fp->f_fs, SBLOCKSIZE); |
785 | dealloc(fp, sizeof(struct file)); | | 871 | dealloc(fp, sizeof(struct file)); |
786 | return 0; | | 872 | return 0; |
787 | } | | 873 | } |
788 | | | 874 | |
789 | /* | | 875 | /* |
790 | * Copy a portion of a file into kernel memory. | | 876 | * Copy a portion of a file into kernel memory. |
791 | * Cross block boundaries when necessary. | | 877 | * Cross block boundaries when necessary. |
792 | */ | | 878 | */ |
793 | __compactcall int | | 879 | __compactcall int |
794 | ufs_read(struct open_file *f, void *start, size_t size, size_t *resid) | | 880 | ufs_read(struct open_file *f, void *start, size_t size, size_t *resid) |
795 | { | | 881 | { |
796 | struct file *fp = (struct file *)f->f_fsdata; | | 882 | struct file *fp = (struct file *)f->f_fsdata; |
797 | size_t csize; | | 883 | size_t csize; |
798 | char *buf; | | 884 | char *buf; |
799 | size_t buf_size; | | 885 | size_t buf_size; |
800 | int rc = 0; | | 886 | int rc = 0; |
801 | char *addr = start; | | 887 | char *addr = start; |
802 | | | 888 | |
803 | while (size != 0) { | | 889 | while (size != 0) { |
804 | if (fp->f_seekp >= (off_t)fp->f_di.di_size) | | 890 | if (fp->f_seekp >= (off_t)fp->f_di.di_size) |
805 | break; | | 891 | break; |
806 | | | 892 | |
807 | rc = buf_read_file(f, &buf, &buf_size); | | 893 | rc = buf_read_file(f, &buf, &buf_size); |
808 | if (rc) | | 894 | if (rc) |
809 | break; | | 895 | break; |
810 | | | 896 | |
811 | csize = size; | | 897 | csize = size; |
812 | if (csize > buf_size) | | 898 | if (csize > buf_size) |
813 | csize = buf_size; | | 899 | csize = buf_size; |
814 | | | 900 | |
815 | memcpy(addr, buf, csize); | | 901 | memcpy(addr, buf, csize); |
816 | | | 902 | |
817 | fp->f_seekp += csize; | | 903 | fp->f_seekp += csize; |
818 | addr += csize; | | 904 | addr += csize; |
819 | size -= csize; | | 905 | size -= csize; |
820 | } | | 906 | } |
821 | if (resid) | | 907 | if (resid) |
822 | *resid = size; | | 908 | *resid = size; |
823 | return rc; | | 909 | return rc; |
824 | } | | 910 | } |
825 | | | 911 | |
826 | /* | | 912 | /* |
827 | * Not implemented. | | 913 | * Not implemented. |
828 | */ | | 914 | */ |
829 | #ifndef LIBSA_NO_FS_WRITE | | 915 | #ifndef LIBSA_NO_FS_WRITE |
830 | __compactcall int | | 916 | __compactcall int |
831 | ufs_write(struct open_file *f, void *start, size_t size, size_t *resid) | | 917 | ufs_write(struct open_file *f, void *start, size_t size, size_t *resid) |
832 | { | | 918 | { |
833 | | | 919 | |
834 | return EROFS; | | 920 | return EROFS; |
835 | } | | 921 | } |
836 | #endif /* !LIBSA_NO_FS_WRITE */ | | 922 | #endif /* !LIBSA_NO_FS_WRITE */ |
837 | | | 923 | |
838 | #ifndef LIBSA_NO_FS_SEEK | | 924 | #ifndef LIBSA_NO_FS_SEEK |
839 | __compactcall off_t | | 925 | __compactcall off_t |
840 | ufs_seek(struct open_file *f, off_t offset, int where) | | 926 | ufs_seek(struct open_file *f, off_t offset, int where) |
841 | { | | 927 | { |
842 | struct file *fp = (struct file *)f->f_fsdata; | | 928 | struct file *fp = (struct file *)f->f_fsdata; |
843 | | | 929 | |
844 | switch (where) { | | 930 | switch (where) { |
845 | case SEEK_SET: | | 931 | case SEEK_SET: |
846 | fp->f_seekp = offset; | | 932 | fp->f_seekp = offset; |
847 | break; | | 933 | break; |
848 | case SEEK_CUR: | | 934 | case SEEK_CUR: |
849 | fp->f_seekp += offset; | | 935 | fp->f_seekp += offset; |
850 | break; | | 936 | break; |
851 | case SEEK_END: | | 937 | case SEEK_END: |
852 | fp->f_seekp = fp->f_di.di_size - offset; | | 938 | fp->f_seekp = fp->f_di.di_size - offset; |
853 | break; | | 939 | break; |
854 | default: | | 940 | default: |
855 | return -1; | | 941 | return -1; |
856 | } | | 942 | } |
857 | return fp->f_seekp; | | 943 | return fp->f_seekp; |
858 | } | | 944 | } |
859 | #endif /* !LIBSA_NO_FS_SEEK */ | | 945 | #endif /* !LIBSA_NO_FS_SEEK */ |
860 | | | 946 | |
861 | __compactcall int | | 947 | __compactcall int |
862 | ufs_stat(struct open_file *f, struct stat *sb) | | 948 | ufs_stat(struct open_file *f, struct stat *sb) |
863 | { | | 949 | { |
864 | struct file *fp = (struct file *)f->f_fsdata; | | 950 | struct file *fp = (struct file *)f->f_fsdata; |
865 | | | 951 | |
866 | /* only important stuff */ | | 952 | /* only important stuff */ |
867 | memset(sb, 0, sizeof *sb); | | 953 | memset(sb, 0, sizeof *sb); |
868 | sb->st_mode = fp->f_di.di_mode; | | 954 | sb->st_mode = fp->f_di.di_mode; |
869 | sb->st_uid = fp->f_di.di_uid; | | 955 | sb->st_uid = fp->f_di.di_uid; |
870 | sb->st_gid = fp->f_di.di_gid; | | 956 | sb->st_gid = fp->f_di.di_gid; |
871 | sb->st_size = fp->f_di.di_size; | | 957 | sb->st_size = fp->f_di.di_size; |
872 | return 0; | | 958 | return 0; |
873 | } | | 959 | } |
874 | | | 960 | |
875 | #if defined(LIBSA_ENABLE_LS_OP) | | 961 | #if defined(LIBSA_ENABLE_LS_OP) |
876 | | | 962 | |
877 | #include "ls.h" | | 963 | #include "ls.h" |
878 | | | 964 | |
879 | static const char *const typestr[] = { | | 965 | static const char *const typestr[] = { |
880 | "unknown", | | 966 | "unknown", |
881 | "FIFO", | | 967 | "FIFO", |
882 | "CHR", | | 968 | "CHR", |
883 | 0, | | 969 | 0, |
884 | "DIR", | | 970 | "DIR", |
885 | 0, | | 971 | 0, |
886 | "BLK", | | 972 | "BLK", |
887 | 0, | | 973 | 0, |
888 | "REG", | | 974 | "REG", |
889 | 0, | | 975 | 0, |
890 | "LNK", | | 976 | "LNK", |
891 | 0, | | 977 | 0, |
892 | "SOCK", | | 978 | "SOCK", |
893 | 0, | | 979 | 0, |
894 | "WHT" | | 980 | "WHT" |
895 | }; | | 981 | }; |
896 | | | 982 | |
897 | __compactcall void | | 983 | __compactcall void |
898 | ufs_ls(struct open_file *f, const char *pattern) | | 984 | ufs_ls(struct open_file *f, const char *pattern) |
899 | { | | 985 | { |
900 | struct file *fp = (struct file *)f->f_fsdata; | | 986 | struct file *fp = (struct file *)f->f_fsdata; |
901 | char *buf; | | 987 | char *buf; |
902 | size_t buf_size; | | 988 | size_t buf_size; |
903 | lsentry_t *names = NULL; | | 989 | lsentry_t *names = NULL; |
904 | | | 990 | |
905 | fp->f_seekp = 0; | | 991 | fp->f_seekp = 0; |
906 | while (fp->f_seekp < (off_t)fp->f_di.di_size) { | | 992 | while (fp->f_seekp < (off_t)fp->f_di.di_size) { |
907 | struct direct *dp, *edp; | | 993 | struct direct *dp, *edp; |
908 | int rc = buf_read_file(f, &buf, &buf_size); | | 994 | int rc = buf_read_file(f, &buf, &buf_size); |
909 | if (rc) | | 995 | if (rc) |
910 | goto out; | | 996 | goto out; |
911 | /* some firmware might use block size larger than DEV_BSIZE */ | | 997 | /* some firmware might use block size larger than DEV_BSIZE */ |
912 | if (buf_size < UFS_DIRBLKSIZ) | | 998 | if (buf_size < UFS_DIRBLKSIZ) |
913 | goto out; | | 999 | goto out; |
914 | | | 1000 | |
915 | dp = (struct direct *)buf; | | 1001 | dp = (struct direct *)buf; |
916 | edp = (struct direct *)(buf + buf_size); | | 1002 | edp = (struct direct *)(buf + buf_size); |
917 | | | 1003 | |
918 | for (; dp < edp; dp = (void *)((char *)dp + dp->d_reclen)) { | | 1004 | for (; dp < edp; |
| | | 1005 | dp = (void *)((char *)dp + ffs_get_reclen(fp, dp))) { |
919 | const char *t; | | 1006 | const char *t; |
920 | if (dp->d_ino == 0) | | 1007 | if (ffs_get_ino(fp, dp) == 0) |
921 | continue; | | 1008 | continue; |
922 | | | 1009 | |
923 | if (dp->d_type >= NELEM(typestr) || | | 1010 | if (dp->d_type >= NELEM(typestr) || |
924 | !(t = typestr[dp->d_type])) { | | 1011 | !(t = typestr[dp->d_type])) { |
925 | /* | | 1012 | /* |
926 | * This does not handle "old" | | 1013 | * This does not handle "old" |
927 | * filesystems properly. On little | | 1014 | * filesystems properly. On little |
928 | * endian machines, we get a bogus | | 1015 | * endian machines, we get a bogus |
929 | * type name if the namlen matches a | | 1016 | * type name if the namlen matches a |
930 | * valid type identifier. We could | | 1017 | * valid type identifier. We could |
931 | * check if we read namlen "0" and | | 1018 | * check if we read namlen "0" and |
932 | * handle this case specially, if | | 1019 | * handle this case specially, if |
933 | * there were a pressing need... | | 1020 | * there were a pressing need... |
934 | */ | | 1021 | */ |
935 | printf("bad dir entry\n"); | | 1022 | printf("bad dir entry\n"); |
936 | goto out; | | 1023 | goto out; |
937 | } | | 1024 | } |
938 | lsadd(&names, pattern, dp->d_name, strlen(dp->d_name), | | 1025 | lsadd(&names, pattern, dp->d_name, strlen(dp->d_name), |
939 | dp->d_ino, t); | | 1026 | ffs_get_ino(fp, dp), t); |
940 | } | | 1027 | } |
941 | fp->f_seekp += buf_size; | | 1028 | fp->f_seekp += buf_size; |
942 | } | | 1029 | } |
943 | lsprint(names); | | 1030 | lsprint(names); |
944 | out: lsfree(names); | | 1031 | out: lsfree(names); |
945 | } | | 1032 | } |
946 | #endif /* LIBSA_ENABLE_LS_OP */ | | 1033 | #endif /* LIBSA_ENABLE_LS_OP */ |
947 | | | 1034 | |
948 | #ifdef LIBSA_FFSv1 | | 1035 | #ifdef LIBSA_FFSv1 |
949 | /* | | 1036 | /* |
950 | * Sanity checks for old file systems. | | 1037 | * Sanity checks for old file systems. |
951 | * | | 1038 | * |
952 | * XXX - goes away some day. | | 1039 | * XXX - goes away some day. |
953 | * Stripped of stuff libsa doesn't need..... | | 1040 | * Stripped of stuff libsa doesn't need..... |
954 | */ | | 1041 | */ |
955 | static void | | 1042 | static void |
956 | ffs_oldfscompat(FS *fs) | | 1043 | ffs_oldfscompat(FS *fs) |
957 | { | | 1044 | { |
958 | | | 1045 | |
959 | #ifdef COMPAT_UFS | | 1046 | #ifdef COMPAT_UFS |
960 | /* | | 1047 | /* |
961 | * Newer Solaris versions have a slightly incompatible | | 1048 | * Newer Solaris versions have a slightly incompatible |
962 | * superblock - so always calculate this values on the fly, which | | 1049 | * superblock - so always calculate this values on the fly, which |
963 | * is good enough for libsa purposes | | 1050 | * is good enough for libsa purposes |
964 | */ | | 1051 | */ |
965 | if (fs->fs_magic == FS_UFS1_MAGIC | | 1052 | if (fs->fs_magic == FS_UFS1_MAGIC |
966 | #ifndef COMPAT_SOLARIS_UFS | | 1053 | #ifndef COMPAT_SOLARIS_UFS |
967 | && fs->fs_old_inodefmt < FS_44INODEFMT | | 1054 | && fs->fs_old_inodefmt < FS_44INODEFMT |
968 | #endif | | 1055 | #endif |
969 | ) { | | 1056 | ) { |
970 | fs->fs_qbmask = ~fs->fs_bmask; | | 1057 | fs->fs_qbmask = ~fs->fs_bmask; |
971 | fs->fs_qfmask = ~fs->fs_fmask; | | 1058 | fs->fs_qfmask = ~fs->fs_fmask; |
972 | } | | 1059 | } |
973 | #endif | | 1060 | #endif |
974 | } | | 1061 | } |
975 | #endif | | 1062 | #endif |