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