1 1.88 christos /* $NetBSD: ufs.c,v 1.88 2022/12/01 18:06:09 christos 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.88 christos #ifdef LIBSA_FFS_EI 222 1.87 chs static __inline__ bool 223 1.87 chs ffs_is_magic_swapped(FS *fs) 224 1.87 chs { 225 1.87 chs return fs->fs_magic == bswap32(FS_UFS1_MAGIC); 226 1.80 mrg } 227 1.87 chs #endif 228 1.87 chs 229 1.88 christos #endif 230 1.88 christos 231 1.87 chs #ifdef LIBSA_FFSv2 232 1.87 chs static __inline__ bool 233 1.87 chs ffs_is_magic(FS *fs) 234 1.87 chs { 235 1.87 chs return fs->fs_magic == FS_UFS2_MAGIC || fs->fs_magic == FS_UFS2EA_MAGIC; 236 1.87 chs } 237 1.87 chs 238 1.88 christos #ifdef LIBSA_FFS_EI 239 1.87 chs static __inline__ bool 240 1.87 chs ffs_is_magic_swapped(FS *fs) 241 1.87 chs { 242 1.87 chs return fs->fs_magic == bswap32(FS_UFS2_MAGIC) || 243 1.87 chs fs->fs_magic == bswap32(FS_UFS2EA_MAGIC); 244 1.87 chs } 245 1.87 chs #endif 246 1.87 chs 247 1.88 christos #endif 248 1.88 christos 249 1.87 chs #ifdef LIBSA_LFS 250 1.87 chs static __inline__ bool 251 1.87 chs ffs_is_magic(FS *fs) 252 1.87 chs { 253 1.87 chs return fs->fs_magic == LFS_MAGIC; 254 1.87 chs } 255 1.87 chs 256 1.88 christos #ifdef LIBSA_FFS_EI 257 1.87 chs static __inline__ bool 258 1.87 chs ffs_is_magic_swapped(FS *fs) 259 1.87 chs { 260 1.87 chs return fs->fs_magic == bswap32(LFS_MAGIC); 261 1.87 chs } 262 1.87 chs #endif 263 1.80 mrg 264 1.88 christos #endif 265 1.88 christos 266 1.80 mrg static __inline__ void 267 1.80 mrg ffs_fix_magic_swapped(struct file *fp, FS *fs) 268 1.80 mrg { 269 1.80 mrg #ifdef LIBSA_FFS_EI 270 1.87 chs fp->f_swapped = ffs_is_magic_swapped(fs); 271 1.80 mrg if (fp->f_swapped) 272 1.80 mrg { 273 1.80 mrg ffs_sb_swap(fs, fs); 274 1.80 mrg } 275 1.80 mrg #endif 276 1.80 mrg } 277 1.80 mrg 278 1.80 mrg #ifdef LIBSA_FFS_EI 279 1.80 mrg static __inline__ bool 280 1.80 mrg ffs_swapped(struct file *fp) 281 1.80 mrg { 282 1.80 mrg return fp->f_swapped; 283 1.80 mrg } 284 1.80 mrg #endif 285 1.80 mrg 286 1.80 mrg static __inline__ uint16_t 287 1.80 mrg ffs_get_reclen(struct file *fp, struct direct *dp) 288 1.80 mrg { 289 1.80 mrg #ifdef LIBSA_FFS_EI 290 1.80 mrg if (ffs_swapped(fp)) 291 1.80 mrg return bswap16(dp->d_reclen); 292 1.80 mrg #endif 293 1.80 mrg return dp->d_reclen; 294 1.80 mrg } 295 1.80 mrg 296 1.80 mrg static __inline__ uint32_t 297 1.80 mrg ffs_get_ino(struct file *fp, struct direct *dp) 298 1.80 mrg { 299 1.80 mrg #ifdef LIBSA_FFS_EI 300 1.80 mrg if (ffs_swapped(fp)) 301 1.80 mrg return bswap32(dp->d_ino); 302 1.80 mrg #endif 303 1.80 mrg return dp->d_ino; 304 1.80 mrg } 305 1.80 mrg 306 1.56 tsutsui 307 1.35 dsl #ifdef LIBSA_LFS 308 1.35 dsl /* 309 1.35 dsl * Find an inode's block. Look it up in the ifile. Whee! 310 1.35 dsl */ 311 1.35 dsl static int 312 1.45 christos find_inode_sector(ino32_t inumber, struct open_file *f, daddr_t *isp) 313 1.35 dsl { 314 1.35 dsl struct file *fp = (struct file *)f->f_fsdata; 315 1.66 dholland FS *fs = fp->f_fs; 316 1.35 dsl daddr_t ifileent_blkno; 317 1.35 dsl char *ent_in_buf; 318 1.35 dsl size_t buf_after_ent; 319 1.71 dholland size_t entsize; 320 1.35 dsl int rc; 321 1.33 fvdl 322 1.73 dholland rc = read_inode(LFS_IFILE_INUM, f); 323 1.35 dsl if (rc) 324 1.51 isaki return rc; 325 1.35 dsl 326 1.71 dholland entsize = fs->lfs_is64 ? sizeof(IFILE64) : 327 1.71 dholland (lfs_sb_getversion(fs) > 1 ? sizeof(IFILE32) : sizeof(IFILE_V1)); 328 1.35 dsl ifileent_blkno = 329 1.67 dholland (inumber / lfs_sb_getifpb(fs)) + lfs_sb_getcleansz(fs) + lfs_sb_getsegtabsz(fs); 330 1.67 dholland fp->f_seekp = (off_t)ifileent_blkno * lfs_sb_getbsize(fs) + 331 1.71 dholland (inumber % lfs_sb_getifpb(fs)) * entsize; 332 1.35 dsl rc = buf_read_file(f, &ent_in_buf, &buf_after_ent); 333 1.35 dsl if (rc) 334 1.51 isaki return rc; 335 1.35 dsl /* make sure something's not badly wrong, but don't panic. */ 336 1.71 dholland if (buf_after_ent < entsize) 337 1.51 isaki return EINVAL; 338 1.35 dsl 339 1.71 dholland *isp = FSBTODB(fs, lfs_if_getdaddr(fs, (IFILE *)ent_in_buf)); 340 1.35 dsl if (*isp == LFS_UNUSED_DADDR) /* again, something badly wrong */ 341 1.51 isaki return EINVAL; 342 1.51 isaki return 0; 343 1.35 dsl } 344 1.7 brezak #endif 345 1.7 brezak 346 1.1 brezak /* 347 1.1 brezak * Read a new inode into a file structure. 348 1.1 brezak */ 349 1.1 brezak static int 350 1.45 christos read_inode(ino32_t inumber, struct open_file *f) 351 1.1 brezak { 352 1.30 augustss struct file *fp = (struct file *)f->f_fsdata; 353 1.66 dholland FS *fs = fp->f_fs; 354 1.1 brezak char *buf; 355 1.49 mrg size_t rsize; 356 1.1 brezak int rc; 357 1.64 christos daddr_t inode_sector = 0; /* XXX: gcc */ 358 1.35 dsl #ifdef LIBSA_LFS 359 1.35 dsl struct ufs_dinode *dip; 360 1.35 dsl int cnt; 361 1.35 dsl #endif 362 1.35 dsl 363 1.35 dsl #ifdef LIBSA_LFS 364 1.73 dholland if (inumber == LFS_IFILE_INUM) 365 1.67 dholland inode_sector = FSBTODB(fs, lfs_sb_getidaddr(fs)); 366 1.35 dsl else if ((rc = find_inode_sector(inumber, f, &inode_sector)) != 0) 367 1.51 isaki return rc; 368 1.35 dsl #else 369 1.35 dsl inode_sector = FSBTODB(fs, ino_to_fsba(fs, inumber)); 370 1.35 dsl #endif 371 1.1 brezak 372 1.1 brezak /* 373 1.1 brezak * Read inode and save it. 374 1.1 brezak */ 375 1.40 dsl buf = fp->f_buf; 376 1.11 mycroft twiddle(); 377 1.23 cgd rc = DEV_STRATEGY(f->f_dev)(f->f_devdata, F_READ, 378 1.40 dsl inode_sector, fs->fs_bsize, buf, &rsize); 379 1.1 brezak if (rc) 380 1.40 dsl return rc; 381 1.75 christos if (rsize != (size_t)fs->fs_bsize) 382 1.40 dsl return EIO; 383 1.1 brezak 384 1.35 dsl #ifdef LIBSA_LFS 385 1.35 dsl cnt = INOPBx(fs); 386 1.40 dsl dip = (struct ufs_dinode *)buf + (cnt - 1); 387 1.40 dsl for (; dip->di_inumber != inumber; --dip) { 388 1.40 dsl /* kernel code panics, but boot blocks which panic are Bad. */ 389 1.40 dsl if (--cnt == 0) 390 1.40 dsl return EINVAL; 391 1.1 brezak } 392 1.35 dsl fp->f_di = *dip; 393 1.35 dsl #else 394 1.35 dsl fp->f_di = ((struct ufs_dinode *)buf)[ino_to_fsbo(fs, inumber)]; 395 1.80 mrg #ifdef LIBSA_FFS_EI 396 1.80 mrg if (ffs_swapped(fp)) 397 1.80 mrg ufs_dinode_swap(&fp->f_di, &fp->f_di); 398 1.80 mrg #endif 399 1.35 dsl #endif 400 1.1 brezak 401 1.1 brezak /* 402 1.1 brezak * Clear out the old buffers 403 1.1 brezak */ 404 1.40 dsl fp->f_ind_cache_block = ~0; 405 1.40 dsl fp->f_buf_blkno = -1; 406 1.51 isaki return rc; 407 1.1 brezak } 408 1.1 brezak 409 1.1 brezak /* 410 1.1 brezak * Given an offset in a file, find the disk block number that 411 1.1 brezak * contains that block. 412 1.1 brezak */ 413 1.1 brezak static int 414 1.40 dsl block_map(struct open_file *f, indp_t file_block, indp_t *disk_block_p) 415 1.1 brezak { 416 1.30 augustss struct file *fp = (struct file *)f->f_fsdata; 417 1.66 dholland FS *fs = fp->f_fs; 418 1.52 tsutsui uint level; 419 1.40 dsl indp_t ind_cache; 420 1.40 dsl indp_t ind_block_num; 421 1.49 mrg size_t rsize; 422 1.1 brezak int rc; 423 1.40 dsl indp_t *buf = (void *)fp->f_buf; 424 1.1 brezak 425 1.1 brezak /* 426 1.1 brezak * Index structure of an inode: 427 1.1 brezak * 428 1.59 dholland * di_db[0..UFS_NDADDR-1] hold block numbers for blocks 429 1.59 dholland * 0..UFS_NDADDR-1 430 1.1 brezak * 431 1.1 brezak * di_ib[0] index block 0 is the single indirect block 432 1.1 brezak * holds block numbers for blocks 433 1.61 dholland * UFS_NDADDR .. UFS_NDADDR + UFS_NINDIR(fs)-1 434 1.1 brezak * 435 1.1 brezak * di_ib[1] index block 1 is the double indirect block 436 1.1 brezak * holds block numbers for INDEX blocks for blocks 437 1.61 dholland * UFS_NDADDR + UFS_NINDIR(fs) .. 438 1.61 dholland * UFS_NDADDR + UFS_NINDIR(fs) + UFS_NINDIR(fs)**2 - 1 439 1.1 brezak * 440 1.1 brezak * di_ib[2] index block 2 is the triple indirect block 441 1.1 brezak * holds block numbers for double-indirect 442 1.1 brezak * blocks for blocks 443 1.61 dholland * UFS_NDADDR + UFS_NINDIR(fs) + UFS_NINDIR(fs)**2 .. 444 1.61 dholland * UFS_NDADDR + UFS_NINDIR(fs) + UFS_NINDIR(fs)**2 445 1.61 dholland * + UFS_NINDIR(fs)**3 - 1 446 1.1 brezak */ 447 1.1 brezak 448 1.59 dholland if (file_block < UFS_NDADDR) { 449 1.1 brezak /* Direct block. */ 450 1.35 dsl *disk_block_p = fp->f_di.di_db[file_block]; 451 1.51 isaki return 0; 452 1.1 brezak } 453 1.1 brezak 454 1.59 dholland file_block -= UFS_NDADDR; 455 1.1 brezak 456 1.40 dsl ind_cache = file_block >> LN2_IND_CACHE_SZ; 457 1.40 dsl if (ind_cache == fp->f_ind_cache_block) { 458 1.40 dsl *disk_block_p = fp->f_ind_cache[file_block & IND_CACHE_MASK]; 459 1.40 dsl return 0; 460 1.40 dsl } 461 1.40 dsl 462 1.40 dsl for (level = 0;;) { 463 1.40 dsl level += fp->f_nishift; 464 1.40 dsl if (file_block < (indp_t)1 << level) 465 1.40 dsl break; 466 1.59 dholland if (level > UFS_NIADDR * fp->f_nishift) 467 1.38 dsl /* Block number too high */ 468 1.51 isaki return EFBIG; 469 1.40 dsl file_block -= (indp_t)1 << level; 470 1.1 brezak } 471 1.1 brezak 472 1.40 dsl ind_block_num = fp->f_di.di_ib[level / fp->f_nishift - 1]; 473 1.1 brezak 474 1.40 dsl for (;;) { 475 1.40 dsl level -= fp->f_nishift; 476 1.1 brezak if (ind_block_num == 0) { 477 1.1 brezak *disk_block_p = 0; /* missing */ 478 1.51 isaki return 0; 479 1.1 brezak } 480 1.1 brezak 481 1.40 dsl twiddle(); 482 1.40 dsl /* 483 1.40 dsl * If we were feeling brave, we could work out the number 484 1.40 dsl * of the disk sector and read a single disk sector instead 485 1.40 dsl * of a filesystem block. 486 1.40 dsl * However we don't do this very often anyway... 487 1.40 dsl */ 488 1.40 dsl rc = DEV_STRATEGY(f->f_dev)(f->f_devdata, F_READ, 489 1.40 dsl FSBTODB(fp->f_fs, ind_block_num), fs->fs_bsize, 490 1.40 dsl buf, &rsize); 491 1.40 dsl if (rc) 492 1.51 isaki return rc; 493 1.75 christos if (rsize != (size_t)fs->fs_bsize) 494 1.40 dsl return EIO; 495 1.80 mrg #ifdef LIBSA_FFS_EI 496 1.80 mrg if (ffs_swapped(fp)) 497 1.80 mrg ind_block_num = ufs_indp_swap(buf[file_block >> level]); 498 1.80 mrg else 499 1.80 mrg #endif 500 1.80 mrg ind_block_num = buf[file_block >> level]; 501 1.40 dsl if (level == 0) 502 1.40 dsl break; 503 1.40 dsl file_block &= (1 << level) - 1; 504 1.40 dsl } 505 1.1 brezak 506 1.40 dsl /* Save the part of the block that contains this sector */ 507 1.80 mrg #if defined(LIBSA_FFS_EI) 508 1.80 mrg if (ffs_swapped(fp)) { 509 1.80 mrg size_t i; 510 1.80 mrg 511 1.80 mrg for (i = 0; i < IND_CACHE_SZ; i++) { 512 1.80 mrg fp->f_ind_cache[i] = ufs_indp_swap( 513 1.80 mrg buf[(file_block & ~IND_CACHE_MASK) + i]); 514 1.80 mrg } 515 1.80 mrg } else 516 1.80 mrg #endif 517 1.80 mrg memcpy(fp->f_ind_cache, &buf[file_block & ~IND_CACHE_MASK], 518 1.80 mrg IND_CACHE_SZ * sizeof fp->f_ind_cache[0]); 519 1.40 dsl fp->f_ind_cache_block = ind_cache; 520 1.1 brezak 521 1.1 brezak *disk_block_p = ind_block_num; 522 1.1 brezak 523 1.51 isaki return 0; 524 1.1 brezak } 525 1.1 brezak 526 1.1 brezak /* 527 1.40 dsl * Read a portion of a file into an internal buffer. 528 1.40 dsl * Return the location in the buffer and the amount in the buffer. 529 1.1 brezak */ 530 1.1 brezak static int 531 1.37 dsl buf_read_file(struct open_file *f, char **buf_p, size_t *size_p) 532 1.1 brezak { 533 1.30 augustss struct file *fp = (struct file *)f->f_fsdata; 534 1.66 dholland FS *fs = fp->f_fs; 535 1.1 brezak long off; 536 1.40 dsl indp_t file_block; 537 1.13 cgd size_t block_size; 538 1.1 brezak int rc; 539 1.1 brezak 540 1.61 dholland off = ufs_blkoff(fs, fp->f_seekp); 541 1.63 dholland file_block = ufs_lblkno(fs, fp->f_seekp); 542 1.35 dsl #ifdef LIBSA_LFS 543 1.76 christos block_size = (size_t)dblksize(fs, &fp->f_di, (uint64_t)file_block); 544 1.35 dsl #else 545 1.75 christos block_size = (size_t)ffs_sblksize(fs, (int64_t)fp->f_di.di_size, file_block); 546 1.35 dsl #endif 547 1.1 brezak 548 1.1 brezak if (file_block != fp->f_buf_blkno) { 549 1.64 christos indp_t disk_block = 0; /* XXX: gcc */ 550 1.1 brezak rc = block_map(f, file_block, &disk_block); 551 1.1 brezak if (rc) 552 1.51 isaki return rc; 553 1.1 brezak 554 1.1 brezak if (disk_block == 0) { 555 1.41 dsl memset(fp->f_buf, 0, block_size); 556 1.1 brezak fp->f_buf_size = block_size; 557 1.1 brezak } else { 558 1.11 mycroft twiddle(); 559 1.23 cgd rc = DEV_STRATEGY(f->f_dev)(f->f_devdata, F_READ, 560 1.35 dsl FSBTODB(fs, disk_block), 561 1.1 brezak block_size, fp->f_buf, &fp->f_buf_size); 562 1.1 brezak if (rc) 563 1.51 isaki return rc; 564 1.1 brezak } 565 1.1 brezak 566 1.1 brezak fp->f_buf_blkno = file_block; 567 1.1 brezak } 568 1.1 brezak 569 1.1 brezak /* 570 1.1 brezak * Return address of byte in buffer corresponding to 571 1.1 brezak * offset, and size of remainder of buffer after that 572 1.1 brezak * byte. 573 1.1 brezak */ 574 1.1 brezak *buf_p = fp->f_buf + off; 575 1.1 brezak *size_p = block_size - off; 576 1.1 brezak 577 1.1 brezak /* 578 1.1 brezak * But truncate buffer at end of file. 579 1.1 brezak */ 580 1.35 dsl if (*size_p > fp->f_di.di_size - fp->f_seekp) 581 1.35 dsl *size_p = fp->f_di.di_size - fp->f_seekp; 582 1.1 brezak 583 1.51 isaki return 0; 584 1.1 brezak } 585 1.1 brezak 586 1.1 brezak /* 587 1.1 brezak * Search a directory for a name and return its 588 1.38 dsl * inode number. 589 1.1 brezak */ 590 1.1 brezak static int 591 1.38 dsl search_directory(const char *name, int length, struct open_file *f, 592 1.51 isaki ino32_t *inumber_p) 593 1.1 brezak { 594 1.30 augustss struct file *fp = (struct file *)f->f_fsdata; 595 1.30 augustss struct direct *dp; 596 1.1 brezak struct direct *edp; 597 1.1 brezak char *buf; 598 1.13 cgd size_t buf_size; 599 1.38 dsl int namlen; 600 1.1 brezak int rc; 601 1.1 brezak 602 1.1 brezak fp->f_seekp = 0; 603 1.42 fvdl while (fp->f_seekp < (off_t)fp->f_di.di_size) { 604 1.1 brezak rc = buf_read_file(f, &buf, &buf_size); 605 1.1 brezak if (rc) 606 1.51 isaki return rc; 607 1.1 brezak 608 1.1 brezak dp = (struct direct *)buf; 609 1.1 brezak edp = (struct direct *)(buf + buf_size); 610 1.80 mrg for (; dp < edp; 611 1.80 mrg dp = (void *)((char *)dp + ffs_get_reclen(fp, dp))) { 612 1.80 mrg if (ffs_get_reclen(fp, dp) <= 0) 613 1.40 dsl break; 614 1.80 mrg if (ffs_get_ino(fp, dp) == (ino32_t)0) 615 1.38 dsl continue; 616 1.1 brezak #if BYTE_ORDER == LITTLE_ENDIAN 617 1.1 brezak if (fp->f_fs->fs_maxsymlinklen <= 0) 618 1.1 brezak namlen = dp->d_type; 619 1.1 brezak else 620 1.1 brezak #endif 621 1.1 brezak namlen = dp->d_namlen; 622 1.1 brezak if (namlen == length && 623 1.38 dsl !memcmp(name, dp->d_name, length)) { 624 1.1 brezak /* found entry */ 625 1.80 mrg *inumber_p = ffs_get_ino(fp, dp); 626 1.51 isaki return 0; 627 1.1 brezak } 628 1.1 brezak } 629 1.1 brezak fp->f_seekp += buf_size; 630 1.1 brezak } 631 1.51 isaki return ENOENT; 632 1.1 brezak } 633 1.1 brezak 634 1.79 mrg static __inline__ int 635 1.66 dholland ffs_find_superblock(struct open_file *f, FS *fs) 636 1.33 fvdl { 637 1.80 mrg struct file *fp = (struct file *)f->f_fsdata; 638 1.79 mrg int rc; 639 1.33 fvdl size_t buf_size; 640 1.79 mrg #ifdef LIBSA_FFSv2 641 1.79 mrg static daddr_t sblock_try[] = SBLOCKSEARCH; 642 1.79 mrg int i; 643 1.82 mlelstv #endif 644 1.82 mlelstv 645 1.82 mlelstv #ifdef LIBSA_FFSv2 646 1.33 fvdl for (i = 0; sblock_try[i] != -1; i++) { 647 1.33 fvdl rc = DEV_STRATEGY(f->f_dev)(f->f_devdata, F_READ, 648 1.86 rin sblock_try[i] / GETSECSIZE(f), SBLOCKSIZE, fs, &buf_size); 649 1.80 mrg if (rc) 650 1.33 fvdl return rc; 651 1.80 mrg if (buf_size != SBLOCKSIZE) 652 1.80 mrg return EINVAL; 653 1.80 mrg ffs_fix_magic_swapped(fp, fs); 654 1.43 dsl if (fs->fs_sblockloc != sblock_try[i]) 655 1.43 dsl /* an alternate superblock - try again */ 656 1.43 dsl continue; 657 1.80 mrg if (ffs_is_magic(fs)) 658 1.33 fvdl return 0; 659 1.33 fvdl } 660 1.33 fvdl return EINVAL; 661 1.79 mrg #else /* LIBSA_FFSv2 */ 662 1.79 mrg rc = DEV_STRATEGY(f->f_dev)(f->f_devdata, F_READ, 663 1.86 rin SBLOCKOFFSET / GETSECSIZE(f), SBLOCKSIZE, fs, &buf_size); 664 1.79 mrg if (rc) 665 1.79 mrg return rc; 666 1.80 mrg if (buf_size != SBLOCKSIZE) 667 1.80 mrg return EINVAL; 668 1.80 mrg ffs_fix_magic_swapped(fp, fs); 669 1.80 mrg 670 1.79 mrg #ifdef LIBSA_LFS 671 1.80 mrg if (fs->lfs_version != REQUIRED_LFS_VERSION) 672 1.80 mrg return EINVAL; 673 1.79 mrg #endif 674 1.80 mrg if (!ffs_is_magic(fs)) 675 1.79 mrg return EINVAL; 676 1.80 mrg 677 1.79 mrg return 0; 678 1.79 mrg #endif /* !LIBSA_FFSv2 */ 679 1.33 fvdl } 680 1.33 fvdl 681 1.1 brezak /* 682 1.1 brezak * Open a file. 683 1.1 brezak */ 684 1.55 joerg __compactcall int 685 1.38 dsl ufs_open(const char *path, struct open_file *f) 686 1.1 brezak { 687 1.23 cgd #ifndef LIBSA_FS_SINGLECOMPONENT 688 1.38 dsl const char *cp, *ncp; 689 1.30 augustss int c; 690 1.23 cgd #endif 691 1.45 christos ino32_t inumber; 692 1.1 brezak struct file *fp; 693 1.66 dholland FS *fs; 694 1.10 ws int rc; 695 1.23 cgd #ifndef LIBSA_NO_FS_SYMLINK 696 1.45 christos ino32_t parent_inumber; 697 1.10 ws int nlinks = 0; 698 1.1 brezak char namebuf[MAXPATHLEN+1]; 699 1.40 dsl char *buf; 700 1.22 simonb #endif 701 1.1 brezak 702 1.1 brezak /* allocate file system specific data structure */ 703 1.1 brezak fp = alloc(sizeof(struct file)); 704 1.41 dsl memset(fp, 0, sizeof(struct file)); 705 1.1 brezak f->f_fsdata = (void *)fp; 706 1.1 brezak 707 1.1 brezak /* allocate space and read super block */ 708 1.33 fvdl fs = alloc(SBLOCKSIZE); 709 1.1 brezak fp->f_fs = fs; 710 1.11 mycroft twiddle(); 711 1.33 fvdl 712 1.33 fvdl rc = ffs_find_superblock(f, fs); 713 1.33 fvdl if (rc) 714 1.33 fvdl goto out; 715 1.79 mrg 716 1.35 dsl #if defined(LIBSA_LFS) && REQUIRED_LFS_VERSION == 2 717 1.35 dsl /* 718 1.35 dsl * XXX We should check the second superblock and use the eldest 719 1.35 dsl * of the two. See comments near the top of lfs_mountfs() 720 1.35 dsl * in sys/ufs/lfs/lfs_vfsops.c. 721 1.35 dsl * This may need a LIBSA_LFS_SMALL check as well. 722 1.35 dsl */ 723 1.35 dsl #endif 724 1.70 dholland #if defined(LIBSA_LFS) 725 1.70 dholland fs->lfs_is64 = 0; 726 1.74 dholland fs->lfs_dobyteswap = 0; 727 1.74 dholland fs->lfs_hasolddirfmt = (fs->fs_maxsymlinklen <= 0); 728 1.70 dholland #endif 729 1.35 dsl #ifdef LIBSA_FFSv1 730 1.33 fvdl ffs_oldfscompat(fs); 731 1.35 dsl #endif 732 1.33 fvdl 733 1.42 fvdl if (fs->fs_bsize > MAXBSIZE || 734 1.66 dholland (size_t)fs->fs_bsize < sizeof(FS)) { 735 1.1 brezak rc = EINVAL; 736 1.1 brezak goto out; 737 1.1 brezak } 738 1.1 brezak 739 1.1 brezak /* 740 1.1 brezak * Calculate indirect block levels. 741 1.1 brezak */ 742 1.1 brezak { 743 1.40 dsl indp_t mult; 744 1.35 dsl int ln2; 745 1.35 dsl 746 1.35 dsl /* 747 1.35 dsl * We note that the number of indirect blocks is always 748 1.35 dsl * a power of 2. This lets us use shifts and masks instead 749 1.81 skrll * of divide and remainder and avoids pulling in the 750 1.35 dsl * 64bit division routine into the boot code. 751 1.35 dsl */ 752 1.61 dholland mult = UFS_NINDIR(fs); 753 1.35 dsl #ifdef DEBUG 754 1.35 dsl if (mult & (mult - 1)) { 755 1.35 dsl /* Hummm was't a power of 2 */ 756 1.35 dsl rc = EINVAL; 757 1.35 dsl goto out; 758 1.35 dsl } 759 1.35 dsl #endif 760 1.35 dsl for (ln2 = 0; mult != 1; ln2++) 761 1.35 dsl mult >>= 1; 762 1.1 brezak 763 1.40 dsl fp->f_nishift = ln2; 764 1.1 brezak } 765 1.1 brezak 766 1.40 dsl /* alloc a block sized buffer used for all fs transfers */ 767 1.40 dsl fp->f_buf = alloc(fs->fs_bsize); 768 1.59 dholland inumber = UFS_ROOTINO; 769 1.1 brezak if ((rc = read_inode(inumber, f)) != 0) 770 1.1 brezak goto out; 771 1.1 brezak 772 1.23 cgd #ifndef LIBSA_FS_SINGLECOMPONENT 773 1.1 brezak cp = path; 774 1.1 brezak while (*cp) { 775 1.1 brezak 776 1.1 brezak /* 777 1.1 brezak * Remove extra separators 778 1.1 brezak */ 779 1.1 brezak while (*cp == '/') 780 1.1 brezak cp++; 781 1.1 brezak if (*cp == '\0') 782 1.1 brezak break; 783 1.1 brezak 784 1.1 brezak /* 785 1.1 brezak * Check that current node is a directory. 786 1.1 brezak */ 787 1.35 dsl if ((fp->f_di.di_mode & IFMT) != IFDIR) { 788 1.1 brezak rc = ENOTDIR; 789 1.1 brezak goto out; 790 1.1 brezak } 791 1.1 brezak 792 1.1 brezak /* 793 1.1 brezak * Get next component of path name. 794 1.1 brezak */ 795 1.38 dsl ncp = cp; 796 1.38 dsl while ((c = *cp) != '\0' && c != '/') 797 1.38 dsl cp++; 798 1.1 brezak 799 1.1 brezak /* 800 1.1 brezak * Look up component in current directory. 801 1.1 brezak * Save directory inumber in case we find a 802 1.1 brezak * symbolic link. 803 1.1 brezak */ 804 1.23 cgd #ifndef LIBSA_NO_FS_SYMLINK 805 1.1 brezak parent_inumber = inumber; 806 1.23 cgd #endif 807 1.38 dsl rc = search_directory(ncp, cp - ncp, f, &inumber); 808 1.1 brezak if (rc) 809 1.1 brezak goto out; 810 1.1 brezak 811 1.1 brezak /* 812 1.1 brezak * Open next component. 813 1.1 brezak */ 814 1.1 brezak if ((rc = read_inode(inumber, f)) != 0) 815 1.1 brezak goto out; 816 1.1 brezak 817 1.23 cgd #ifndef LIBSA_NO_FS_SYMLINK 818 1.1 brezak /* 819 1.1 brezak * Check for symbolic link. 820 1.1 brezak */ 821 1.35 dsl if ((fp->f_di.di_mode & IFMT) == IFLNK) { 822 1.35 dsl int link_len = fp->f_di.di_size; 823 1.10 ws int len; 824 1.10 ws 825 1.10 ws len = strlen(cp); 826 1.1 brezak 827 1.10 ws if (link_len + len > MAXPATHLEN || 828 1.10 ws ++nlinks > MAXSYMLINKS) { 829 1.1 brezak rc = ENOENT; 830 1.1 brezak goto out; 831 1.1 brezak } 832 1.1 brezak 833 1.38 dsl memmove(&namebuf[link_len], cp, len + 1); 834 1.1 brezak 835 1.9 pk if (link_len < fs->fs_maxsymlinklen) { 836 1.38 dsl memcpy(namebuf, fp->f_di.di_db, link_len); 837 1.1 brezak } else { 838 1.1 brezak /* 839 1.1 brezak * Read file for symbolic link 840 1.1 brezak */ 841 1.13 cgd size_t buf_size; 842 1.40 dsl indp_t disk_block; 843 1.9 pk 844 1.40 dsl buf = fp->f_buf; 845 1.40 dsl rc = block_map(f, (indp_t)0, &disk_block); 846 1.9 pk if (rc) 847 1.9 pk goto out; 848 1.22 simonb 849 1.11 mycroft twiddle(); 850 1.23 cgd rc = DEV_STRATEGY(f->f_dev)(f->f_devdata, 851 1.35 dsl F_READ, FSBTODB(fs, disk_block), 852 1.9 pk fs->fs_bsize, buf, &buf_size); 853 1.1 brezak if (rc) 854 1.1 brezak goto out; 855 1.1 brezak 856 1.38 dsl memcpy(namebuf, buf, link_len); 857 1.1 brezak } 858 1.1 brezak 859 1.1 brezak /* 860 1.1 brezak * If relative pathname, restart at parent directory. 861 1.1 brezak * If absolute pathname, restart at root. 862 1.1 brezak */ 863 1.1 brezak cp = namebuf; 864 1.1 brezak if (*cp != '/') 865 1.1 brezak inumber = parent_inumber; 866 1.1 brezak else 867 1.59 dholland inumber = (ino32_t)UFS_ROOTINO; 868 1.1 brezak 869 1.9 pk if ((rc = read_inode(inumber, f)) != 0) 870 1.1 brezak goto out; 871 1.1 brezak } 872 1.23 cgd #endif /* !LIBSA_NO_FS_SYMLINK */ 873 1.1 brezak } 874 1.1 brezak 875 1.1 brezak /* 876 1.1 brezak * Found terminal component. 877 1.1 brezak */ 878 1.1 brezak rc = 0; 879 1.23 cgd 880 1.23 cgd #else /* !LIBSA_FS_SINGLECOMPONENT */ 881 1.23 cgd 882 1.23 cgd /* look up component in the current (root) directory */ 883 1.38 dsl rc = search_directory(path, strlen(path), f, &inumber); 884 1.23 cgd if (rc) 885 1.23 cgd goto out; 886 1.23 cgd 887 1.23 cgd /* open it */ 888 1.23 cgd rc = read_inode(inumber, f); 889 1.23 cgd 890 1.23 cgd #endif /* !LIBSA_FS_SINGLECOMPONENT */ 891 1.26 cgd 892 1.51 isaki fp->f_seekp = 0; /* reset seek pointer */ 893 1.23 cgd 894 1.1 brezak out: 895 1.40 dsl if (rc) 896 1.38 dsl ufs_close(f); 897 1.58 dsl else 898 1.83 mlelstv #ifdef FSMOD 899 1.54 ad fsmod = FSMOD; 900 1.83 mlelstv #else 901 1.83 mlelstv fsmod = NULL; 902 1.54 ad #endif 903 1.51 isaki return rc; 904 1.1 brezak } 905 1.1 brezak 906 1.55 joerg __compactcall int 907 1.37 dsl ufs_close(struct open_file *f) 908 1.1 brezak { 909 1.30 augustss struct file *fp = (struct file *)f->f_fsdata; 910 1.1 brezak 911 1.38 dsl f->f_fsdata = NULL; 912 1.38 dsl if (fp == NULL) 913 1.51 isaki return 0; 914 1.1 brezak 915 1.1 brezak if (fp->f_buf) 916 1.48 christos dealloc(fp->f_buf, fp->f_fs->fs_bsize); 917 1.48 christos dealloc(fp->f_fs, SBLOCKSIZE); 918 1.48 christos dealloc(fp, sizeof(struct file)); 919 1.51 isaki return 0; 920 1.1 brezak } 921 1.1 brezak 922 1.1 brezak /* 923 1.1 brezak * Copy a portion of a file into kernel memory. 924 1.1 brezak * Cross block boundaries when necessary. 925 1.1 brezak */ 926 1.55 joerg __compactcall int 927 1.37 dsl ufs_read(struct open_file *f, void *start, size_t size, size_t *resid) 928 1.1 brezak { 929 1.30 augustss struct file *fp = (struct file *)f->f_fsdata; 930 1.30 augustss size_t csize; 931 1.1 brezak char *buf; 932 1.13 cgd size_t buf_size; 933 1.1 brezak int rc = 0; 934 1.30 augustss char *addr = start; 935 1.1 brezak 936 1.1 brezak while (size != 0) { 937 1.42 fvdl if (fp->f_seekp >= (off_t)fp->f_di.di_size) 938 1.1 brezak break; 939 1.1 brezak 940 1.1 brezak rc = buf_read_file(f, &buf, &buf_size); 941 1.1 brezak if (rc) 942 1.1 brezak break; 943 1.1 brezak 944 1.1 brezak csize = size; 945 1.1 brezak if (csize > buf_size) 946 1.1 brezak csize = buf_size; 947 1.1 brezak 948 1.38 dsl memcpy(addr, buf, csize); 949 1.1 brezak 950 1.1 brezak fp->f_seekp += csize; 951 1.12 pk addr += csize; 952 1.1 brezak size -= csize; 953 1.1 brezak } 954 1.1 brezak if (resid) 955 1.1 brezak *resid = size; 956 1.51 isaki return rc; 957 1.1 brezak } 958 1.1 brezak 959 1.1 brezak /* 960 1.1 brezak * Not implemented. 961 1.1 brezak */ 962 1.23 cgd #ifndef LIBSA_NO_FS_WRITE 963 1.55 joerg __compactcall int 964 1.37 dsl ufs_write(struct open_file *f, void *start, size_t size, size_t *resid) 965 1.1 brezak { 966 1.1 brezak 967 1.51 isaki return EROFS; 968 1.1 brezak } 969 1.23 cgd #endif /* !LIBSA_NO_FS_WRITE */ 970 1.1 brezak 971 1.23 cgd #ifndef LIBSA_NO_FS_SEEK 972 1.55 joerg __compactcall off_t 973 1.37 dsl ufs_seek(struct open_file *f, off_t offset, int where) 974 1.1 brezak { 975 1.30 augustss struct file *fp = (struct file *)f->f_fsdata; 976 1.1 brezak 977 1.1 brezak switch (where) { 978 1.1 brezak case SEEK_SET: 979 1.1 brezak fp->f_seekp = offset; 980 1.1 brezak break; 981 1.1 brezak case SEEK_CUR: 982 1.1 brezak fp->f_seekp += offset; 983 1.1 brezak break; 984 1.1 brezak case SEEK_END: 985 1.35 dsl fp->f_seekp = fp->f_di.di_size - offset; 986 1.1 brezak break; 987 1.1 brezak default: 988 1.51 isaki return -1; 989 1.1 brezak } 990 1.51 isaki return fp->f_seekp; 991 1.1 brezak } 992 1.23 cgd #endif /* !LIBSA_NO_FS_SEEK */ 993 1.1 brezak 994 1.55 joerg __compactcall int 995 1.37 dsl ufs_stat(struct open_file *f, struct stat *sb) 996 1.1 brezak { 997 1.30 augustss struct file *fp = (struct file *)f->f_fsdata; 998 1.1 brezak 999 1.1 brezak /* only important stuff */ 1000 1.40 dsl memset(sb, 0, sizeof *sb); 1001 1.35 dsl sb->st_mode = fp->f_di.di_mode; 1002 1.35 dsl sb->st_uid = fp->f_di.di_uid; 1003 1.35 dsl sb->st_gid = fp->f_di.di_gid; 1004 1.35 dsl sb->st_size = fp->f_di.di_size; 1005 1.51 isaki return 0; 1006 1.4 pk } 1007 1.4 pk 1008 1.56 tsutsui #if defined(LIBSA_ENABLE_LS_OP) 1009 1.65 christos 1010 1.65 christos #include "ls.h" 1011 1.65 christos 1012 1.65 christos static const char *const typestr[] = { 1013 1.65 christos "unknown", 1014 1.65 christos "FIFO", 1015 1.65 christos "CHR", 1016 1.65 christos 0, 1017 1.65 christos "DIR", 1018 1.65 christos 0, 1019 1.65 christos "BLK", 1020 1.65 christos 0, 1021 1.65 christos "REG", 1022 1.65 christos 0, 1023 1.65 christos "LNK", 1024 1.65 christos 0, 1025 1.65 christos "SOCK", 1026 1.65 christos 0, 1027 1.65 christos "WHT" 1028 1.65 christos }; 1029 1.65 christos 1030 1.56 tsutsui __compactcall void 1031 1.56 tsutsui ufs_ls(struct open_file *f, const char *pattern) 1032 1.56 tsutsui { 1033 1.56 tsutsui struct file *fp = (struct file *)f->f_fsdata; 1034 1.56 tsutsui char *buf; 1035 1.56 tsutsui size_t buf_size; 1036 1.65 christos lsentry_t *names = NULL; 1037 1.56 tsutsui 1038 1.56 tsutsui fp->f_seekp = 0; 1039 1.56 tsutsui while (fp->f_seekp < (off_t)fp->f_di.di_size) { 1040 1.56 tsutsui struct direct *dp, *edp; 1041 1.56 tsutsui int rc = buf_read_file(f, &buf, &buf_size); 1042 1.56 tsutsui if (rc) 1043 1.56 tsutsui goto out; 1044 1.56 tsutsui /* some firmware might use block size larger than DEV_BSIZE */ 1045 1.60 dholland if (buf_size < UFS_DIRBLKSIZ) 1046 1.56 tsutsui goto out; 1047 1.56 tsutsui 1048 1.56 tsutsui dp = (struct direct *)buf; 1049 1.56 tsutsui edp = (struct direct *)(buf + buf_size); 1050 1.56 tsutsui 1051 1.80 mrg for (; dp < edp; 1052 1.80 mrg dp = (void *)((char *)dp + ffs_get_reclen(fp, dp))) { 1053 1.56 tsutsui const char *t; 1054 1.80 mrg if (ffs_get_ino(fp, dp) == 0) 1055 1.56 tsutsui continue; 1056 1.56 tsutsui 1057 1.56 tsutsui if (dp->d_type >= NELEM(typestr) || 1058 1.56 tsutsui !(t = typestr[dp->d_type])) { 1059 1.56 tsutsui /* 1060 1.56 tsutsui * This does not handle "old" 1061 1.56 tsutsui * filesystems properly. On little 1062 1.56 tsutsui * endian machines, we get a bogus 1063 1.56 tsutsui * type name if the namlen matches a 1064 1.56 tsutsui * valid type identifier. We could 1065 1.56 tsutsui * check if we read namlen "0" and 1066 1.56 tsutsui * handle this case specially, if 1067 1.56 tsutsui * there were a pressing need... 1068 1.56 tsutsui */ 1069 1.56 tsutsui printf("bad dir entry\n"); 1070 1.56 tsutsui goto out; 1071 1.56 tsutsui } 1072 1.65 christos lsadd(&names, pattern, dp->d_name, strlen(dp->d_name), 1073 1.80 mrg ffs_get_ino(fp, dp), t); 1074 1.56 tsutsui } 1075 1.56 tsutsui fp->f_seekp += buf_size; 1076 1.56 tsutsui } 1077 1.65 christos lsprint(names); 1078 1.65 christos out: lsfree(names); 1079 1.56 tsutsui } 1080 1.56 tsutsui #endif /* LIBSA_ENABLE_LS_OP */ 1081 1.56 tsutsui 1082 1.35 dsl #ifdef LIBSA_FFSv1 1083 1.4 pk /* 1084 1.4 pk * Sanity checks for old file systems. 1085 1.4 pk * 1086 1.4 pk * XXX - goes away some day. 1087 1.40 dsl * Stripped of stuff libsa doesn't need..... 1088 1.4 pk */ 1089 1.13 cgd static void 1090 1.66 dholland ffs_oldfscompat(FS *fs) 1091 1.4 pk { 1092 1.4 pk 1093 1.33 fvdl #ifdef COMPAT_UFS 1094 1.50 martin /* 1095 1.50 martin * Newer Solaris versions have a slightly incompatible 1096 1.50 martin * superblock - so always calculate this values on the fly, which 1097 1.50 martin * is good enough for libsa purposes 1098 1.50 martin */ 1099 1.50 martin if (fs->fs_magic == FS_UFS1_MAGIC 1100 1.50 martin #ifndef COMPAT_SOLARIS_UFS 1101 1.50 martin && fs->fs_old_inodefmt < FS_44INODEFMT 1102 1.50 martin #endif 1103 1.50 martin ) { 1104 1.33 fvdl fs->fs_qbmask = ~fs->fs_bmask; 1105 1.33 fvdl fs->fs_qfmask = ~fs->fs_fmask; 1106 1.33 fvdl } 1107 1.33 fvdl #endif 1108 1.1 brezak } 1109 1.35 dsl #endif 1110