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