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