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 724a5d661aSToomas Soome /* 734a5d661aSToomas Soome * Stand-alone file reading package. 744a5d661aSToomas Soome */ 754a5d661aSToomas Soome 764a5d661aSToomas Soome #include <sys/param.h> 774a5d661aSToomas Soome #include <sys/disklabel.h> 784a5d661aSToomas Soome #include <sys/time.h> 794a5d661aSToomas Soome #include <ufs/ufs/dinode.h> 804a5d661aSToomas Soome #include <ufs/ufs/dir.h> 814a5d661aSToomas Soome #include <ufs/ffs/fs.h> 824a5d661aSToomas Soome #include "stand.h" 834a5d661aSToomas Soome #include "string.h" 844a5d661aSToomas Soome 854a5d661aSToomas Soome static int ufs_open(const char *path, struct open_file *f); 864a5d661aSToomas Soome static int ufs_write(struct open_file *f, void *buf, size_t size, size_t *resid); 874a5d661aSToomas Soome static int ufs_close(struct open_file *f); 884a5d661aSToomas Soome static int ufs_read(struct open_file *f, void *buf, size_t size, size_t *resid); 894a5d661aSToomas Soome static off_t ufs_seek(struct open_file *f, off_t offset, int where); 904a5d661aSToomas Soome static int ufs_stat(struct open_file *f, struct stat *sb); 914a5d661aSToomas Soome static int ufs_readdir(struct open_file *f, struct dirent *d); 924a5d661aSToomas Soome 934a5d661aSToomas Soome struct fs_ops ufs_fsops = { 944a5d661aSToomas Soome "ufs", 954a5d661aSToomas Soome ufs_open, 964a5d661aSToomas Soome ufs_close, 974a5d661aSToomas Soome ufs_read, 984a5d661aSToomas Soome ufs_write, 994a5d661aSToomas Soome ufs_seek, 1004a5d661aSToomas Soome ufs_stat, 1014a5d661aSToomas Soome ufs_readdir 1024a5d661aSToomas Soome }; 1034a5d661aSToomas Soome 1044a5d661aSToomas Soome /* 1054a5d661aSToomas Soome * In-core open file. 1064a5d661aSToomas Soome */ 1074a5d661aSToomas Soome struct file { 1084a5d661aSToomas Soome off_t f_seekp; /* seek pointer */ 1094a5d661aSToomas Soome struct fs *f_fs; /* pointer to super-block */ 1104a5d661aSToomas Soome union dinode { 1114a5d661aSToomas Soome struct ufs1_dinode di1; 1124a5d661aSToomas Soome struct ufs2_dinode di2; 1134a5d661aSToomas Soome } f_di; /* copy of on-disk inode */ 1144a5d661aSToomas Soome int f_nindir[NIADDR]; 1154a5d661aSToomas Soome /* number of blocks mapped by 1164a5d661aSToomas Soome indirect block at level i */ 1174a5d661aSToomas Soome char *f_blk[NIADDR]; /* buffer for indirect block at 1184a5d661aSToomas Soome level i */ 1194a5d661aSToomas Soome size_t f_blksize[NIADDR]; 1204a5d661aSToomas Soome /* size of buffer */ 1214a5d661aSToomas Soome ufs2_daddr_t f_blkno[NIADDR];/* disk address of block in buffer */ 1224a5d661aSToomas Soome ufs2_daddr_t f_buf_blkno; /* block number of data block */ 1234a5d661aSToomas Soome char *f_buf; /* buffer for data block */ 1244a5d661aSToomas Soome size_t f_buf_size; /* size of data block */ 1254a5d661aSToomas Soome }; 1264a5d661aSToomas Soome #define DIP(fp, field) \ 1274a5d661aSToomas Soome ((fp)->f_fs->fs_magic == FS_UFS1_MAGIC ? \ 1284a5d661aSToomas Soome (fp)->f_di.di1.field : (fp)->f_di.di2.field) 1294a5d661aSToomas Soome 1304a5d661aSToomas Soome static int read_inode(ino_t, struct open_file *); 1314a5d661aSToomas Soome static int block_map(struct open_file *, ufs2_daddr_t, ufs2_daddr_t *); 1324a5d661aSToomas Soome static int buf_read_file(struct open_file *, char **, size_t *); 1334a5d661aSToomas Soome static int buf_write_file(struct open_file *, char *, size_t *); 1344a5d661aSToomas Soome static int search_directory(char *, struct open_file *, ino_t *); 1354a5d661aSToomas Soome 1364a5d661aSToomas Soome /* 1374a5d661aSToomas Soome * Read a new inode into a file structure. 1384a5d661aSToomas Soome */ 1394a5d661aSToomas Soome static int 1404a5d661aSToomas Soome read_inode(inumber, f) 1414a5d661aSToomas Soome ino_t inumber; 1424a5d661aSToomas Soome struct open_file *f; 1434a5d661aSToomas Soome { 1444a5d661aSToomas Soome struct file *fp = (struct file *)f->f_fsdata; 1454a5d661aSToomas Soome struct fs *fs = fp->f_fs; 1464a5d661aSToomas Soome char *buf; 1474a5d661aSToomas Soome size_t rsize; 1484a5d661aSToomas Soome int rc; 1494a5d661aSToomas Soome 1504a5d661aSToomas Soome if (fs == NULL) 1514a5d661aSToomas Soome panic("fs == NULL"); 1524a5d661aSToomas Soome 1534a5d661aSToomas Soome /* 1544a5d661aSToomas Soome * Read inode and save it. 1554a5d661aSToomas Soome */ 1564a5d661aSToomas Soome buf = malloc(fs->fs_bsize); 1574a5d661aSToomas Soome twiddle(1); 1584a5d661aSToomas Soome rc = (f->f_dev->dv_strategy)(f->f_devdata, F_READ, 159976852c7SToomas Soome fsbtodb(fs, ino_to_fsba(fs, inumber)), fs->fs_bsize, 1604a5d661aSToomas Soome buf, &rsize); 1614a5d661aSToomas Soome if (rc) 1624a5d661aSToomas Soome goto out; 1634a5d661aSToomas Soome if (rsize != fs->fs_bsize) { 1644a5d661aSToomas Soome rc = EIO; 1654a5d661aSToomas Soome goto out; 1664a5d661aSToomas Soome } 1674a5d661aSToomas Soome 1684a5d661aSToomas Soome if (fp->f_fs->fs_magic == FS_UFS1_MAGIC) 1694a5d661aSToomas Soome fp->f_di.di1 = ((struct ufs1_dinode *)buf) 1704a5d661aSToomas Soome [ino_to_fsbo(fs, inumber)]; 1714a5d661aSToomas Soome else 1724a5d661aSToomas Soome fp->f_di.di2 = ((struct ufs2_dinode *)buf) 1734a5d661aSToomas Soome [ino_to_fsbo(fs, inumber)]; 1744a5d661aSToomas Soome 1754a5d661aSToomas Soome /* 1764a5d661aSToomas Soome * Clear out the old buffers 1774a5d661aSToomas Soome */ 1784a5d661aSToomas Soome { 1794a5d661aSToomas Soome int level; 1804a5d661aSToomas Soome 1814a5d661aSToomas Soome for (level = 0; level < NIADDR; level++) 1824a5d661aSToomas Soome fp->f_blkno[level] = -1; 1834a5d661aSToomas Soome fp->f_buf_blkno = -1; 1844a5d661aSToomas Soome } 1854a5d661aSToomas Soome fp->f_seekp = 0; 1864a5d661aSToomas Soome out: 1874a5d661aSToomas Soome free(buf); 1884a5d661aSToomas Soome return (rc); 1894a5d661aSToomas Soome } 1904a5d661aSToomas Soome 1914a5d661aSToomas Soome /* 1924a5d661aSToomas Soome * Given an offset in a file, find the disk block number that 1934a5d661aSToomas Soome * contains that block. 1944a5d661aSToomas Soome */ 1954a5d661aSToomas Soome static int 1964a5d661aSToomas Soome block_map(f, file_block, disk_block_p) 1974a5d661aSToomas Soome struct open_file *f; 1984a5d661aSToomas Soome ufs2_daddr_t file_block; 1994a5d661aSToomas Soome ufs2_daddr_t *disk_block_p; /* out */ 2004a5d661aSToomas Soome { 2014a5d661aSToomas Soome struct file *fp = (struct file *)f->f_fsdata; 2024a5d661aSToomas Soome struct fs *fs = fp->f_fs; 2034a5d661aSToomas Soome int level; 2044a5d661aSToomas Soome int idx; 2054a5d661aSToomas Soome ufs2_daddr_t ind_block_num; 2064a5d661aSToomas Soome int rc; 2074a5d661aSToomas Soome 2084a5d661aSToomas Soome /* 2094a5d661aSToomas Soome * Index structure of an inode: 2104a5d661aSToomas Soome * 2114a5d661aSToomas Soome * di_db[0..NDADDR-1] hold block numbers for blocks 2124a5d661aSToomas Soome * 0..NDADDR-1 2134a5d661aSToomas Soome * 2144a5d661aSToomas Soome * di_ib[0] index block 0 is the single indirect block 2154a5d661aSToomas Soome * holds block numbers for blocks 2164a5d661aSToomas Soome * NDADDR .. NDADDR + NINDIR(fs)-1 2174a5d661aSToomas Soome * 2184a5d661aSToomas Soome * di_ib[1] index block 1 is the double indirect block 2194a5d661aSToomas Soome * holds block numbers for INDEX blocks for blocks 2204a5d661aSToomas Soome * NDADDR + NINDIR(fs) .. 2214a5d661aSToomas Soome * NDADDR + NINDIR(fs) + NINDIR(fs)**2 - 1 2224a5d661aSToomas Soome * 2234a5d661aSToomas Soome * di_ib[2] index block 2 is the triple indirect block 2244a5d661aSToomas Soome * holds block numbers for double-indirect 2254a5d661aSToomas Soome * blocks for blocks 2264a5d661aSToomas Soome * NDADDR + NINDIR(fs) + NINDIR(fs)**2 .. 2274a5d661aSToomas Soome * NDADDR + NINDIR(fs) + NINDIR(fs)**2 2284a5d661aSToomas Soome * + NINDIR(fs)**3 - 1 2294a5d661aSToomas Soome */ 2304a5d661aSToomas Soome 2314a5d661aSToomas Soome if (file_block < NDADDR) { 2324a5d661aSToomas Soome /* Direct block. */ 2334a5d661aSToomas Soome *disk_block_p = DIP(fp, di_db[file_block]); 2344a5d661aSToomas Soome return (0); 2354a5d661aSToomas Soome } 2364a5d661aSToomas Soome 2374a5d661aSToomas Soome file_block -= NDADDR; 2384a5d661aSToomas Soome 2394a5d661aSToomas Soome /* 2404a5d661aSToomas Soome * nindir[0] = NINDIR 2414a5d661aSToomas Soome * nindir[1] = NINDIR**2 2424a5d661aSToomas Soome * nindir[2] = NINDIR**3 2434a5d661aSToomas Soome * etc 2444a5d661aSToomas Soome */ 2454a5d661aSToomas Soome for (level = 0; level < NIADDR; level++) { 2464a5d661aSToomas Soome if (file_block < fp->f_nindir[level]) 2474a5d661aSToomas Soome break; 2484a5d661aSToomas Soome file_block -= fp->f_nindir[level]; 2494a5d661aSToomas Soome } 2504a5d661aSToomas Soome if (level == NIADDR) { 2514a5d661aSToomas Soome /* Block number too high */ 2524a5d661aSToomas Soome return (EFBIG); 2534a5d661aSToomas Soome } 2544a5d661aSToomas Soome 2554a5d661aSToomas Soome ind_block_num = DIP(fp, di_ib[level]); 2564a5d661aSToomas Soome 2574a5d661aSToomas Soome for (; level >= 0; level--) { 2584a5d661aSToomas Soome if (ind_block_num == 0) { 2594a5d661aSToomas Soome *disk_block_p = 0; /* missing */ 2604a5d661aSToomas Soome return (0); 2614a5d661aSToomas Soome } 2624a5d661aSToomas Soome 2634a5d661aSToomas Soome if (fp->f_blkno[level] != ind_block_num) { 2644a5d661aSToomas Soome if (fp->f_blk[level] == (char *)0) 2654a5d661aSToomas Soome fp->f_blk[level] = 2664a5d661aSToomas Soome malloc(fs->fs_bsize); 2674a5d661aSToomas Soome twiddle(1); 2684a5d661aSToomas Soome rc = (f->f_dev->dv_strategy)(f->f_devdata, F_READ, 269976852c7SToomas Soome fsbtodb(fp->f_fs, ind_block_num), 2704a5d661aSToomas Soome fs->fs_bsize, 2714a5d661aSToomas Soome fp->f_blk[level], 2724a5d661aSToomas Soome &fp->f_blksize[level]); 2734a5d661aSToomas Soome if (rc) 2744a5d661aSToomas Soome return (rc); 2754a5d661aSToomas Soome if (fp->f_blksize[level] != fs->fs_bsize) 2764a5d661aSToomas Soome return (EIO); 2774a5d661aSToomas Soome fp->f_blkno[level] = ind_block_num; 2784a5d661aSToomas Soome } 2794a5d661aSToomas Soome 2804a5d661aSToomas Soome if (level > 0) { 2814a5d661aSToomas Soome idx = file_block / fp->f_nindir[level - 1]; 2824a5d661aSToomas Soome file_block %= fp->f_nindir[level - 1]; 2834a5d661aSToomas Soome } else 2844a5d661aSToomas Soome idx = file_block; 2854a5d661aSToomas Soome 2864a5d661aSToomas Soome if (fp->f_fs->fs_magic == FS_UFS1_MAGIC) 2874a5d661aSToomas Soome ind_block_num = ((ufs1_daddr_t *)fp->f_blk[level])[idx]; 2884a5d661aSToomas Soome else 2894a5d661aSToomas Soome ind_block_num = ((ufs2_daddr_t *)fp->f_blk[level])[idx]; 2904a5d661aSToomas Soome } 2914a5d661aSToomas Soome 2924a5d661aSToomas Soome *disk_block_p = ind_block_num; 2934a5d661aSToomas Soome 2944a5d661aSToomas Soome return (0); 2954a5d661aSToomas Soome } 2964a5d661aSToomas Soome 2974a5d661aSToomas Soome /* 2984a5d661aSToomas Soome * Write a portion of a file from an internal buffer. 2994a5d661aSToomas Soome */ 3004a5d661aSToomas Soome static int 3014a5d661aSToomas Soome buf_write_file(f, buf_p, size_p) 3024a5d661aSToomas Soome struct open_file *f; 3034a5d661aSToomas Soome char *buf_p; 3044a5d661aSToomas Soome size_t *size_p; /* out */ 3054a5d661aSToomas Soome { 3064a5d661aSToomas Soome struct file *fp = (struct file *)f->f_fsdata; 3074a5d661aSToomas Soome struct fs *fs = fp->f_fs; 3084a5d661aSToomas Soome long off; 3094a5d661aSToomas Soome ufs_lbn_t file_block; 3104a5d661aSToomas Soome ufs2_daddr_t disk_block; 3114a5d661aSToomas Soome size_t block_size; 3124a5d661aSToomas Soome int rc; 3134a5d661aSToomas Soome 3144a5d661aSToomas Soome /* 3154a5d661aSToomas Soome * Calculate the starting block address and offset. 3164a5d661aSToomas Soome */ 3174a5d661aSToomas Soome off = blkoff(fs, fp->f_seekp); 3184a5d661aSToomas Soome file_block = lblkno(fs, fp->f_seekp); 3194a5d661aSToomas Soome block_size = sblksize(fs, DIP(fp, di_size), file_block); 3204a5d661aSToomas Soome 3214a5d661aSToomas Soome rc = block_map(f, file_block, &disk_block); 3224a5d661aSToomas Soome if (rc) 3234a5d661aSToomas Soome return (rc); 3244a5d661aSToomas Soome 3254a5d661aSToomas Soome if (disk_block == 0) 3264a5d661aSToomas Soome /* Because we can't allocate space on the drive */ 3274a5d661aSToomas Soome return (EFBIG); 3284a5d661aSToomas Soome 3294a5d661aSToomas Soome /* 3304a5d661aSToomas Soome * Truncate buffer at end of file, and at the end of 3314a5d661aSToomas Soome * this block. 3324a5d661aSToomas Soome */ 3334a5d661aSToomas Soome if (*size_p > DIP(fp, di_size) - fp->f_seekp) 3344a5d661aSToomas Soome *size_p = DIP(fp, di_size) - fp->f_seekp; 3354a5d661aSToomas Soome if (*size_p > block_size - off) 3364a5d661aSToomas Soome *size_p = block_size - off; 3374a5d661aSToomas Soome 3384a5d661aSToomas Soome /* 3394a5d661aSToomas Soome * If we don't entirely occlude the block and it's not 3404a5d661aSToomas Soome * in memory already, read it in first. 3414a5d661aSToomas Soome */ 3424a5d661aSToomas Soome if (((off > 0) || (*size_p + off < block_size)) && 3434a5d661aSToomas Soome (file_block != fp->f_buf_blkno)) { 3444a5d661aSToomas Soome 3454a5d661aSToomas Soome if (fp->f_buf == (char *)0) 3464a5d661aSToomas Soome fp->f_buf = malloc(fs->fs_bsize); 3474a5d661aSToomas Soome 3484a5d661aSToomas Soome twiddle(8); 3494a5d661aSToomas Soome rc = (f->f_dev->dv_strategy)(f->f_devdata, F_READ, 350976852c7SToomas Soome fsbtodb(fs, disk_block), 3514a5d661aSToomas Soome block_size, fp->f_buf, &fp->f_buf_size); 3524a5d661aSToomas Soome if (rc) 3534a5d661aSToomas Soome return (rc); 3544a5d661aSToomas Soome 3554a5d661aSToomas Soome fp->f_buf_blkno = file_block; 3564a5d661aSToomas Soome } 3574a5d661aSToomas Soome 3584a5d661aSToomas Soome /* 3594a5d661aSToomas Soome * Copy the user data into the cached block. 3604a5d661aSToomas Soome */ 3614a5d661aSToomas Soome bcopy(buf_p, fp->f_buf + off, *size_p); 3624a5d661aSToomas Soome 3634a5d661aSToomas Soome /* 3644a5d661aSToomas Soome * Write the block out to storage. 3654a5d661aSToomas Soome */ 3664a5d661aSToomas Soome 3674a5d661aSToomas Soome twiddle(4); 3684a5d661aSToomas Soome rc = (f->f_dev->dv_strategy)(f->f_devdata, F_WRITE, 369976852c7SToomas Soome fsbtodb(fs, disk_block), 3704a5d661aSToomas Soome block_size, fp->f_buf, &fp->f_buf_size); 3714a5d661aSToomas Soome return (rc); 3724a5d661aSToomas Soome } 3734a5d661aSToomas Soome 3744a5d661aSToomas Soome /* 3754a5d661aSToomas Soome * Read a portion of a file into an internal buffer. Return 3764a5d661aSToomas Soome * the location in the buffer and the amount in the buffer. 3774a5d661aSToomas Soome */ 3784a5d661aSToomas Soome static int 3794a5d661aSToomas Soome buf_read_file(f, buf_p, size_p) 3804a5d661aSToomas Soome struct open_file *f; 3814a5d661aSToomas Soome char **buf_p; /* out */ 3824a5d661aSToomas Soome size_t *size_p; /* out */ 3834a5d661aSToomas Soome { 3844a5d661aSToomas Soome struct file *fp = (struct file *)f->f_fsdata; 3854a5d661aSToomas Soome struct fs *fs = fp->f_fs; 3864a5d661aSToomas Soome long off; 3874a5d661aSToomas Soome ufs_lbn_t file_block; 3884a5d661aSToomas Soome ufs2_daddr_t disk_block; 3894a5d661aSToomas Soome size_t block_size; 3904a5d661aSToomas Soome int rc; 3914a5d661aSToomas Soome 3924a5d661aSToomas Soome off = blkoff(fs, fp->f_seekp); 3934a5d661aSToomas Soome file_block = lblkno(fs, fp->f_seekp); 3944a5d661aSToomas Soome block_size = sblksize(fs, DIP(fp, di_size), file_block); 3954a5d661aSToomas Soome 3964a5d661aSToomas Soome if (file_block != fp->f_buf_blkno) { 3974a5d661aSToomas Soome if (fp->f_buf == (char *)0) 3984a5d661aSToomas Soome fp->f_buf = malloc(fs->fs_bsize); 3994a5d661aSToomas Soome 4004a5d661aSToomas Soome rc = block_map(f, file_block, &disk_block); 4014a5d661aSToomas Soome if (rc) 4024a5d661aSToomas Soome return (rc); 4034a5d661aSToomas Soome 4044a5d661aSToomas Soome if (disk_block == 0) { 4054a5d661aSToomas Soome bzero(fp->f_buf, block_size); 4064a5d661aSToomas Soome fp->f_buf_size = block_size; 4074a5d661aSToomas Soome } else { 4084a5d661aSToomas Soome twiddle(4); 4094a5d661aSToomas Soome rc = (f->f_dev->dv_strategy)(f->f_devdata, 410976852c7SToomas Soome F_READ, fsbtodb(fs, disk_block), 4114a5d661aSToomas Soome block_size, fp->f_buf, &fp->f_buf_size); 4124a5d661aSToomas Soome if (rc) 4134a5d661aSToomas Soome return (rc); 4144a5d661aSToomas Soome } 4154a5d661aSToomas Soome 4164a5d661aSToomas Soome fp->f_buf_blkno = file_block; 4174a5d661aSToomas Soome } 4184a5d661aSToomas Soome 4194a5d661aSToomas Soome /* 4204a5d661aSToomas Soome * Return address of byte in buffer corresponding to 4214a5d661aSToomas Soome * offset, and size of remainder of buffer after that 4224a5d661aSToomas Soome * byte. 4234a5d661aSToomas Soome */ 4244a5d661aSToomas Soome *buf_p = fp->f_buf + off; 4254a5d661aSToomas Soome *size_p = block_size - off; 4264a5d661aSToomas Soome 4274a5d661aSToomas Soome /* 4284a5d661aSToomas Soome * But truncate buffer at end of file. 4294a5d661aSToomas Soome */ 4304a5d661aSToomas Soome if (*size_p > DIP(fp, di_size) - fp->f_seekp) 4314a5d661aSToomas Soome *size_p = DIP(fp, di_size) - fp->f_seekp; 4324a5d661aSToomas Soome 4334a5d661aSToomas Soome return (0); 4344a5d661aSToomas Soome } 4354a5d661aSToomas Soome 4364a5d661aSToomas Soome /* 4374a5d661aSToomas Soome * Search a directory for a name and return its 4384a5d661aSToomas Soome * i_number. 4394a5d661aSToomas Soome */ 4404a5d661aSToomas Soome static int 4414a5d661aSToomas Soome search_directory(name, f, inumber_p) 4424a5d661aSToomas Soome char *name; 4434a5d661aSToomas Soome struct open_file *f; 4444a5d661aSToomas Soome ino_t *inumber_p; /* out */ 4454a5d661aSToomas Soome { 4464a5d661aSToomas Soome struct file *fp = (struct file *)f->f_fsdata; 4474a5d661aSToomas Soome struct direct *dp; 4484a5d661aSToomas Soome struct direct *edp; 4494a5d661aSToomas Soome char *buf; 4504a5d661aSToomas Soome size_t buf_size; 4514a5d661aSToomas Soome int namlen, length; 4524a5d661aSToomas Soome int rc; 4534a5d661aSToomas Soome 4544a5d661aSToomas Soome length = strlen(name); 4554a5d661aSToomas Soome 4564a5d661aSToomas Soome fp->f_seekp = 0; 4574a5d661aSToomas Soome while (fp->f_seekp < DIP(fp, di_size)) { 4584a5d661aSToomas Soome rc = buf_read_file(f, &buf, &buf_size); 4594a5d661aSToomas Soome if (rc) 4604a5d661aSToomas Soome return (rc); 4614a5d661aSToomas Soome 4624a5d661aSToomas Soome dp = (struct direct *)buf; 4634a5d661aSToomas Soome edp = (struct direct *)(buf + buf_size); 4644a5d661aSToomas Soome while (dp < edp) { 4654a5d661aSToomas Soome if (dp->d_ino == (ino_t)0) 4664a5d661aSToomas Soome goto next; 4674a5d661aSToomas Soome namlen = dp->d_namlen; 4684a5d661aSToomas Soome if (namlen == length && 4694a5d661aSToomas Soome !strcmp(name, dp->d_name)) { 4704a5d661aSToomas Soome /* found entry */ 4714a5d661aSToomas Soome *inumber_p = dp->d_ino; 4724a5d661aSToomas Soome return (0); 4734a5d661aSToomas Soome } 4744a5d661aSToomas Soome next: 4754a5d661aSToomas Soome dp = (struct direct *)((char *)dp + dp->d_reclen); 4764a5d661aSToomas Soome } 4774a5d661aSToomas Soome fp->f_seekp += buf_size; 4784a5d661aSToomas Soome } 4794a5d661aSToomas Soome return (ENOENT); 4804a5d661aSToomas Soome } 4814a5d661aSToomas Soome 4824a5d661aSToomas Soome static int sblock_try[] = SBLOCKSEARCH; 4834a5d661aSToomas Soome 4844a5d661aSToomas Soome /* 4854a5d661aSToomas Soome * Open a file. 4864a5d661aSToomas Soome */ 4874a5d661aSToomas Soome static int 4884a5d661aSToomas Soome ufs_open(upath, f) 4894a5d661aSToomas Soome const char *upath; 4904a5d661aSToomas Soome struct open_file *f; 4914a5d661aSToomas Soome { 4924a5d661aSToomas Soome char *cp, *ncp; 4934a5d661aSToomas Soome int c; 4944a5d661aSToomas Soome ino_t inumber, parent_inumber; 4954a5d661aSToomas Soome struct file *fp; 4964a5d661aSToomas Soome struct fs *fs; 4974a5d661aSToomas Soome int i, rc; 4984a5d661aSToomas Soome size_t buf_size; 4994a5d661aSToomas Soome int nlinks = 0; 5004a5d661aSToomas Soome char namebuf[MAXPATHLEN+1]; 5014a5d661aSToomas Soome char *buf = NULL; 5024a5d661aSToomas Soome char *path = NULL; 5034a5d661aSToomas Soome 5044a5d661aSToomas Soome /* allocate file system specific data structure */ 5054a5d661aSToomas Soome fp = malloc(sizeof(struct file)); 5064a5d661aSToomas Soome bzero(fp, sizeof(struct file)); 5074a5d661aSToomas Soome f->f_fsdata = (void *)fp; 5084a5d661aSToomas Soome 5094a5d661aSToomas Soome /* allocate space and read super block */ 5104a5d661aSToomas Soome fs = malloc(SBLOCKSIZE); 5114a5d661aSToomas Soome fp->f_fs = fs; 5124a5d661aSToomas Soome twiddle(1); 5134a5d661aSToomas Soome /* 5144a5d661aSToomas Soome * Try reading the superblock in each of its possible locations. 5154a5d661aSToomas Soome */ 5164a5d661aSToomas Soome for (i = 0; sblock_try[i] != -1; i++) { 5174a5d661aSToomas Soome rc = (f->f_dev->dv_strategy)(f->f_devdata, F_READ, 518976852c7SToomas Soome sblock_try[i] / DEV_BSIZE, SBLOCKSIZE, 5194a5d661aSToomas Soome (char *)fs, &buf_size); 5204a5d661aSToomas Soome if (rc) 5214a5d661aSToomas Soome goto out; 5224a5d661aSToomas Soome if ((fs->fs_magic == FS_UFS1_MAGIC || 5234a5d661aSToomas Soome (fs->fs_magic == FS_UFS2_MAGIC && 5244a5d661aSToomas Soome fs->fs_sblockloc == sblock_try[i])) && 5254a5d661aSToomas Soome buf_size == SBLOCKSIZE && 5264a5d661aSToomas Soome fs->fs_bsize <= MAXBSIZE && 5274a5d661aSToomas Soome fs->fs_bsize >= sizeof(struct fs)) 5284a5d661aSToomas Soome break; 5294a5d661aSToomas Soome } 5304a5d661aSToomas Soome if (sblock_try[i] == -1) { 5314a5d661aSToomas Soome rc = EINVAL; 5324a5d661aSToomas Soome goto out; 5334a5d661aSToomas Soome } 5344a5d661aSToomas Soome /* 5354a5d661aSToomas Soome * Calculate indirect block levels. 5364a5d661aSToomas Soome */ 5374a5d661aSToomas Soome { 5384a5d661aSToomas Soome ufs2_daddr_t mult; 5394a5d661aSToomas Soome int level; 5404a5d661aSToomas Soome 5414a5d661aSToomas Soome mult = 1; 5424a5d661aSToomas Soome for (level = 0; level < NIADDR; level++) { 5434a5d661aSToomas Soome mult *= NINDIR(fs); 5444a5d661aSToomas Soome fp->f_nindir[level] = mult; 5454a5d661aSToomas Soome } 5464a5d661aSToomas Soome } 5474a5d661aSToomas Soome 5484a5d661aSToomas Soome inumber = ROOTINO; 5494a5d661aSToomas Soome if ((rc = read_inode(inumber, f)) != 0) 5504a5d661aSToomas Soome goto out; 5514a5d661aSToomas Soome 5524a5d661aSToomas Soome cp = path = strdup(upath); 5534a5d661aSToomas Soome if (path == NULL) { 5544a5d661aSToomas Soome rc = ENOMEM; 5554a5d661aSToomas Soome goto out; 5564a5d661aSToomas Soome } 5574a5d661aSToomas Soome while (*cp) { 5584a5d661aSToomas Soome 5594a5d661aSToomas Soome /* 5604a5d661aSToomas Soome * Remove extra separators 5614a5d661aSToomas Soome */ 5624a5d661aSToomas Soome while (*cp == '/') 5634a5d661aSToomas Soome cp++; 5644a5d661aSToomas Soome if (*cp == '\0') 5654a5d661aSToomas Soome break; 5664a5d661aSToomas Soome 5674a5d661aSToomas Soome /* 5684a5d661aSToomas Soome * Check that current node is a directory. 5694a5d661aSToomas Soome */ 5704a5d661aSToomas Soome if ((DIP(fp, di_mode) & IFMT) != IFDIR) { 5714a5d661aSToomas Soome rc = ENOTDIR; 5724a5d661aSToomas Soome goto out; 5734a5d661aSToomas Soome } 5744a5d661aSToomas Soome 5754a5d661aSToomas Soome /* 5764a5d661aSToomas Soome * Get next component of path name. 5774a5d661aSToomas Soome */ 5784a5d661aSToomas Soome { 5794a5d661aSToomas Soome int len = 0; 5804a5d661aSToomas Soome 5814a5d661aSToomas Soome ncp = cp; 5824a5d661aSToomas Soome while ((c = *cp) != '\0' && c != '/') { 583*e48f27a0SToomas Soome if (++len > UFS_MAXNAMLEN) { 5844a5d661aSToomas Soome rc = ENOENT; 5854a5d661aSToomas Soome goto out; 5864a5d661aSToomas Soome } 5874a5d661aSToomas Soome cp++; 5884a5d661aSToomas Soome } 5894a5d661aSToomas Soome *cp = '\0'; 5904a5d661aSToomas Soome } 5914a5d661aSToomas Soome 5924a5d661aSToomas Soome /* 5934a5d661aSToomas Soome * Look up component in current directory. 5944a5d661aSToomas Soome * Save directory inumber in case we find a 5954a5d661aSToomas Soome * symbolic link. 5964a5d661aSToomas Soome */ 5974a5d661aSToomas Soome parent_inumber = inumber; 5984a5d661aSToomas Soome rc = search_directory(ncp, f, &inumber); 5994a5d661aSToomas Soome *cp = c; 6004a5d661aSToomas Soome if (rc) 6014a5d661aSToomas Soome goto out; 6024a5d661aSToomas Soome 6034a5d661aSToomas Soome /* 6044a5d661aSToomas Soome * Open next component. 6054a5d661aSToomas Soome */ 6064a5d661aSToomas Soome if ((rc = read_inode(inumber, f)) != 0) 6074a5d661aSToomas Soome goto out; 6084a5d661aSToomas Soome 6094a5d661aSToomas Soome /* 6104a5d661aSToomas Soome * Check for symbolic link. 6114a5d661aSToomas Soome */ 6124a5d661aSToomas Soome if ((DIP(fp, di_mode) & IFMT) == IFLNK) { 6134a5d661aSToomas Soome int link_len = DIP(fp, di_size); 6144a5d661aSToomas Soome int len; 6154a5d661aSToomas Soome 6164a5d661aSToomas Soome len = strlen(cp); 6174a5d661aSToomas Soome 6184a5d661aSToomas Soome if (link_len + len > MAXPATHLEN || 6194a5d661aSToomas Soome ++nlinks > MAXSYMLINKS) { 6204a5d661aSToomas Soome rc = ENOENT; 6214a5d661aSToomas Soome goto out; 6224a5d661aSToomas Soome } 6234a5d661aSToomas Soome 6244a5d661aSToomas Soome bcopy(cp, &namebuf[link_len], len + 1); 6254a5d661aSToomas Soome 6264a5d661aSToomas Soome if (link_len < fs->fs_maxsymlinklen) { 6274a5d661aSToomas Soome if (fp->f_fs->fs_magic == FS_UFS1_MAGIC) 6284a5d661aSToomas Soome cp = (caddr_t)(fp->f_di.di1.di_db); 6294a5d661aSToomas Soome else 6304a5d661aSToomas Soome cp = (caddr_t)(fp->f_di.di2.di_db); 6314a5d661aSToomas Soome bcopy(cp, namebuf, (unsigned) link_len); 6324a5d661aSToomas Soome } else { 6334a5d661aSToomas Soome /* 6344a5d661aSToomas Soome * Read file for symbolic link 6354a5d661aSToomas Soome */ 6364a5d661aSToomas Soome size_t buf_size; 6374a5d661aSToomas Soome ufs2_daddr_t disk_block; 6384a5d661aSToomas Soome struct fs *fs = fp->f_fs; 6394a5d661aSToomas Soome 6404a5d661aSToomas Soome if (!buf) 6414a5d661aSToomas Soome buf = malloc(fs->fs_bsize); 6424a5d661aSToomas Soome rc = block_map(f, (ufs2_daddr_t)0, &disk_block); 6434a5d661aSToomas Soome if (rc) 6444a5d661aSToomas Soome goto out; 6454a5d661aSToomas Soome 6464a5d661aSToomas Soome twiddle(1); 6474a5d661aSToomas Soome rc = (f->f_dev->dv_strategy)(f->f_devdata, 648976852c7SToomas Soome F_READ, fsbtodb(fs, disk_block), 6494a5d661aSToomas Soome fs->fs_bsize, buf, &buf_size); 6504a5d661aSToomas Soome if (rc) 6514a5d661aSToomas Soome goto out; 6524a5d661aSToomas Soome 6534a5d661aSToomas Soome bcopy((char *)buf, namebuf, (unsigned)link_len); 6544a5d661aSToomas Soome } 6554a5d661aSToomas Soome 6564a5d661aSToomas Soome /* 6574a5d661aSToomas Soome * If relative pathname, restart at parent directory. 6584a5d661aSToomas Soome * If absolute pathname, restart at root. 6594a5d661aSToomas Soome */ 6604a5d661aSToomas Soome cp = namebuf; 6614a5d661aSToomas Soome if (*cp != '/') 6624a5d661aSToomas Soome inumber = parent_inumber; 6634a5d661aSToomas Soome else 6644a5d661aSToomas Soome inumber = (ino_t)ROOTINO; 6654a5d661aSToomas Soome 6664a5d661aSToomas Soome if ((rc = read_inode(inumber, f)) != 0) 6674a5d661aSToomas Soome goto out; 6684a5d661aSToomas Soome } 6694a5d661aSToomas Soome } 6704a5d661aSToomas Soome 6714a5d661aSToomas Soome /* 6724a5d661aSToomas Soome * Found terminal component. 6734a5d661aSToomas Soome */ 6744a5d661aSToomas Soome rc = 0; 6754a5d661aSToomas Soome fp->f_seekp = 0; 6764a5d661aSToomas Soome out: 6774a5d661aSToomas Soome if (buf) 6784a5d661aSToomas Soome free(buf); 6794a5d661aSToomas Soome if (path) 6804a5d661aSToomas Soome free(path); 6814a5d661aSToomas Soome if (rc) { 6824a5d661aSToomas Soome if (fp->f_buf) 6834a5d661aSToomas Soome free(fp->f_buf); 6844a5d661aSToomas Soome free(fp->f_fs); 6854a5d661aSToomas Soome free(fp); 6864a5d661aSToomas Soome } 6874a5d661aSToomas Soome return (rc); 6884a5d661aSToomas Soome } 6894a5d661aSToomas Soome 6904a5d661aSToomas Soome static int 6914a5d661aSToomas Soome ufs_close(f) 6924a5d661aSToomas Soome struct open_file *f; 6934a5d661aSToomas Soome { 6944a5d661aSToomas Soome struct file *fp = (struct file *)f->f_fsdata; 6954a5d661aSToomas Soome int level; 6964a5d661aSToomas Soome 6974a5d661aSToomas Soome f->f_fsdata = (void *)0; 6984a5d661aSToomas Soome if (fp == (struct file *)0) 6994a5d661aSToomas Soome return (0); 7004a5d661aSToomas Soome 7014a5d661aSToomas Soome for (level = 0; level < NIADDR; level++) { 7024a5d661aSToomas Soome if (fp->f_blk[level]) 7034a5d661aSToomas Soome free(fp->f_blk[level]); 7044a5d661aSToomas Soome } 7054a5d661aSToomas Soome if (fp->f_buf) 7064a5d661aSToomas Soome free(fp->f_buf); 7074a5d661aSToomas Soome free(fp->f_fs); 7084a5d661aSToomas Soome free(fp); 7094a5d661aSToomas Soome return (0); 7104a5d661aSToomas Soome } 7114a5d661aSToomas Soome 7124a5d661aSToomas Soome /* 7134a5d661aSToomas Soome * Copy a portion of a file into kernel memory. 7144a5d661aSToomas Soome * Cross block boundaries when necessary. 7154a5d661aSToomas Soome */ 7164a5d661aSToomas Soome static int 7174a5d661aSToomas Soome ufs_read(f, start, size, resid) 7184a5d661aSToomas Soome struct open_file *f; 7194a5d661aSToomas Soome void *start; 7204a5d661aSToomas Soome size_t size; 7214a5d661aSToomas Soome size_t *resid; /* out */ 7224a5d661aSToomas Soome { 7234a5d661aSToomas Soome struct file *fp = (struct file *)f->f_fsdata; 7244a5d661aSToomas Soome size_t csize; 7254a5d661aSToomas Soome char *buf; 7264a5d661aSToomas Soome size_t buf_size; 7274a5d661aSToomas Soome int rc = 0; 7284a5d661aSToomas Soome char *addr = start; 7294a5d661aSToomas Soome 7304a5d661aSToomas Soome while (size != 0) { 7314a5d661aSToomas Soome if (fp->f_seekp >= DIP(fp, di_size)) 7324a5d661aSToomas Soome break; 7334a5d661aSToomas Soome 7344a5d661aSToomas Soome rc = buf_read_file(f, &buf, &buf_size); 7354a5d661aSToomas Soome if (rc) 7364a5d661aSToomas Soome break; 7374a5d661aSToomas Soome 7384a5d661aSToomas Soome csize = size; 7394a5d661aSToomas Soome if (csize > buf_size) 7404a5d661aSToomas Soome csize = buf_size; 7414a5d661aSToomas Soome 7424a5d661aSToomas Soome bcopy(buf, addr, csize); 7434a5d661aSToomas Soome 7444a5d661aSToomas Soome fp->f_seekp += csize; 7454a5d661aSToomas Soome addr += csize; 7464a5d661aSToomas Soome size -= csize; 7474a5d661aSToomas Soome } 7484a5d661aSToomas Soome if (resid) 7494a5d661aSToomas Soome *resid = size; 7504a5d661aSToomas Soome return (rc); 7514a5d661aSToomas Soome } 7524a5d661aSToomas Soome 7534a5d661aSToomas Soome /* 7544a5d661aSToomas Soome * Write to a portion of an already allocated file. 7554a5d661aSToomas Soome * Cross block boundaries when necessary. Can not 7564a5d661aSToomas Soome * extend the file. 7574a5d661aSToomas Soome */ 7584a5d661aSToomas Soome static int 7594a5d661aSToomas Soome ufs_write(f, start, size, resid) 7604a5d661aSToomas Soome struct open_file *f; 7614a5d661aSToomas Soome void *start; 7624a5d661aSToomas Soome size_t size; 7634a5d661aSToomas Soome size_t *resid; /* out */ 7644a5d661aSToomas Soome { 7654a5d661aSToomas Soome struct file *fp = (struct file *)f->f_fsdata; 7664a5d661aSToomas Soome size_t csize; 7674a5d661aSToomas Soome int rc = 0; 7684a5d661aSToomas Soome char *addr = start; 7694a5d661aSToomas Soome 7704a5d661aSToomas Soome csize = size; 7714a5d661aSToomas Soome while ((size != 0) && (csize != 0)) { 7724a5d661aSToomas Soome if (fp->f_seekp >= DIP(fp, di_size)) 7734a5d661aSToomas Soome break; 7744a5d661aSToomas Soome 7754a5d661aSToomas Soome if (csize >= 512) csize = 512; /* XXX */ 7764a5d661aSToomas Soome 7774a5d661aSToomas Soome rc = buf_write_file(f, addr, &csize); 7784a5d661aSToomas Soome if (rc) 7794a5d661aSToomas Soome break; 7804a5d661aSToomas Soome 7814a5d661aSToomas Soome fp->f_seekp += csize; 7824a5d661aSToomas Soome addr += csize; 7834a5d661aSToomas Soome size -= csize; 7844a5d661aSToomas Soome } 7854a5d661aSToomas Soome if (resid) 7864a5d661aSToomas Soome *resid = size; 7874a5d661aSToomas Soome return (rc); 7884a5d661aSToomas Soome } 7894a5d661aSToomas Soome 7904a5d661aSToomas Soome static off_t 7914a5d661aSToomas Soome ufs_seek(f, offset, where) 7924a5d661aSToomas Soome struct open_file *f; 7934a5d661aSToomas Soome off_t offset; 7944a5d661aSToomas Soome int where; 7954a5d661aSToomas Soome { 7964a5d661aSToomas Soome struct file *fp = (struct file *)f->f_fsdata; 7974a5d661aSToomas Soome 7984a5d661aSToomas Soome switch (where) { 7994a5d661aSToomas Soome case SEEK_SET: 8004a5d661aSToomas Soome fp->f_seekp = offset; 8014a5d661aSToomas Soome break; 8024a5d661aSToomas Soome case SEEK_CUR: 8034a5d661aSToomas Soome fp->f_seekp += offset; 8044a5d661aSToomas Soome break; 8054a5d661aSToomas Soome case SEEK_END: 8064a5d661aSToomas Soome fp->f_seekp = DIP(fp, di_size) - offset; 8074a5d661aSToomas Soome break; 8084a5d661aSToomas Soome default: 8094a5d661aSToomas Soome errno = EINVAL; 8104a5d661aSToomas Soome return (-1); 8114a5d661aSToomas Soome } 8124a5d661aSToomas Soome return (fp->f_seekp); 8134a5d661aSToomas Soome } 8144a5d661aSToomas Soome 8154a5d661aSToomas Soome static int 8164a5d661aSToomas Soome ufs_stat(f, sb) 8174a5d661aSToomas Soome struct open_file *f; 8184a5d661aSToomas Soome struct stat *sb; 8194a5d661aSToomas Soome { 8204a5d661aSToomas Soome struct file *fp = (struct file *)f->f_fsdata; 8214a5d661aSToomas Soome 8224a5d661aSToomas Soome /* only important stuff */ 8234a5d661aSToomas Soome sb->st_mode = DIP(fp, di_mode); 8244a5d661aSToomas Soome sb->st_uid = DIP(fp, di_uid); 8254a5d661aSToomas Soome sb->st_gid = DIP(fp, di_gid); 8264a5d661aSToomas Soome sb->st_size = DIP(fp, di_size); 8274a5d661aSToomas Soome return (0); 8284a5d661aSToomas Soome } 8294a5d661aSToomas Soome 8304a5d661aSToomas Soome static int 8314a5d661aSToomas Soome ufs_readdir(struct open_file *f, struct dirent *d) 8324a5d661aSToomas Soome { 8334a5d661aSToomas Soome struct file *fp = (struct file *)f->f_fsdata; 8344a5d661aSToomas Soome struct direct *dp; 8354a5d661aSToomas Soome char *buf; 8364a5d661aSToomas Soome size_t buf_size; 8374a5d661aSToomas Soome int error; 8384a5d661aSToomas Soome 8394a5d661aSToomas Soome /* 8404a5d661aSToomas Soome * assume that a directory entry will not be split across blocks 8414a5d661aSToomas Soome */ 8424a5d661aSToomas Soome again: 8434a5d661aSToomas Soome if (fp->f_seekp >= DIP(fp, di_size)) 8444a5d661aSToomas Soome return (ENOENT); 8454a5d661aSToomas Soome error = buf_read_file(f, &buf, &buf_size); 8464a5d661aSToomas Soome if (error) 8474a5d661aSToomas Soome return (error); 8484a5d661aSToomas Soome dp = (struct direct *)buf; 8494a5d661aSToomas Soome fp->f_seekp += dp->d_reclen; 8504a5d661aSToomas Soome if (dp->d_ino == (ino_t)0) 8514a5d661aSToomas Soome goto again; 8524a5d661aSToomas Soome 8534a5d661aSToomas Soome d->d_type = 0; /* illumos ufs does not have type in direct */ 8544a5d661aSToomas Soome strcpy(d->d_name, dp->d_name); 8554a5d661aSToomas Soome return (0); 8564a5d661aSToomas Soome } 857