14a5d661aSToomas Soome /* $NetBSD: ufs.c,v 1.20 1998/03/01 07:15:39 ross Exp $ */ 24a5d661aSToomas Soome 34a5d661aSToomas Soome /*- 44a5d661aSToomas Soome * Copyright (c) 2002 Networks Associates Technology, Inc. 54a5d661aSToomas Soome * All rights reserved. 64a5d661aSToomas Soome * 74a5d661aSToomas Soome * This software was developed for the FreeBSD Project by Marshall 84a5d661aSToomas Soome * Kirk McKusick and Network Associates Laboratories, the Security 94a5d661aSToomas Soome * Research Division of Network Associates, Inc. under DARPA/SPAWAR 104a5d661aSToomas Soome * contract N66001-01-C-8035 ("CBOSS"), as part of the DARPA CHATS 114a5d661aSToomas Soome * research program 124a5d661aSToomas Soome * 134a5d661aSToomas Soome * Copyright (c) 1982, 1989, 1993 144a5d661aSToomas Soome * The Regents of the University of California. All rights reserved. 154a5d661aSToomas Soome * 164a5d661aSToomas Soome * This code is derived from software contributed to Berkeley by 174a5d661aSToomas Soome * The Mach Operating System project at Carnegie-Mellon University. 184a5d661aSToomas Soome * 194a5d661aSToomas Soome * Redistribution and use in source and binary forms, with or without 204a5d661aSToomas Soome * modification, are permitted provided that the following conditions 214a5d661aSToomas Soome * are met: 224a5d661aSToomas Soome * 1. Redistributions of source code must retain the above copyright 234a5d661aSToomas Soome * notice, this list of conditions and the following disclaimer. 244a5d661aSToomas Soome * 2. Redistributions in binary form must reproduce the above copyright 254a5d661aSToomas Soome * notice, this list of conditions and the following disclaimer in the 264a5d661aSToomas Soome * documentation and/or other materials provided with the distribution. 274a5d661aSToomas Soome * 3. Neither the name of the University nor the names of its contributors 284a5d661aSToomas Soome * may be used to endorse or promote products derived from this software 294a5d661aSToomas Soome * without specific prior written permission. 304a5d661aSToomas Soome * 314a5d661aSToomas Soome * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 324a5d661aSToomas Soome * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 334a5d661aSToomas Soome * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 344a5d661aSToomas Soome * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 354a5d661aSToomas Soome * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 364a5d661aSToomas Soome * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 374a5d661aSToomas Soome * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 384a5d661aSToomas Soome * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 394a5d661aSToomas Soome * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 404a5d661aSToomas Soome * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 414a5d661aSToomas Soome * SUCH DAMAGE. 424a5d661aSToomas Soome * 434a5d661aSToomas Soome * 444a5d661aSToomas Soome * Copyright (c) 1990, 1991 Carnegie Mellon University 454a5d661aSToomas Soome * All Rights Reserved. 464a5d661aSToomas Soome * 474a5d661aSToomas Soome * Author: David Golub 484a5d661aSToomas Soome * 494a5d661aSToomas Soome * Permission to use, copy, modify and distribute this software and its 504a5d661aSToomas Soome * documentation is hereby granted, provided that both the copyright 514a5d661aSToomas Soome * notice and this permission notice appear in all copies of the 524a5d661aSToomas Soome * software, derivative works or modified versions, and any portions 534a5d661aSToomas Soome * thereof, and that both notices appear in supporting documentation. 544a5d661aSToomas Soome * 554a5d661aSToomas Soome * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" 564a5d661aSToomas Soome * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR 574a5d661aSToomas Soome * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. 584a5d661aSToomas Soome * 594a5d661aSToomas Soome * Carnegie Mellon requests users of this software to return to 604a5d661aSToomas Soome * 614a5d661aSToomas Soome * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU 624a5d661aSToomas Soome * School of Computer Science 634a5d661aSToomas Soome * Carnegie Mellon University 644a5d661aSToomas Soome * Pittsburgh PA 15213-3890 654a5d661aSToomas Soome * 664a5d661aSToomas Soome * any improvements or extensions that they make and grant Carnegie the 674a5d661aSToomas Soome * rights to redistribute these changes. 684a5d661aSToomas Soome */ 694a5d661aSToomas Soome 704a5d661aSToomas Soome #include <sys/cdefs.h> 714a5d661aSToomas Soome __FBSDID("$FreeBSD$"); 724a5d661aSToomas Soome 734a5d661aSToomas Soome /* 744a5d661aSToomas Soome * Stand-alone file reading package. 754a5d661aSToomas Soome */ 764a5d661aSToomas Soome 774a5d661aSToomas Soome #include <sys/param.h> 784a5d661aSToomas Soome #include <sys/disklabel.h> 794a5d661aSToomas Soome #include <sys/time.h> 804a5d661aSToomas Soome #include <ufs/ufs/dinode.h> 814a5d661aSToomas Soome #include <ufs/ufs/dir.h> 824a5d661aSToomas Soome #include <ufs/ffs/fs.h> 834a5d661aSToomas Soome #include "stand.h" 844a5d661aSToomas Soome #include "string.h" 854a5d661aSToomas Soome 864a5d661aSToomas Soome static int ufs_open(const char *path, struct open_file *f); 874a5d661aSToomas Soome static int ufs_write(struct open_file *f, void *buf, size_t size, size_t *resid); 884a5d661aSToomas Soome static int ufs_close(struct open_file *f); 894a5d661aSToomas Soome static int ufs_read(struct open_file *f, void *buf, size_t size, size_t *resid); 904a5d661aSToomas Soome static off_t ufs_seek(struct open_file *f, off_t offset, int where); 914a5d661aSToomas Soome static int ufs_stat(struct open_file *f, struct stat *sb); 924a5d661aSToomas Soome static int ufs_readdir(struct open_file *f, struct dirent *d); 934a5d661aSToomas Soome 944a5d661aSToomas Soome struct fs_ops ufs_fsops = { 954a5d661aSToomas Soome "ufs", 964a5d661aSToomas Soome ufs_open, 974a5d661aSToomas Soome ufs_close, 984a5d661aSToomas Soome ufs_read, 994a5d661aSToomas Soome ufs_write, 1004a5d661aSToomas Soome ufs_seek, 1014a5d661aSToomas Soome ufs_stat, 1024a5d661aSToomas Soome ufs_readdir 1034a5d661aSToomas Soome }; 1044a5d661aSToomas Soome 1054a5d661aSToomas Soome /* 1064a5d661aSToomas Soome * In-core open file. 1074a5d661aSToomas Soome */ 1084a5d661aSToomas Soome struct file { 1094a5d661aSToomas Soome off_t f_seekp; /* seek pointer */ 1104a5d661aSToomas Soome struct fs *f_fs; /* pointer to super-block */ 1114a5d661aSToomas Soome union dinode { 1124a5d661aSToomas Soome struct ufs1_dinode di1; 1134a5d661aSToomas Soome struct ufs2_dinode di2; 1144a5d661aSToomas Soome } f_di; /* copy of on-disk inode */ 1154a5d661aSToomas Soome int f_nindir[NIADDR]; 1164a5d661aSToomas Soome /* number of blocks mapped by 1174a5d661aSToomas Soome indirect block at level i */ 1184a5d661aSToomas Soome char *f_blk[NIADDR]; /* buffer for indirect block at 1194a5d661aSToomas Soome level i */ 1204a5d661aSToomas Soome size_t f_blksize[NIADDR]; 1214a5d661aSToomas Soome /* size of buffer */ 1224a5d661aSToomas Soome ufs2_daddr_t f_blkno[NIADDR];/* disk address of block in buffer */ 1234a5d661aSToomas Soome ufs2_daddr_t f_buf_blkno; /* block number of data block */ 1244a5d661aSToomas Soome char *f_buf; /* buffer for data block */ 1254a5d661aSToomas Soome size_t f_buf_size; /* size of data block */ 1264a5d661aSToomas Soome }; 1274a5d661aSToomas Soome #define DIP(fp, field) \ 1284a5d661aSToomas Soome ((fp)->f_fs->fs_magic == FS_UFS1_MAGIC ? \ 1294a5d661aSToomas Soome (fp)->f_di.di1.field : (fp)->f_di.di2.field) 1304a5d661aSToomas Soome 1314a5d661aSToomas Soome static int read_inode(ino_t, struct open_file *); 1324a5d661aSToomas Soome static int block_map(struct open_file *, ufs2_daddr_t, ufs2_daddr_t *); 1334a5d661aSToomas Soome static int buf_read_file(struct open_file *, char **, size_t *); 1344a5d661aSToomas Soome static int buf_write_file(struct open_file *, char *, size_t *); 1354a5d661aSToomas Soome static int search_directory(char *, struct open_file *, ino_t *); 1364a5d661aSToomas Soome 1374a5d661aSToomas Soome /* 1384a5d661aSToomas Soome * Read a new inode into a file structure. 1394a5d661aSToomas Soome */ 1404a5d661aSToomas Soome static int 1414a5d661aSToomas Soome read_inode(inumber, f) 1424a5d661aSToomas Soome ino_t inumber; 1434a5d661aSToomas Soome struct open_file *f; 1444a5d661aSToomas Soome { 1454a5d661aSToomas Soome struct file *fp = (struct file *)f->f_fsdata; 1464a5d661aSToomas Soome struct fs *fs = fp->f_fs; 1474a5d661aSToomas Soome char *buf; 1484a5d661aSToomas Soome size_t rsize; 1494a5d661aSToomas Soome int rc; 1504a5d661aSToomas Soome 1514a5d661aSToomas Soome if (fs == NULL) 1524a5d661aSToomas Soome panic("fs == NULL"); 1534a5d661aSToomas Soome 1544a5d661aSToomas Soome /* 1554a5d661aSToomas Soome * Read inode and save it. 1564a5d661aSToomas Soome */ 1574a5d661aSToomas Soome buf = malloc(fs->fs_bsize); 1584a5d661aSToomas Soome twiddle(1); 1594a5d661aSToomas Soome rc = (f->f_dev->dv_strategy)(f->f_devdata, F_READ, 160*976852c7SToomas Soome fsbtodb(fs, ino_to_fsba(fs, inumber)), fs->fs_bsize, 1614a5d661aSToomas Soome buf, &rsize); 1624a5d661aSToomas Soome if (rc) 1634a5d661aSToomas Soome goto out; 1644a5d661aSToomas Soome if (rsize != fs->fs_bsize) { 1654a5d661aSToomas Soome rc = EIO; 1664a5d661aSToomas Soome goto out; 1674a5d661aSToomas Soome } 1684a5d661aSToomas Soome 1694a5d661aSToomas Soome if (fp->f_fs->fs_magic == FS_UFS1_MAGIC) 1704a5d661aSToomas Soome fp->f_di.di1 = ((struct ufs1_dinode *)buf) 1714a5d661aSToomas Soome [ino_to_fsbo(fs, inumber)]; 1724a5d661aSToomas Soome else 1734a5d661aSToomas Soome fp->f_di.di2 = ((struct ufs2_dinode *)buf) 1744a5d661aSToomas Soome [ino_to_fsbo(fs, inumber)]; 1754a5d661aSToomas Soome 1764a5d661aSToomas Soome /* 1774a5d661aSToomas Soome * Clear out the old buffers 1784a5d661aSToomas Soome */ 1794a5d661aSToomas Soome { 1804a5d661aSToomas Soome int level; 1814a5d661aSToomas Soome 1824a5d661aSToomas Soome for (level = 0; level < NIADDR; level++) 1834a5d661aSToomas Soome fp->f_blkno[level] = -1; 1844a5d661aSToomas Soome fp->f_buf_blkno = -1; 1854a5d661aSToomas Soome } 1864a5d661aSToomas Soome fp->f_seekp = 0; 1874a5d661aSToomas Soome out: 1884a5d661aSToomas Soome free(buf); 1894a5d661aSToomas Soome return (rc); 1904a5d661aSToomas Soome } 1914a5d661aSToomas Soome 1924a5d661aSToomas Soome /* 1934a5d661aSToomas Soome * Given an offset in a file, find the disk block number that 1944a5d661aSToomas Soome * contains that block. 1954a5d661aSToomas Soome */ 1964a5d661aSToomas Soome static int 1974a5d661aSToomas Soome block_map(f, file_block, disk_block_p) 1984a5d661aSToomas Soome struct open_file *f; 1994a5d661aSToomas Soome ufs2_daddr_t file_block; 2004a5d661aSToomas Soome ufs2_daddr_t *disk_block_p; /* out */ 2014a5d661aSToomas Soome { 2024a5d661aSToomas Soome struct file *fp = (struct file *)f->f_fsdata; 2034a5d661aSToomas Soome struct fs *fs = fp->f_fs; 2044a5d661aSToomas Soome int level; 2054a5d661aSToomas Soome int idx; 2064a5d661aSToomas Soome ufs2_daddr_t ind_block_num; 2074a5d661aSToomas Soome int rc; 2084a5d661aSToomas Soome 2094a5d661aSToomas Soome /* 2104a5d661aSToomas Soome * Index structure of an inode: 2114a5d661aSToomas Soome * 2124a5d661aSToomas Soome * di_db[0..NDADDR-1] hold block numbers for blocks 2134a5d661aSToomas Soome * 0..NDADDR-1 2144a5d661aSToomas Soome * 2154a5d661aSToomas Soome * di_ib[0] index block 0 is the single indirect block 2164a5d661aSToomas Soome * holds block numbers for blocks 2174a5d661aSToomas Soome * NDADDR .. NDADDR + NINDIR(fs)-1 2184a5d661aSToomas Soome * 2194a5d661aSToomas Soome * di_ib[1] index block 1 is the double indirect block 2204a5d661aSToomas Soome * holds block numbers for INDEX blocks for blocks 2214a5d661aSToomas Soome * NDADDR + NINDIR(fs) .. 2224a5d661aSToomas Soome * NDADDR + NINDIR(fs) + NINDIR(fs)**2 - 1 2234a5d661aSToomas Soome * 2244a5d661aSToomas Soome * di_ib[2] index block 2 is the triple indirect block 2254a5d661aSToomas Soome * holds block numbers for double-indirect 2264a5d661aSToomas Soome * blocks for blocks 2274a5d661aSToomas Soome * NDADDR + NINDIR(fs) + NINDIR(fs)**2 .. 2284a5d661aSToomas Soome * NDADDR + NINDIR(fs) + NINDIR(fs)**2 2294a5d661aSToomas Soome * + NINDIR(fs)**3 - 1 2304a5d661aSToomas Soome */ 2314a5d661aSToomas Soome 2324a5d661aSToomas Soome if (file_block < NDADDR) { 2334a5d661aSToomas Soome /* Direct block. */ 2344a5d661aSToomas Soome *disk_block_p = DIP(fp, di_db[file_block]); 2354a5d661aSToomas Soome return (0); 2364a5d661aSToomas Soome } 2374a5d661aSToomas Soome 2384a5d661aSToomas Soome file_block -= NDADDR; 2394a5d661aSToomas Soome 2404a5d661aSToomas Soome /* 2414a5d661aSToomas Soome * nindir[0] = NINDIR 2424a5d661aSToomas Soome * nindir[1] = NINDIR**2 2434a5d661aSToomas Soome * nindir[2] = NINDIR**3 2444a5d661aSToomas Soome * etc 2454a5d661aSToomas Soome */ 2464a5d661aSToomas Soome for (level = 0; level < NIADDR; level++) { 2474a5d661aSToomas Soome if (file_block < fp->f_nindir[level]) 2484a5d661aSToomas Soome break; 2494a5d661aSToomas Soome file_block -= fp->f_nindir[level]; 2504a5d661aSToomas Soome } 2514a5d661aSToomas Soome if (level == NIADDR) { 2524a5d661aSToomas Soome /* Block number too high */ 2534a5d661aSToomas Soome return (EFBIG); 2544a5d661aSToomas Soome } 2554a5d661aSToomas Soome 2564a5d661aSToomas Soome ind_block_num = DIP(fp, di_ib[level]); 2574a5d661aSToomas Soome 2584a5d661aSToomas Soome for (; level >= 0; level--) { 2594a5d661aSToomas Soome if (ind_block_num == 0) { 2604a5d661aSToomas Soome *disk_block_p = 0; /* missing */ 2614a5d661aSToomas Soome return (0); 2624a5d661aSToomas Soome } 2634a5d661aSToomas Soome 2644a5d661aSToomas Soome if (fp->f_blkno[level] != ind_block_num) { 2654a5d661aSToomas Soome if (fp->f_blk[level] == (char *)0) 2664a5d661aSToomas Soome fp->f_blk[level] = 2674a5d661aSToomas Soome malloc(fs->fs_bsize); 2684a5d661aSToomas Soome twiddle(1); 2694a5d661aSToomas Soome rc = (f->f_dev->dv_strategy)(f->f_devdata, F_READ, 270*976852c7SToomas Soome fsbtodb(fp->f_fs, ind_block_num), 2714a5d661aSToomas Soome fs->fs_bsize, 2724a5d661aSToomas Soome fp->f_blk[level], 2734a5d661aSToomas Soome &fp->f_blksize[level]); 2744a5d661aSToomas Soome if (rc) 2754a5d661aSToomas Soome return (rc); 2764a5d661aSToomas Soome if (fp->f_blksize[level] != fs->fs_bsize) 2774a5d661aSToomas Soome return (EIO); 2784a5d661aSToomas Soome fp->f_blkno[level] = ind_block_num; 2794a5d661aSToomas Soome } 2804a5d661aSToomas Soome 2814a5d661aSToomas Soome if (level > 0) { 2824a5d661aSToomas Soome idx = file_block / fp->f_nindir[level - 1]; 2834a5d661aSToomas Soome file_block %= fp->f_nindir[level - 1]; 2844a5d661aSToomas Soome } else 2854a5d661aSToomas Soome idx = file_block; 2864a5d661aSToomas Soome 2874a5d661aSToomas Soome if (fp->f_fs->fs_magic == FS_UFS1_MAGIC) 2884a5d661aSToomas Soome ind_block_num = ((ufs1_daddr_t *)fp->f_blk[level])[idx]; 2894a5d661aSToomas Soome else 2904a5d661aSToomas Soome ind_block_num = ((ufs2_daddr_t *)fp->f_blk[level])[idx]; 2914a5d661aSToomas Soome } 2924a5d661aSToomas Soome 2934a5d661aSToomas Soome *disk_block_p = ind_block_num; 2944a5d661aSToomas Soome 2954a5d661aSToomas Soome return (0); 2964a5d661aSToomas Soome } 2974a5d661aSToomas Soome 2984a5d661aSToomas Soome /* 2994a5d661aSToomas Soome * Write a portion of a file from an internal buffer. 3004a5d661aSToomas Soome */ 3014a5d661aSToomas Soome static int 3024a5d661aSToomas Soome buf_write_file(f, buf_p, size_p) 3034a5d661aSToomas Soome struct open_file *f; 3044a5d661aSToomas Soome char *buf_p; 3054a5d661aSToomas Soome size_t *size_p; /* out */ 3064a5d661aSToomas Soome { 3074a5d661aSToomas Soome struct file *fp = (struct file *)f->f_fsdata; 3084a5d661aSToomas Soome struct fs *fs = fp->f_fs; 3094a5d661aSToomas Soome long off; 3104a5d661aSToomas Soome ufs_lbn_t file_block; 3114a5d661aSToomas Soome ufs2_daddr_t disk_block; 3124a5d661aSToomas Soome size_t block_size; 3134a5d661aSToomas Soome int rc; 3144a5d661aSToomas Soome 3154a5d661aSToomas Soome /* 3164a5d661aSToomas Soome * Calculate the starting block address and offset. 3174a5d661aSToomas Soome */ 3184a5d661aSToomas Soome off = blkoff(fs, fp->f_seekp); 3194a5d661aSToomas Soome file_block = lblkno(fs, fp->f_seekp); 3204a5d661aSToomas Soome block_size = sblksize(fs, DIP(fp, di_size), file_block); 3214a5d661aSToomas Soome 3224a5d661aSToomas Soome rc = block_map(f, file_block, &disk_block); 3234a5d661aSToomas Soome if (rc) 3244a5d661aSToomas Soome return (rc); 3254a5d661aSToomas Soome 3264a5d661aSToomas Soome if (disk_block == 0) 3274a5d661aSToomas Soome /* Because we can't allocate space on the drive */ 3284a5d661aSToomas Soome return (EFBIG); 3294a5d661aSToomas Soome 3304a5d661aSToomas Soome /* 3314a5d661aSToomas Soome * Truncate buffer at end of file, and at the end of 3324a5d661aSToomas Soome * this block. 3334a5d661aSToomas Soome */ 3344a5d661aSToomas Soome if (*size_p > DIP(fp, di_size) - fp->f_seekp) 3354a5d661aSToomas Soome *size_p = DIP(fp, di_size) - fp->f_seekp; 3364a5d661aSToomas Soome if (*size_p > block_size - off) 3374a5d661aSToomas Soome *size_p = block_size - off; 3384a5d661aSToomas Soome 3394a5d661aSToomas Soome /* 3404a5d661aSToomas Soome * If we don't entirely occlude the block and it's not 3414a5d661aSToomas Soome * in memory already, read it in first. 3424a5d661aSToomas Soome */ 3434a5d661aSToomas Soome if (((off > 0) || (*size_p + off < block_size)) && 3444a5d661aSToomas Soome (file_block != fp->f_buf_blkno)) { 3454a5d661aSToomas Soome 3464a5d661aSToomas Soome if (fp->f_buf == (char *)0) 3474a5d661aSToomas Soome fp->f_buf = malloc(fs->fs_bsize); 3484a5d661aSToomas Soome 3494a5d661aSToomas Soome twiddle(8); 3504a5d661aSToomas Soome rc = (f->f_dev->dv_strategy)(f->f_devdata, F_READ, 351*976852c7SToomas Soome fsbtodb(fs, disk_block), 3524a5d661aSToomas Soome block_size, fp->f_buf, &fp->f_buf_size); 3534a5d661aSToomas Soome if (rc) 3544a5d661aSToomas Soome return (rc); 3554a5d661aSToomas Soome 3564a5d661aSToomas Soome fp->f_buf_blkno = file_block; 3574a5d661aSToomas Soome } 3584a5d661aSToomas Soome 3594a5d661aSToomas Soome /* 3604a5d661aSToomas Soome * Copy the user data into the cached block. 3614a5d661aSToomas Soome */ 3624a5d661aSToomas Soome bcopy(buf_p, fp->f_buf + off, *size_p); 3634a5d661aSToomas Soome 3644a5d661aSToomas Soome /* 3654a5d661aSToomas Soome * Write the block out to storage. 3664a5d661aSToomas Soome */ 3674a5d661aSToomas Soome 3684a5d661aSToomas Soome twiddle(4); 3694a5d661aSToomas Soome rc = (f->f_dev->dv_strategy)(f->f_devdata, F_WRITE, 370*976852c7SToomas Soome fsbtodb(fs, disk_block), 3714a5d661aSToomas Soome block_size, fp->f_buf, &fp->f_buf_size); 3724a5d661aSToomas Soome return (rc); 3734a5d661aSToomas Soome } 3744a5d661aSToomas Soome 3754a5d661aSToomas Soome /* 3764a5d661aSToomas Soome * Read a portion of a file into an internal buffer. Return 3774a5d661aSToomas Soome * the location in the buffer and the amount in the buffer. 3784a5d661aSToomas Soome */ 3794a5d661aSToomas Soome static int 3804a5d661aSToomas Soome buf_read_file(f, buf_p, size_p) 3814a5d661aSToomas Soome struct open_file *f; 3824a5d661aSToomas Soome char **buf_p; /* out */ 3834a5d661aSToomas Soome size_t *size_p; /* out */ 3844a5d661aSToomas Soome { 3854a5d661aSToomas Soome struct file *fp = (struct file *)f->f_fsdata; 3864a5d661aSToomas Soome struct fs *fs = fp->f_fs; 3874a5d661aSToomas Soome long off; 3884a5d661aSToomas Soome ufs_lbn_t file_block; 3894a5d661aSToomas Soome ufs2_daddr_t disk_block; 3904a5d661aSToomas Soome size_t block_size; 3914a5d661aSToomas Soome int rc; 3924a5d661aSToomas Soome 3934a5d661aSToomas Soome off = blkoff(fs, fp->f_seekp); 3944a5d661aSToomas Soome file_block = lblkno(fs, fp->f_seekp); 3954a5d661aSToomas Soome block_size = sblksize(fs, DIP(fp, di_size), file_block); 3964a5d661aSToomas Soome 3974a5d661aSToomas Soome if (file_block != fp->f_buf_blkno) { 3984a5d661aSToomas Soome if (fp->f_buf == (char *)0) 3994a5d661aSToomas Soome fp->f_buf = malloc(fs->fs_bsize); 4004a5d661aSToomas Soome 4014a5d661aSToomas Soome rc = block_map(f, file_block, &disk_block); 4024a5d661aSToomas Soome if (rc) 4034a5d661aSToomas Soome return (rc); 4044a5d661aSToomas Soome 4054a5d661aSToomas Soome if (disk_block == 0) { 4064a5d661aSToomas Soome bzero(fp->f_buf, block_size); 4074a5d661aSToomas Soome fp->f_buf_size = block_size; 4084a5d661aSToomas Soome } else { 4094a5d661aSToomas Soome twiddle(4); 4104a5d661aSToomas Soome rc = (f->f_dev->dv_strategy)(f->f_devdata, 411*976852c7SToomas Soome F_READ, fsbtodb(fs, disk_block), 4124a5d661aSToomas Soome block_size, fp->f_buf, &fp->f_buf_size); 4134a5d661aSToomas Soome if (rc) 4144a5d661aSToomas Soome return (rc); 4154a5d661aSToomas Soome } 4164a5d661aSToomas Soome 4174a5d661aSToomas Soome fp->f_buf_blkno = file_block; 4184a5d661aSToomas Soome } 4194a5d661aSToomas Soome 4204a5d661aSToomas Soome /* 4214a5d661aSToomas Soome * Return address of byte in buffer corresponding to 4224a5d661aSToomas Soome * offset, and size of remainder of buffer after that 4234a5d661aSToomas Soome * byte. 4244a5d661aSToomas Soome */ 4254a5d661aSToomas Soome *buf_p = fp->f_buf + off; 4264a5d661aSToomas Soome *size_p = block_size - off; 4274a5d661aSToomas Soome 4284a5d661aSToomas Soome /* 4294a5d661aSToomas Soome * But truncate buffer at end of file. 4304a5d661aSToomas Soome */ 4314a5d661aSToomas Soome if (*size_p > DIP(fp, di_size) - fp->f_seekp) 4324a5d661aSToomas Soome *size_p = DIP(fp, di_size) - fp->f_seekp; 4334a5d661aSToomas Soome 4344a5d661aSToomas Soome return (0); 4354a5d661aSToomas Soome } 4364a5d661aSToomas Soome 4374a5d661aSToomas Soome /* 4384a5d661aSToomas Soome * Search a directory for a name and return its 4394a5d661aSToomas Soome * i_number. 4404a5d661aSToomas Soome */ 4414a5d661aSToomas Soome static int 4424a5d661aSToomas Soome search_directory(name, f, inumber_p) 4434a5d661aSToomas Soome char *name; 4444a5d661aSToomas Soome struct open_file *f; 4454a5d661aSToomas Soome ino_t *inumber_p; /* out */ 4464a5d661aSToomas Soome { 4474a5d661aSToomas Soome struct file *fp = (struct file *)f->f_fsdata; 4484a5d661aSToomas Soome struct direct *dp; 4494a5d661aSToomas Soome struct direct *edp; 4504a5d661aSToomas Soome char *buf; 4514a5d661aSToomas Soome size_t buf_size; 4524a5d661aSToomas Soome int namlen, length; 4534a5d661aSToomas Soome int rc; 4544a5d661aSToomas Soome 4554a5d661aSToomas Soome length = strlen(name); 4564a5d661aSToomas Soome 4574a5d661aSToomas Soome fp->f_seekp = 0; 4584a5d661aSToomas Soome while (fp->f_seekp < DIP(fp, di_size)) { 4594a5d661aSToomas Soome rc = buf_read_file(f, &buf, &buf_size); 4604a5d661aSToomas Soome if (rc) 4614a5d661aSToomas Soome return (rc); 4624a5d661aSToomas Soome 4634a5d661aSToomas Soome dp = (struct direct *)buf; 4644a5d661aSToomas Soome edp = (struct direct *)(buf + buf_size); 4654a5d661aSToomas Soome while (dp < edp) { 4664a5d661aSToomas Soome if (dp->d_ino == (ino_t)0) 4674a5d661aSToomas Soome goto next; 4684a5d661aSToomas Soome namlen = dp->d_namlen; 4694a5d661aSToomas Soome if (namlen == length && 4704a5d661aSToomas Soome !strcmp(name, dp->d_name)) { 4714a5d661aSToomas Soome /* found entry */ 4724a5d661aSToomas Soome *inumber_p = dp->d_ino; 4734a5d661aSToomas Soome return (0); 4744a5d661aSToomas Soome } 4754a5d661aSToomas Soome next: 4764a5d661aSToomas Soome dp = (struct direct *)((char *)dp + dp->d_reclen); 4774a5d661aSToomas Soome } 4784a5d661aSToomas Soome fp->f_seekp += buf_size; 4794a5d661aSToomas Soome } 4804a5d661aSToomas Soome return (ENOENT); 4814a5d661aSToomas Soome } 4824a5d661aSToomas Soome 4834a5d661aSToomas Soome static int sblock_try[] = SBLOCKSEARCH; 4844a5d661aSToomas Soome 4854a5d661aSToomas Soome /* 4864a5d661aSToomas Soome * Open a file. 4874a5d661aSToomas Soome */ 4884a5d661aSToomas Soome static int 4894a5d661aSToomas Soome ufs_open(upath, f) 4904a5d661aSToomas Soome const char *upath; 4914a5d661aSToomas Soome struct open_file *f; 4924a5d661aSToomas Soome { 4934a5d661aSToomas Soome char *cp, *ncp; 4944a5d661aSToomas Soome int c; 4954a5d661aSToomas Soome ino_t inumber, parent_inumber; 4964a5d661aSToomas Soome struct file *fp; 4974a5d661aSToomas Soome struct fs *fs; 4984a5d661aSToomas Soome int i, rc; 4994a5d661aSToomas Soome size_t buf_size; 5004a5d661aSToomas Soome int nlinks = 0; 5014a5d661aSToomas Soome char namebuf[MAXPATHLEN+1]; 5024a5d661aSToomas Soome char *buf = NULL; 5034a5d661aSToomas Soome char *path = NULL; 5044a5d661aSToomas Soome 5054a5d661aSToomas Soome /* allocate file system specific data structure */ 5064a5d661aSToomas Soome fp = malloc(sizeof(struct file)); 5074a5d661aSToomas Soome bzero(fp, sizeof(struct file)); 5084a5d661aSToomas Soome f->f_fsdata = (void *)fp; 5094a5d661aSToomas Soome 5104a5d661aSToomas Soome /* allocate space and read super block */ 5114a5d661aSToomas Soome fs = malloc(SBLOCKSIZE); 5124a5d661aSToomas Soome fp->f_fs = fs; 5134a5d661aSToomas Soome twiddle(1); 5144a5d661aSToomas Soome /* 5154a5d661aSToomas Soome * Try reading the superblock in each of its possible locations. 5164a5d661aSToomas Soome */ 5174a5d661aSToomas Soome for (i = 0; sblock_try[i] != -1; i++) { 5184a5d661aSToomas Soome rc = (f->f_dev->dv_strategy)(f->f_devdata, F_READ, 519*976852c7SToomas Soome sblock_try[i] / DEV_BSIZE, SBLOCKSIZE, 5204a5d661aSToomas Soome (char *)fs, &buf_size); 5214a5d661aSToomas Soome if (rc) 5224a5d661aSToomas Soome goto out; 5234a5d661aSToomas Soome if ((fs->fs_magic == FS_UFS1_MAGIC || 5244a5d661aSToomas Soome (fs->fs_magic == FS_UFS2_MAGIC && 5254a5d661aSToomas Soome fs->fs_sblockloc == sblock_try[i])) && 5264a5d661aSToomas Soome buf_size == SBLOCKSIZE && 5274a5d661aSToomas Soome fs->fs_bsize <= MAXBSIZE && 5284a5d661aSToomas Soome fs->fs_bsize >= sizeof(struct fs)) 5294a5d661aSToomas Soome break; 5304a5d661aSToomas Soome } 5314a5d661aSToomas Soome if (sblock_try[i] == -1) { 5324a5d661aSToomas Soome rc = EINVAL; 5334a5d661aSToomas Soome goto out; 5344a5d661aSToomas Soome } 5354a5d661aSToomas Soome /* 5364a5d661aSToomas Soome * Calculate indirect block levels. 5374a5d661aSToomas Soome */ 5384a5d661aSToomas Soome { 5394a5d661aSToomas Soome ufs2_daddr_t mult; 5404a5d661aSToomas Soome int level; 5414a5d661aSToomas Soome 5424a5d661aSToomas Soome mult = 1; 5434a5d661aSToomas Soome for (level = 0; level < NIADDR; level++) { 5444a5d661aSToomas Soome mult *= NINDIR(fs); 5454a5d661aSToomas Soome fp->f_nindir[level] = mult; 5464a5d661aSToomas Soome } 5474a5d661aSToomas Soome } 5484a5d661aSToomas Soome 5494a5d661aSToomas Soome inumber = ROOTINO; 5504a5d661aSToomas Soome if ((rc = read_inode(inumber, f)) != 0) 5514a5d661aSToomas Soome goto out; 5524a5d661aSToomas Soome 5534a5d661aSToomas Soome cp = path = strdup(upath); 5544a5d661aSToomas Soome if (path == NULL) { 5554a5d661aSToomas Soome rc = ENOMEM; 5564a5d661aSToomas Soome goto out; 5574a5d661aSToomas Soome } 5584a5d661aSToomas Soome while (*cp) { 5594a5d661aSToomas Soome 5604a5d661aSToomas Soome /* 5614a5d661aSToomas Soome * Remove extra separators 5624a5d661aSToomas Soome */ 5634a5d661aSToomas Soome while (*cp == '/') 5644a5d661aSToomas Soome cp++; 5654a5d661aSToomas Soome if (*cp == '\0') 5664a5d661aSToomas Soome break; 5674a5d661aSToomas Soome 5684a5d661aSToomas Soome /* 5694a5d661aSToomas Soome * Check that current node is a directory. 5704a5d661aSToomas Soome */ 5714a5d661aSToomas Soome if ((DIP(fp, di_mode) & IFMT) != IFDIR) { 5724a5d661aSToomas Soome rc = ENOTDIR; 5734a5d661aSToomas Soome goto out; 5744a5d661aSToomas Soome } 5754a5d661aSToomas Soome 5764a5d661aSToomas Soome /* 5774a5d661aSToomas Soome * Get next component of path name. 5784a5d661aSToomas Soome */ 5794a5d661aSToomas Soome { 5804a5d661aSToomas Soome int len = 0; 5814a5d661aSToomas Soome 5824a5d661aSToomas Soome ncp = cp; 5834a5d661aSToomas Soome while ((c = *cp) != '\0' && c != '/') { 5844a5d661aSToomas Soome if (++len > MAXNAMLEN) { 5854a5d661aSToomas Soome rc = ENOENT; 5864a5d661aSToomas Soome goto out; 5874a5d661aSToomas Soome } 5884a5d661aSToomas Soome cp++; 5894a5d661aSToomas Soome } 5904a5d661aSToomas Soome *cp = '\0'; 5914a5d661aSToomas Soome } 5924a5d661aSToomas Soome 5934a5d661aSToomas Soome /* 5944a5d661aSToomas Soome * Look up component in current directory. 5954a5d661aSToomas Soome * Save directory inumber in case we find a 5964a5d661aSToomas Soome * symbolic link. 5974a5d661aSToomas Soome */ 5984a5d661aSToomas Soome parent_inumber = inumber; 5994a5d661aSToomas Soome rc = search_directory(ncp, f, &inumber); 6004a5d661aSToomas Soome *cp = c; 6014a5d661aSToomas Soome if (rc) 6024a5d661aSToomas Soome goto out; 6034a5d661aSToomas Soome 6044a5d661aSToomas Soome /* 6054a5d661aSToomas Soome * Open next component. 6064a5d661aSToomas Soome */ 6074a5d661aSToomas Soome if ((rc = read_inode(inumber, f)) != 0) 6084a5d661aSToomas Soome goto out; 6094a5d661aSToomas Soome 6104a5d661aSToomas Soome /* 6114a5d661aSToomas Soome * Check for symbolic link. 6124a5d661aSToomas Soome */ 6134a5d661aSToomas Soome if ((DIP(fp, di_mode) & IFMT) == IFLNK) { 6144a5d661aSToomas Soome int link_len = DIP(fp, di_size); 6154a5d661aSToomas Soome int len; 6164a5d661aSToomas Soome 6174a5d661aSToomas Soome len = strlen(cp); 6184a5d661aSToomas Soome 6194a5d661aSToomas Soome if (link_len + len > MAXPATHLEN || 6204a5d661aSToomas Soome ++nlinks > MAXSYMLINKS) { 6214a5d661aSToomas Soome rc = ENOENT; 6224a5d661aSToomas Soome goto out; 6234a5d661aSToomas Soome } 6244a5d661aSToomas Soome 6254a5d661aSToomas Soome bcopy(cp, &namebuf[link_len], len + 1); 6264a5d661aSToomas Soome 6274a5d661aSToomas Soome if (link_len < fs->fs_maxsymlinklen) { 6284a5d661aSToomas Soome if (fp->f_fs->fs_magic == FS_UFS1_MAGIC) 6294a5d661aSToomas Soome cp = (caddr_t)(fp->f_di.di1.di_db); 6304a5d661aSToomas Soome else 6314a5d661aSToomas Soome cp = (caddr_t)(fp->f_di.di2.di_db); 6324a5d661aSToomas Soome bcopy(cp, namebuf, (unsigned) link_len); 6334a5d661aSToomas Soome } else { 6344a5d661aSToomas Soome /* 6354a5d661aSToomas Soome * Read file for symbolic link 6364a5d661aSToomas Soome */ 6374a5d661aSToomas Soome size_t buf_size; 6384a5d661aSToomas Soome ufs2_daddr_t disk_block; 6394a5d661aSToomas Soome struct fs *fs = fp->f_fs; 6404a5d661aSToomas Soome 6414a5d661aSToomas Soome if (!buf) 6424a5d661aSToomas Soome buf = malloc(fs->fs_bsize); 6434a5d661aSToomas Soome rc = block_map(f, (ufs2_daddr_t)0, &disk_block); 6444a5d661aSToomas Soome if (rc) 6454a5d661aSToomas Soome goto out; 6464a5d661aSToomas Soome 6474a5d661aSToomas Soome twiddle(1); 6484a5d661aSToomas Soome rc = (f->f_dev->dv_strategy)(f->f_devdata, 649*976852c7SToomas Soome F_READ, fsbtodb(fs, disk_block), 6504a5d661aSToomas Soome fs->fs_bsize, buf, &buf_size); 6514a5d661aSToomas Soome if (rc) 6524a5d661aSToomas Soome goto out; 6534a5d661aSToomas Soome 6544a5d661aSToomas Soome bcopy((char *)buf, namebuf, (unsigned)link_len); 6554a5d661aSToomas Soome } 6564a5d661aSToomas Soome 6574a5d661aSToomas Soome /* 6584a5d661aSToomas Soome * If relative pathname, restart at parent directory. 6594a5d661aSToomas Soome * If absolute pathname, restart at root. 6604a5d661aSToomas Soome */ 6614a5d661aSToomas Soome cp = namebuf; 6624a5d661aSToomas Soome if (*cp != '/') 6634a5d661aSToomas Soome inumber = parent_inumber; 6644a5d661aSToomas Soome else 6654a5d661aSToomas Soome inumber = (ino_t)ROOTINO; 6664a5d661aSToomas Soome 6674a5d661aSToomas Soome if ((rc = read_inode(inumber, f)) != 0) 6684a5d661aSToomas Soome goto out; 6694a5d661aSToomas Soome } 6704a5d661aSToomas Soome } 6714a5d661aSToomas Soome 6724a5d661aSToomas Soome /* 6734a5d661aSToomas Soome * Found terminal component. 6744a5d661aSToomas Soome */ 6754a5d661aSToomas Soome rc = 0; 6764a5d661aSToomas Soome fp->f_seekp = 0; 6774a5d661aSToomas Soome out: 6784a5d661aSToomas Soome if (buf) 6794a5d661aSToomas Soome free(buf); 6804a5d661aSToomas Soome if (path) 6814a5d661aSToomas Soome free(path); 6824a5d661aSToomas Soome if (rc) { 6834a5d661aSToomas Soome if (fp->f_buf) 6844a5d661aSToomas Soome free(fp->f_buf); 6854a5d661aSToomas Soome free(fp->f_fs); 6864a5d661aSToomas Soome free(fp); 6874a5d661aSToomas Soome } 6884a5d661aSToomas Soome return (rc); 6894a5d661aSToomas Soome } 6904a5d661aSToomas Soome 6914a5d661aSToomas Soome static int 6924a5d661aSToomas Soome ufs_close(f) 6934a5d661aSToomas Soome struct open_file *f; 6944a5d661aSToomas Soome { 6954a5d661aSToomas Soome struct file *fp = (struct file *)f->f_fsdata; 6964a5d661aSToomas Soome int level; 6974a5d661aSToomas Soome 6984a5d661aSToomas Soome f->f_fsdata = (void *)0; 6994a5d661aSToomas Soome if (fp == (struct file *)0) 7004a5d661aSToomas Soome return (0); 7014a5d661aSToomas Soome 7024a5d661aSToomas Soome for (level = 0; level < NIADDR; level++) { 7034a5d661aSToomas Soome if (fp->f_blk[level]) 7044a5d661aSToomas Soome free(fp->f_blk[level]); 7054a5d661aSToomas Soome } 7064a5d661aSToomas Soome if (fp->f_buf) 7074a5d661aSToomas Soome free(fp->f_buf); 7084a5d661aSToomas Soome free(fp->f_fs); 7094a5d661aSToomas Soome free(fp); 7104a5d661aSToomas Soome return (0); 7114a5d661aSToomas Soome } 7124a5d661aSToomas Soome 7134a5d661aSToomas Soome /* 7144a5d661aSToomas Soome * Copy a portion of a file into kernel memory. 7154a5d661aSToomas Soome * Cross block boundaries when necessary. 7164a5d661aSToomas Soome */ 7174a5d661aSToomas Soome static int 7184a5d661aSToomas Soome ufs_read(f, start, size, resid) 7194a5d661aSToomas Soome struct open_file *f; 7204a5d661aSToomas Soome void *start; 7214a5d661aSToomas Soome size_t size; 7224a5d661aSToomas Soome size_t *resid; /* out */ 7234a5d661aSToomas Soome { 7244a5d661aSToomas Soome struct file *fp = (struct file *)f->f_fsdata; 7254a5d661aSToomas Soome size_t csize; 7264a5d661aSToomas Soome char *buf; 7274a5d661aSToomas Soome size_t buf_size; 7284a5d661aSToomas Soome int rc = 0; 7294a5d661aSToomas Soome char *addr = start; 7304a5d661aSToomas Soome 7314a5d661aSToomas Soome while (size != 0) { 7324a5d661aSToomas Soome if (fp->f_seekp >= DIP(fp, di_size)) 7334a5d661aSToomas Soome break; 7344a5d661aSToomas Soome 7354a5d661aSToomas Soome rc = buf_read_file(f, &buf, &buf_size); 7364a5d661aSToomas Soome if (rc) 7374a5d661aSToomas Soome break; 7384a5d661aSToomas Soome 7394a5d661aSToomas Soome csize = size; 7404a5d661aSToomas Soome if (csize > buf_size) 7414a5d661aSToomas Soome csize = buf_size; 7424a5d661aSToomas Soome 7434a5d661aSToomas Soome bcopy(buf, addr, csize); 7444a5d661aSToomas Soome 7454a5d661aSToomas Soome fp->f_seekp += csize; 7464a5d661aSToomas Soome addr += csize; 7474a5d661aSToomas Soome size -= csize; 7484a5d661aSToomas Soome } 7494a5d661aSToomas Soome if (resid) 7504a5d661aSToomas Soome *resid = size; 7514a5d661aSToomas Soome return (rc); 7524a5d661aSToomas Soome } 7534a5d661aSToomas Soome 7544a5d661aSToomas Soome /* 7554a5d661aSToomas Soome * Write to a portion of an already allocated file. 7564a5d661aSToomas Soome * Cross block boundaries when necessary. Can not 7574a5d661aSToomas Soome * extend the file. 7584a5d661aSToomas Soome */ 7594a5d661aSToomas Soome static int 7604a5d661aSToomas Soome ufs_write(f, start, size, resid) 7614a5d661aSToomas Soome struct open_file *f; 7624a5d661aSToomas Soome void *start; 7634a5d661aSToomas Soome size_t size; 7644a5d661aSToomas Soome size_t *resid; /* out */ 7654a5d661aSToomas Soome { 7664a5d661aSToomas Soome struct file *fp = (struct file *)f->f_fsdata; 7674a5d661aSToomas Soome size_t csize; 7684a5d661aSToomas Soome int rc = 0; 7694a5d661aSToomas Soome char *addr = start; 7704a5d661aSToomas Soome 7714a5d661aSToomas Soome csize = size; 7724a5d661aSToomas Soome while ((size != 0) && (csize != 0)) { 7734a5d661aSToomas Soome if (fp->f_seekp >= DIP(fp, di_size)) 7744a5d661aSToomas Soome break; 7754a5d661aSToomas Soome 7764a5d661aSToomas Soome if (csize >= 512) csize = 512; /* XXX */ 7774a5d661aSToomas Soome 7784a5d661aSToomas Soome rc = buf_write_file(f, addr, &csize); 7794a5d661aSToomas Soome if (rc) 7804a5d661aSToomas Soome break; 7814a5d661aSToomas Soome 7824a5d661aSToomas Soome fp->f_seekp += csize; 7834a5d661aSToomas Soome addr += csize; 7844a5d661aSToomas Soome size -= csize; 7854a5d661aSToomas Soome } 7864a5d661aSToomas Soome if (resid) 7874a5d661aSToomas Soome *resid = size; 7884a5d661aSToomas Soome return (rc); 7894a5d661aSToomas Soome } 7904a5d661aSToomas Soome 7914a5d661aSToomas Soome static off_t 7924a5d661aSToomas Soome ufs_seek(f, offset, where) 7934a5d661aSToomas Soome struct open_file *f; 7944a5d661aSToomas Soome off_t offset; 7954a5d661aSToomas Soome int where; 7964a5d661aSToomas Soome { 7974a5d661aSToomas Soome struct file *fp = (struct file *)f->f_fsdata; 7984a5d661aSToomas Soome 7994a5d661aSToomas Soome switch (where) { 8004a5d661aSToomas Soome case SEEK_SET: 8014a5d661aSToomas Soome fp->f_seekp = offset; 8024a5d661aSToomas Soome break; 8034a5d661aSToomas Soome case SEEK_CUR: 8044a5d661aSToomas Soome fp->f_seekp += offset; 8054a5d661aSToomas Soome break; 8064a5d661aSToomas Soome case SEEK_END: 8074a5d661aSToomas Soome fp->f_seekp = DIP(fp, di_size) - offset; 8084a5d661aSToomas Soome break; 8094a5d661aSToomas Soome default: 8104a5d661aSToomas Soome errno = EINVAL; 8114a5d661aSToomas Soome return (-1); 8124a5d661aSToomas Soome } 8134a5d661aSToomas Soome return (fp->f_seekp); 8144a5d661aSToomas Soome } 8154a5d661aSToomas Soome 8164a5d661aSToomas Soome static int 8174a5d661aSToomas Soome ufs_stat(f, sb) 8184a5d661aSToomas Soome struct open_file *f; 8194a5d661aSToomas Soome struct stat *sb; 8204a5d661aSToomas Soome { 8214a5d661aSToomas Soome struct file *fp = (struct file *)f->f_fsdata; 8224a5d661aSToomas Soome 8234a5d661aSToomas Soome /* only important stuff */ 8244a5d661aSToomas Soome sb->st_mode = DIP(fp, di_mode); 8254a5d661aSToomas Soome sb->st_uid = DIP(fp, di_uid); 8264a5d661aSToomas Soome sb->st_gid = DIP(fp, di_gid); 8274a5d661aSToomas Soome sb->st_size = DIP(fp, di_size); 8284a5d661aSToomas Soome return (0); 8294a5d661aSToomas Soome } 8304a5d661aSToomas Soome 8314a5d661aSToomas Soome static int 8324a5d661aSToomas Soome ufs_readdir(struct open_file *f, struct dirent *d) 8334a5d661aSToomas Soome { 8344a5d661aSToomas Soome struct file *fp = (struct file *)f->f_fsdata; 8354a5d661aSToomas Soome struct direct *dp; 8364a5d661aSToomas Soome char *buf; 8374a5d661aSToomas Soome size_t buf_size; 8384a5d661aSToomas Soome int error; 8394a5d661aSToomas Soome 8404a5d661aSToomas Soome /* 8414a5d661aSToomas Soome * assume that a directory entry will not be split across blocks 8424a5d661aSToomas Soome */ 8434a5d661aSToomas Soome again: 8444a5d661aSToomas Soome if (fp->f_seekp >= DIP(fp, di_size)) 8454a5d661aSToomas Soome return (ENOENT); 8464a5d661aSToomas Soome error = buf_read_file(f, &buf, &buf_size); 8474a5d661aSToomas Soome if (error) 8484a5d661aSToomas Soome return (error); 8494a5d661aSToomas Soome dp = (struct direct *)buf; 8504a5d661aSToomas Soome fp->f_seekp += dp->d_reclen; 8514a5d661aSToomas Soome if (dp->d_ino == (ino_t)0) 8524a5d661aSToomas Soome goto again; 8534a5d661aSToomas Soome 8544a5d661aSToomas Soome d->d_type = 0; /* illumos ufs does not have type in direct */ 8554a5d661aSToomas Soome strcpy(d->d_name, dp->d_name); 8564a5d661aSToomas Soome return (0); 8574a5d661aSToomas Soome } 858