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