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