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