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