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
read_inode(inumber,f)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
block_map(f,file_block,disk_block_p)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
buf_write_file(f,buf_p,size_p)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
buf_read_file(f,buf_p,size_p)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
search_directory(name,f,inumber_p)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
ufs_open(upath,f)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
ufs_close(f)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
ufs_read(f,start,size,resid)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
ufs_write(f,start,size,resid)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
ufs_seek(f,offset,where)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
ufs_stat(f,sb)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
ufs_readdir(struct open_file * f,struct dirent * d)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