1*4a5d661aSToomas Soome /* $NetBSD: ufs.c,v 1.20 1998/03/01 07:15:39 ross Exp $ */ 2*4a5d661aSToomas Soome 3*4a5d661aSToomas Soome /*- 4*4a5d661aSToomas Soome * Copyright (c) 2002 Networks Associates Technology, Inc. 5*4a5d661aSToomas Soome * All rights reserved. 6*4a5d661aSToomas Soome * 7*4a5d661aSToomas Soome * This software was developed for the FreeBSD Project by Marshall 8*4a5d661aSToomas Soome * Kirk McKusick and Network Associates Laboratories, the Security 9*4a5d661aSToomas Soome * Research Division of Network Associates, Inc. under DARPA/SPAWAR 10*4a5d661aSToomas Soome * contract N66001-01-C-8035 ("CBOSS"), as part of the DARPA CHATS 11*4a5d661aSToomas Soome * research program 12*4a5d661aSToomas Soome * 13*4a5d661aSToomas Soome * Copyright (c) 1982, 1989, 1993 14*4a5d661aSToomas Soome * The Regents of the University of California. All rights reserved. 15*4a5d661aSToomas Soome * 16*4a5d661aSToomas Soome * This code is derived from software contributed to Berkeley by 17*4a5d661aSToomas Soome * The Mach Operating System project at Carnegie-Mellon University. 18*4a5d661aSToomas Soome * 19*4a5d661aSToomas Soome * Redistribution and use in source and binary forms, with or without 20*4a5d661aSToomas Soome * modification, are permitted provided that the following conditions 21*4a5d661aSToomas Soome * are met: 22*4a5d661aSToomas Soome * 1. Redistributions of source code must retain the above copyright 23*4a5d661aSToomas Soome * notice, this list of conditions and the following disclaimer. 24*4a5d661aSToomas Soome * 2. Redistributions in binary form must reproduce the above copyright 25*4a5d661aSToomas Soome * notice, this list of conditions and the following disclaimer in the 26*4a5d661aSToomas Soome * documentation and/or other materials provided with the distribution. 27*4a5d661aSToomas Soome * 3. Neither the name of the University nor the names of its contributors 28*4a5d661aSToomas Soome * may be used to endorse or promote products derived from this software 29*4a5d661aSToomas Soome * without specific prior written permission. 30*4a5d661aSToomas Soome * 31*4a5d661aSToomas Soome * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 32*4a5d661aSToomas Soome * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 33*4a5d661aSToomas Soome * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 34*4a5d661aSToomas Soome * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 35*4a5d661aSToomas Soome * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 36*4a5d661aSToomas Soome * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 37*4a5d661aSToomas Soome * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 38*4a5d661aSToomas Soome * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 39*4a5d661aSToomas Soome * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 40*4a5d661aSToomas Soome * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 41*4a5d661aSToomas Soome * SUCH DAMAGE. 42*4a5d661aSToomas Soome * 43*4a5d661aSToomas Soome * 44*4a5d661aSToomas Soome * Copyright (c) 1990, 1991 Carnegie Mellon University 45*4a5d661aSToomas Soome * All Rights Reserved. 46*4a5d661aSToomas Soome * 47*4a5d661aSToomas Soome * Author: David Golub 48*4a5d661aSToomas Soome * 49*4a5d661aSToomas Soome * Permission to use, copy, modify and distribute this software and its 50*4a5d661aSToomas Soome * documentation is hereby granted, provided that both the copyright 51*4a5d661aSToomas Soome * notice and this permission notice appear in all copies of the 52*4a5d661aSToomas Soome * software, derivative works or modified versions, and any portions 53*4a5d661aSToomas Soome * thereof, and that both notices appear in supporting documentation. 54*4a5d661aSToomas Soome * 55*4a5d661aSToomas Soome * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" 56*4a5d661aSToomas Soome * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR 57*4a5d661aSToomas Soome * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. 58*4a5d661aSToomas Soome * 59*4a5d661aSToomas Soome * Carnegie Mellon requests users of this software to return to 60*4a5d661aSToomas Soome * 61*4a5d661aSToomas Soome * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU 62*4a5d661aSToomas Soome * School of Computer Science 63*4a5d661aSToomas Soome * Carnegie Mellon University 64*4a5d661aSToomas Soome * Pittsburgh PA 15213-3890 65*4a5d661aSToomas Soome * 66*4a5d661aSToomas Soome * any improvements or extensions that they make and grant Carnegie the 67*4a5d661aSToomas Soome * rights to redistribute these changes. 68*4a5d661aSToomas Soome */ 69*4a5d661aSToomas Soome 70*4a5d661aSToomas Soome #include <sys/cdefs.h> 71*4a5d661aSToomas Soome __FBSDID("$FreeBSD$"); 72*4a5d661aSToomas Soome 73*4a5d661aSToomas Soome /* 74*4a5d661aSToomas Soome * Stand-alone file reading package. 75*4a5d661aSToomas Soome */ 76*4a5d661aSToomas Soome 77*4a5d661aSToomas Soome #include <sys/param.h> 78*4a5d661aSToomas Soome #include <sys/disklabel.h> 79*4a5d661aSToomas Soome #include <sys/time.h> 80*4a5d661aSToomas Soome #include <ufs/ufs/dinode.h> 81*4a5d661aSToomas Soome #include <ufs/ufs/dir.h> 82*4a5d661aSToomas Soome #include <ufs/ffs/fs.h> 83*4a5d661aSToomas Soome #include "stand.h" 84*4a5d661aSToomas Soome #include "string.h" 85*4a5d661aSToomas Soome 86*4a5d661aSToomas Soome static int ufs_open(const char *path, struct open_file *f); 87*4a5d661aSToomas Soome static int ufs_write(struct open_file *f, void *buf, size_t size, size_t *resid); 88*4a5d661aSToomas Soome static int ufs_close(struct open_file *f); 89*4a5d661aSToomas Soome static int ufs_read(struct open_file *f, void *buf, size_t size, size_t *resid); 90*4a5d661aSToomas Soome static off_t ufs_seek(struct open_file *f, off_t offset, int where); 91*4a5d661aSToomas Soome static int ufs_stat(struct open_file *f, struct stat *sb); 92*4a5d661aSToomas Soome static int ufs_readdir(struct open_file *f, struct dirent *d); 93*4a5d661aSToomas Soome 94*4a5d661aSToomas Soome struct fs_ops ufs_fsops = { 95*4a5d661aSToomas Soome "ufs", 96*4a5d661aSToomas Soome ufs_open, 97*4a5d661aSToomas Soome ufs_close, 98*4a5d661aSToomas Soome ufs_read, 99*4a5d661aSToomas Soome ufs_write, 100*4a5d661aSToomas Soome ufs_seek, 101*4a5d661aSToomas Soome ufs_stat, 102*4a5d661aSToomas Soome ufs_readdir 103*4a5d661aSToomas Soome }; 104*4a5d661aSToomas Soome 105*4a5d661aSToomas Soome /* 106*4a5d661aSToomas Soome * In-core open file. 107*4a5d661aSToomas Soome */ 108*4a5d661aSToomas Soome struct file { 109*4a5d661aSToomas Soome off_t f_seekp; /* seek pointer */ 110*4a5d661aSToomas Soome struct fs *f_fs; /* pointer to super-block */ 111*4a5d661aSToomas Soome union dinode { 112*4a5d661aSToomas Soome struct ufs1_dinode di1; 113*4a5d661aSToomas Soome struct ufs2_dinode di2; 114*4a5d661aSToomas Soome } f_di; /* copy of on-disk inode */ 115*4a5d661aSToomas Soome int f_nindir[NIADDR]; 116*4a5d661aSToomas Soome /* number of blocks mapped by 117*4a5d661aSToomas Soome indirect block at level i */ 118*4a5d661aSToomas Soome char *f_blk[NIADDR]; /* buffer for indirect block at 119*4a5d661aSToomas Soome level i */ 120*4a5d661aSToomas Soome size_t f_blksize[NIADDR]; 121*4a5d661aSToomas Soome /* size of buffer */ 122*4a5d661aSToomas Soome ufs2_daddr_t f_blkno[NIADDR];/* disk address of block in buffer */ 123*4a5d661aSToomas Soome ufs2_daddr_t f_buf_blkno; /* block number of data block */ 124*4a5d661aSToomas Soome char *f_buf; /* buffer for data block */ 125*4a5d661aSToomas Soome size_t f_buf_size; /* size of data block */ 126*4a5d661aSToomas Soome }; 127*4a5d661aSToomas Soome #define DIP(fp, field) \ 128*4a5d661aSToomas Soome ((fp)->f_fs->fs_magic == FS_UFS1_MAGIC ? \ 129*4a5d661aSToomas Soome (fp)->f_di.di1.field : (fp)->f_di.di2.field) 130*4a5d661aSToomas Soome 131*4a5d661aSToomas Soome static int read_inode(ino_t, struct open_file *); 132*4a5d661aSToomas Soome static int block_map(struct open_file *, ufs2_daddr_t, ufs2_daddr_t *); 133*4a5d661aSToomas Soome static int buf_read_file(struct open_file *, char **, size_t *); 134*4a5d661aSToomas Soome static int buf_write_file(struct open_file *, char *, size_t *); 135*4a5d661aSToomas Soome static int search_directory(char *, struct open_file *, ino_t *); 136*4a5d661aSToomas Soome 137*4a5d661aSToomas Soome /* 138*4a5d661aSToomas Soome * Read a new inode into a file structure. 139*4a5d661aSToomas Soome */ 140*4a5d661aSToomas Soome static int 141*4a5d661aSToomas Soome read_inode(inumber, f) 142*4a5d661aSToomas Soome ino_t inumber; 143*4a5d661aSToomas Soome struct open_file *f; 144*4a5d661aSToomas Soome { 145*4a5d661aSToomas Soome struct file *fp = (struct file *)f->f_fsdata; 146*4a5d661aSToomas Soome struct fs *fs = fp->f_fs; 147*4a5d661aSToomas Soome char *buf; 148*4a5d661aSToomas Soome size_t rsize; 149*4a5d661aSToomas Soome int rc; 150*4a5d661aSToomas Soome 151*4a5d661aSToomas Soome if (fs == NULL) 152*4a5d661aSToomas Soome panic("fs == NULL"); 153*4a5d661aSToomas Soome 154*4a5d661aSToomas Soome /* 155*4a5d661aSToomas Soome * Read inode and save it. 156*4a5d661aSToomas Soome */ 157*4a5d661aSToomas Soome buf = malloc(fs->fs_bsize); 158*4a5d661aSToomas Soome twiddle(1); 159*4a5d661aSToomas Soome rc = (f->f_dev->dv_strategy)(f->f_devdata, F_READ, 160*4a5d661aSToomas Soome fsbtodb(fs, ino_to_fsba(fs, inumber)), 0, fs->fs_bsize, 161*4a5d661aSToomas Soome buf, &rsize); 162*4a5d661aSToomas Soome if (rc) 163*4a5d661aSToomas Soome goto out; 164*4a5d661aSToomas Soome if (rsize != fs->fs_bsize) { 165*4a5d661aSToomas Soome rc = EIO; 166*4a5d661aSToomas Soome goto out; 167*4a5d661aSToomas Soome } 168*4a5d661aSToomas Soome 169*4a5d661aSToomas Soome if (fp->f_fs->fs_magic == FS_UFS1_MAGIC) 170*4a5d661aSToomas Soome fp->f_di.di1 = ((struct ufs1_dinode *)buf) 171*4a5d661aSToomas Soome [ino_to_fsbo(fs, inumber)]; 172*4a5d661aSToomas Soome else 173*4a5d661aSToomas Soome fp->f_di.di2 = ((struct ufs2_dinode *)buf) 174*4a5d661aSToomas Soome [ino_to_fsbo(fs, inumber)]; 175*4a5d661aSToomas Soome 176*4a5d661aSToomas Soome /* 177*4a5d661aSToomas Soome * Clear out the old buffers 178*4a5d661aSToomas Soome */ 179*4a5d661aSToomas Soome { 180*4a5d661aSToomas Soome int level; 181*4a5d661aSToomas Soome 182*4a5d661aSToomas Soome for (level = 0; level < NIADDR; level++) 183*4a5d661aSToomas Soome fp->f_blkno[level] = -1; 184*4a5d661aSToomas Soome fp->f_buf_blkno = -1; 185*4a5d661aSToomas Soome } 186*4a5d661aSToomas Soome fp->f_seekp = 0; 187*4a5d661aSToomas Soome out: 188*4a5d661aSToomas Soome free(buf); 189*4a5d661aSToomas Soome return (rc); 190*4a5d661aSToomas Soome } 191*4a5d661aSToomas Soome 192*4a5d661aSToomas Soome /* 193*4a5d661aSToomas Soome * Given an offset in a file, find the disk block number that 194*4a5d661aSToomas Soome * contains that block. 195*4a5d661aSToomas Soome */ 196*4a5d661aSToomas Soome static int 197*4a5d661aSToomas Soome block_map(f, file_block, disk_block_p) 198*4a5d661aSToomas Soome struct open_file *f; 199*4a5d661aSToomas Soome ufs2_daddr_t file_block; 200*4a5d661aSToomas Soome ufs2_daddr_t *disk_block_p; /* out */ 201*4a5d661aSToomas Soome { 202*4a5d661aSToomas Soome struct file *fp = (struct file *)f->f_fsdata; 203*4a5d661aSToomas Soome struct fs *fs = fp->f_fs; 204*4a5d661aSToomas Soome int level; 205*4a5d661aSToomas Soome int idx; 206*4a5d661aSToomas Soome ufs2_daddr_t ind_block_num; 207*4a5d661aSToomas Soome int rc; 208*4a5d661aSToomas Soome 209*4a5d661aSToomas Soome /* 210*4a5d661aSToomas Soome * Index structure of an inode: 211*4a5d661aSToomas Soome * 212*4a5d661aSToomas Soome * di_db[0..NDADDR-1] hold block numbers for blocks 213*4a5d661aSToomas Soome * 0..NDADDR-1 214*4a5d661aSToomas Soome * 215*4a5d661aSToomas Soome * di_ib[0] index block 0 is the single indirect block 216*4a5d661aSToomas Soome * holds block numbers for blocks 217*4a5d661aSToomas Soome * NDADDR .. NDADDR + NINDIR(fs)-1 218*4a5d661aSToomas Soome * 219*4a5d661aSToomas Soome * di_ib[1] index block 1 is the double indirect block 220*4a5d661aSToomas Soome * holds block numbers for INDEX blocks for blocks 221*4a5d661aSToomas Soome * NDADDR + NINDIR(fs) .. 222*4a5d661aSToomas Soome * NDADDR + NINDIR(fs) + NINDIR(fs)**2 - 1 223*4a5d661aSToomas Soome * 224*4a5d661aSToomas Soome * di_ib[2] index block 2 is the triple indirect block 225*4a5d661aSToomas Soome * holds block numbers for double-indirect 226*4a5d661aSToomas Soome * blocks for blocks 227*4a5d661aSToomas Soome * NDADDR + NINDIR(fs) + NINDIR(fs)**2 .. 228*4a5d661aSToomas Soome * NDADDR + NINDIR(fs) + NINDIR(fs)**2 229*4a5d661aSToomas Soome * + NINDIR(fs)**3 - 1 230*4a5d661aSToomas Soome */ 231*4a5d661aSToomas Soome 232*4a5d661aSToomas Soome if (file_block < NDADDR) { 233*4a5d661aSToomas Soome /* Direct block. */ 234*4a5d661aSToomas Soome *disk_block_p = DIP(fp, di_db[file_block]); 235*4a5d661aSToomas Soome return (0); 236*4a5d661aSToomas Soome } 237*4a5d661aSToomas Soome 238*4a5d661aSToomas Soome file_block -= NDADDR; 239*4a5d661aSToomas Soome 240*4a5d661aSToomas Soome /* 241*4a5d661aSToomas Soome * nindir[0] = NINDIR 242*4a5d661aSToomas Soome * nindir[1] = NINDIR**2 243*4a5d661aSToomas Soome * nindir[2] = NINDIR**3 244*4a5d661aSToomas Soome * etc 245*4a5d661aSToomas Soome */ 246*4a5d661aSToomas Soome for (level = 0; level < NIADDR; level++) { 247*4a5d661aSToomas Soome if (file_block < fp->f_nindir[level]) 248*4a5d661aSToomas Soome break; 249*4a5d661aSToomas Soome file_block -= fp->f_nindir[level]; 250*4a5d661aSToomas Soome } 251*4a5d661aSToomas Soome if (level == NIADDR) { 252*4a5d661aSToomas Soome /* Block number too high */ 253*4a5d661aSToomas Soome return (EFBIG); 254*4a5d661aSToomas Soome } 255*4a5d661aSToomas Soome 256*4a5d661aSToomas Soome ind_block_num = DIP(fp, di_ib[level]); 257*4a5d661aSToomas Soome 258*4a5d661aSToomas Soome for (; level >= 0; level--) { 259*4a5d661aSToomas Soome if (ind_block_num == 0) { 260*4a5d661aSToomas Soome *disk_block_p = 0; /* missing */ 261*4a5d661aSToomas Soome return (0); 262*4a5d661aSToomas Soome } 263*4a5d661aSToomas Soome 264*4a5d661aSToomas Soome if (fp->f_blkno[level] != ind_block_num) { 265*4a5d661aSToomas Soome if (fp->f_blk[level] == (char *)0) 266*4a5d661aSToomas Soome fp->f_blk[level] = 267*4a5d661aSToomas Soome malloc(fs->fs_bsize); 268*4a5d661aSToomas Soome twiddle(1); 269*4a5d661aSToomas Soome rc = (f->f_dev->dv_strategy)(f->f_devdata, F_READ, 270*4a5d661aSToomas Soome fsbtodb(fp->f_fs, ind_block_num), 0, 271*4a5d661aSToomas Soome fs->fs_bsize, 272*4a5d661aSToomas Soome fp->f_blk[level], 273*4a5d661aSToomas Soome &fp->f_blksize[level]); 274*4a5d661aSToomas Soome if (rc) 275*4a5d661aSToomas Soome return (rc); 276*4a5d661aSToomas Soome if (fp->f_blksize[level] != fs->fs_bsize) 277*4a5d661aSToomas Soome return (EIO); 278*4a5d661aSToomas Soome fp->f_blkno[level] = ind_block_num; 279*4a5d661aSToomas Soome } 280*4a5d661aSToomas Soome 281*4a5d661aSToomas Soome if (level > 0) { 282*4a5d661aSToomas Soome idx = file_block / fp->f_nindir[level - 1]; 283*4a5d661aSToomas Soome file_block %= fp->f_nindir[level - 1]; 284*4a5d661aSToomas Soome } else 285*4a5d661aSToomas Soome idx = file_block; 286*4a5d661aSToomas Soome 287*4a5d661aSToomas Soome if (fp->f_fs->fs_magic == FS_UFS1_MAGIC) 288*4a5d661aSToomas Soome ind_block_num = ((ufs1_daddr_t *)fp->f_blk[level])[idx]; 289*4a5d661aSToomas Soome else 290*4a5d661aSToomas Soome ind_block_num = ((ufs2_daddr_t *)fp->f_blk[level])[idx]; 291*4a5d661aSToomas Soome } 292*4a5d661aSToomas Soome 293*4a5d661aSToomas Soome *disk_block_p = ind_block_num; 294*4a5d661aSToomas Soome 295*4a5d661aSToomas Soome return (0); 296*4a5d661aSToomas Soome } 297*4a5d661aSToomas Soome 298*4a5d661aSToomas Soome /* 299*4a5d661aSToomas Soome * Write a portion of a file from an internal buffer. 300*4a5d661aSToomas Soome */ 301*4a5d661aSToomas Soome static int 302*4a5d661aSToomas Soome buf_write_file(f, buf_p, size_p) 303*4a5d661aSToomas Soome struct open_file *f; 304*4a5d661aSToomas Soome char *buf_p; 305*4a5d661aSToomas Soome size_t *size_p; /* out */ 306*4a5d661aSToomas Soome { 307*4a5d661aSToomas Soome struct file *fp = (struct file *)f->f_fsdata; 308*4a5d661aSToomas Soome struct fs *fs = fp->f_fs; 309*4a5d661aSToomas Soome long off; 310*4a5d661aSToomas Soome ufs_lbn_t file_block; 311*4a5d661aSToomas Soome ufs2_daddr_t disk_block; 312*4a5d661aSToomas Soome size_t block_size; 313*4a5d661aSToomas Soome int rc; 314*4a5d661aSToomas Soome 315*4a5d661aSToomas Soome /* 316*4a5d661aSToomas Soome * Calculate the starting block address and offset. 317*4a5d661aSToomas Soome */ 318*4a5d661aSToomas Soome off = blkoff(fs, fp->f_seekp); 319*4a5d661aSToomas Soome file_block = lblkno(fs, fp->f_seekp); 320*4a5d661aSToomas Soome block_size = sblksize(fs, DIP(fp, di_size), file_block); 321*4a5d661aSToomas Soome 322*4a5d661aSToomas Soome rc = block_map(f, file_block, &disk_block); 323*4a5d661aSToomas Soome if (rc) 324*4a5d661aSToomas Soome return (rc); 325*4a5d661aSToomas Soome 326*4a5d661aSToomas Soome if (disk_block == 0) 327*4a5d661aSToomas Soome /* Because we can't allocate space on the drive */ 328*4a5d661aSToomas Soome return (EFBIG); 329*4a5d661aSToomas Soome 330*4a5d661aSToomas Soome /* 331*4a5d661aSToomas Soome * Truncate buffer at end of file, and at the end of 332*4a5d661aSToomas Soome * this block. 333*4a5d661aSToomas Soome */ 334*4a5d661aSToomas Soome if (*size_p > DIP(fp, di_size) - fp->f_seekp) 335*4a5d661aSToomas Soome *size_p = DIP(fp, di_size) - fp->f_seekp; 336*4a5d661aSToomas Soome if (*size_p > block_size - off) 337*4a5d661aSToomas Soome *size_p = block_size - off; 338*4a5d661aSToomas Soome 339*4a5d661aSToomas Soome /* 340*4a5d661aSToomas Soome * If we don't entirely occlude the block and it's not 341*4a5d661aSToomas Soome * in memory already, read it in first. 342*4a5d661aSToomas Soome */ 343*4a5d661aSToomas Soome if (((off > 0) || (*size_p + off < block_size)) && 344*4a5d661aSToomas Soome (file_block != fp->f_buf_blkno)) { 345*4a5d661aSToomas Soome 346*4a5d661aSToomas Soome if (fp->f_buf == (char *)0) 347*4a5d661aSToomas Soome fp->f_buf = malloc(fs->fs_bsize); 348*4a5d661aSToomas Soome 349*4a5d661aSToomas Soome twiddle(8); 350*4a5d661aSToomas Soome rc = (f->f_dev->dv_strategy)(f->f_devdata, F_READ, 351*4a5d661aSToomas Soome fsbtodb(fs, disk_block), 0, 352*4a5d661aSToomas Soome block_size, fp->f_buf, &fp->f_buf_size); 353*4a5d661aSToomas Soome if (rc) 354*4a5d661aSToomas Soome return (rc); 355*4a5d661aSToomas Soome 356*4a5d661aSToomas Soome fp->f_buf_blkno = file_block; 357*4a5d661aSToomas Soome } 358*4a5d661aSToomas Soome 359*4a5d661aSToomas Soome /* 360*4a5d661aSToomas Soome * Copy the user data into the cached block. 361*4a5d661aSToomas Soome */ 362*4a5d661aSToomas Soome bcopy(buf_p, fp->f_buf + off, *size_p); 363*4a5d661aSToomas Soome 364*4a5d661aSToomas Soome /* 365*4a5d661aSToomas Soome * Write the block out to storage. 366*4a5d661aSToomas Soome */ 367*4a5d661aSToomas Soome 368*4a5d661aSToomas Soome twiddle(4); 369*4a5d661aSToomas Soome rc = (f->f_dev->dv_strategy)(f->f_devdata, F_WRITE, 370*4a5d661aSToomas Soome fsbtodb(fs, disk_block), 0, 371*4a5d661aSToomas Soome block_size, fp->f_buf, &fp->f_buf_size); 372*4a5d661aSToomas Soome return (rc); 373*4a5d661aSToomas Soome } 374*4a5d661aSToomas Soome 375*4a5d661aSToomas Soome /* 376*4a5d661aSToomas Soome * Read a portion of a file into an internal buffer. Return 377*4a5d661aSToomas Soome * the location in the buffer and the amount in the buffer. 378*4a5d661aSToomas Soome */ 379*4a5d661aSToomas Soome static int 380*4a5d661aSToomas Soome buf_read_file(f, buf_p, size_p) 381*4a5d661aSToomas Soome struct open_file *f; 382*4a5d661aSToomas Soome char **buf_p; /* out */ 383*4a5d661aSToomas Soome size_t *size_p; /* out */ 384*4a5d661aSToomas Soome { 385*4a5d661aSToomas Soome struct file *fp = (struct file *)f->f_fsdata; 386*4a5d661aSToomas Soome struct fs *fs = fp->f_fs; 387*4a5d661aSToomas Soome long off; 388*4a5d661aSToomas Soome ufs_lbn_t file_block; 389*4a5d661aSToomas Soome ufs2_daddr_t disk_block; 390*4a5d661aSToomas Soome size_t block_size; 391*4a5d661aSToomas Soome int rc; 392*4a5d661aSToomas Soome 393*4a5d661aSToomas Soome off = blkoff(fs, fp->f_seekp); 394*4a5d661aSToomas Soome file_block = lblkno(fs, fp->f_seekp); 395*4a5d661aSToomas Soome block_size = sblksize(fs, DIP(fp, di_size), file_block); 396*4a5d661aSToomas Soome 397*4a5d661aSToomas Soome if (file_block != fp->f_buf_blkno) { 398*4a5d661aSToomas Soome if (fp->f_buf == (char *)0) 399*4a5d661aSToomas Soome fp->f_buf = malloc(fs->fs_bsize); 400*4a5d661aSToomas Soome 401*4a5d661aSToomas Soome rc = block_map(f, file_block, &disk_block); 402*4a5d661aSToomas Soome if (rc) 403*4a5d661aSToomas Soome return (rc); 404*4a5d661aSToomas Soome 405*4a5d661aSToomas Soome if (disk_block == 0) { 406*4a5d661aSToomas Soome bzero(fp->f_buf, block_size); 407*4a5d661aSToomas Soome fp->f_buf_size = block_size; 408*4a5d661aSToomas Soome } else { 409*4a5d661aSToomas Soome twiddle(4); 410*4a5d661aSToomas Soome rc = (f->f_dev->dv_strategy)(f->f_devdata, 411*4a5d661aSToomas Soome F_READ, fsbtodb(fs, disk_block), 0, 412*4a5d661aSToomas Soome block_size, fp->f_buf, &fp->f_buf_size); 413*4a5d661aSToomas Soome if (rc) 414*4a5d661aSToomas Soome return (rc); 415*4a5d661aSToomas Soome } 416*4a5d661aSToomas Soome 417*4a5d661aSToomas Soome fp->f_buf_blkno = file_block; 418*4a5d661aSToomas Soome } 419*4a5d661aSToomas Soome 420*4a5d661aSToomas Soome /* 421*4a5d661aSToomas Soome * Return address of byte in buffer corresponding to 422*4a5d661aSToomas Soome * offset, and size of remainder of buffer after that 423*4a5d661aSToomas Soome * byte. 424*4a5d661aSToomas Soome */ 425*4a5d661aSToomas Soome *buf_p = fp->f_buf + off; 426*4a5d661aSToomas Soome *size_p = block_size - off; 427*4a5d661aSToomas Soome 428*4a5d661aSToomas Soome /* 429*4a5d661aSToomas Soome * But truncate buffer at end of file. 430*4a5d661aSToomas Soome */ 431*4a5d661aSToomas Soome if (*size_p > DIP(fp, di_size) - fp->f_seekp) 432*4a5d661aSToomas Soome *size_p = DIP(fp, di_size) - fp->f_seekp; 433*4a5d661aSToomas Soome 434*4a5d661aSToomas Soome return (0); 435*4a5d661aSToomas Soome } 436*4a5d661aSToomas Soome 437*4a5d661aSToomas Soome /* 438*4a5d661aSToomas Soome * Search a directory for a name and return its 439*4a5d661aSToomas Soome * i_number. 440*4a5d661aSToomas Soome */ 441*4a5d661aSToomas Soome static int 442*4a5d661aSToomas Soome search_directory(name, f, inumber_p) 443*4a5d661aSToomas Soome char *name; 444*4a5d661aSToomas Soome struct open_file *f; 445*4a5d661aSToomas Soome ino_t *inumber_p; /* out */ 446*4a5d661aSToomas Soome { 447*4a5d661aSToomas Soome struct file *fp = (struct file *)f->f_fsdata; 448*4a5d661aSToomas Soome struct direct *dp; 449*4a5d661aSToomas Soome struct direct *edp; 450*4a5d661aSToomas Soome char *buf; 451*4a5d661aSToomas Soome size_t buf_size; 452*4a5d661aSToomas Soome int namlen, length; 453*4a5d661aSToomas Soome int rc; 454*4a5d661aSToomas Soome 455*4a5d661aSToomas Soome length = strlen(name); 456*4a5d661aSToomas Soome 457*4a5d661aSToomas Soome fp->f_seekp = 0; 458*4a5d661aSToomas Soome while (fp->f_seekp < DIP(fp, di_size)) { 459*4a5d661aSToomas Soome rc = buf_read_file(f, &buf, &buf_size); 460*4a5d661aSToomas Soome if (rc) 461*4a5d661aSToomas Soome return (rc); 462*4a5d661aSToomas Soome 463*4a5d661aSToomas Soome dp = (struct direct *)buf; 464*4a5d661aSToomas Soome edp = (struct direct *)(buf + buf_size); 465*4a5d661aSToomas Soome while (dp < edp) { 466*4a5d661aSToomas Soome if (dp->d_ino == (ino_t)0) 467*4a5d661aSToomas Soome goto next; 468*4a5d661aSToomas Soome namlen = dp->d_namlen; 469*4a5d661aSToomas Soome if (namlen == length && 470*4a5d661aSToomas Soome !strcmp(name, dp->d_name)) { 471*4a5d661aSToomas Soome /* found entry */ 472*4a5d661aSToomas Soome *inumber_p = dp->d_ino; 473*4a5d661aSToomas Soome return (0); 474*4a5d661aSToomas Soome } 475*4a5d661aSToomas Soome next: 476*4a5d661aSToomas Soome dp = (struct direct *)((char *)dp + dp->d_reclen); 477*4a5d661aSToomas Soome } 478*4a5d661aSToomas Soome fp->f_seekp += buf_size; 479*4a5d661aSToomas Soome } 480*4a5d661aSToomas Soome return (ENOENT); 481*4a5d661aSToomas Soome } 482*4a5d661aSToomas Soome 483*4a5d661aSToomas Soome static int sblock_try[] = SBLOCKSEARCH; 484*4a5d661aSToomas Soome 485*4a5d661aSToomas Soome /* 486*4a5d661aSToomas Soome * Open a file. 487*4a5d661aSToomas Soome */ 488*4a5d661aSToomas Soome static int 489*4a5d661aSToomas Soome ufs_open(upath, f) 490*4a5d661aSToomas Soome const char *upath; 491*4a5d661aSToomas Soome struct open_file *f; 492*4a5d661aSToomas Soome { 493*4a5d661aSToomas Soome char *cp, *ncp; 494*4a5d661aSToomas Soome int c; 495*4a5d661aSToomas Soome ino_t inumber, parent_inumber; 496*4a5d661aSToomas Soome struct file *fp; 497*4a5d661aSToomas Soome struct fs *fs; 498*4a5d661aSToomas Soome int i, rc; 499*4a5d661aSToomas Soome size_t buf_size; 500*4a5d661aSToomas Soome int nlinks = 0; 501*4a5d661aSToomas Soome char namebuf[MAXPATHLEN+1]; 502*4a5d661aSToomas Soome char *buf = NULL; 503*4a5d661aSToomas Soome char *path = NULL; 504*4a5d661aSToomas Soome 505*4a5d661aSToomas Soome /* allocate file system specific data structure */ 506*4a5d661aSToomas Soome fp = malloc(sizeof(struct file)); 507*4a5d661aSToomas Soome bzero(fp, sizeof(struct file)); 508*4a5d661aSToomas Soome f->f_fsdata = (void *)fp; 509*4a5d661aSToomas Soome 510*4a5d661aSToomas Soome /* allocate space and read super block */ 511*4a5d661aSToomas Soome fs = malloc(SBLOCKSIZE); 512*4a5d661aSToomas Soome fp->f_fs = fs; 513*4a5d661aSToomas Soome twiddle(1); 514*4a5d661aSToomas Soome /* 515*4a5d661aSToomas Soome * Try reading the superblock in each of its possible locations. 516*4a5d661aSToomas Soome */ 517*4a5d661aSToomas Soome for (i = 0; sblock_try[i] != -1; i++) { 518*4a5d661aSToomas Soome rc = (f->f_dev->dv_strategy)(f->f_devdata, F_READ, 519*4a5d661aSToomas Soome sblock_try[i] / DEV_BSIZE, 0, SBLOCKSIZE, 520*4a5d661aSToomas Soome (char *)fs, &buf_size); 521*4a5d661aSToomas Soome if (rc) 522*4a5d661aSToomas Soome goto out; 523*4a5d661aSToomas Soome if ((fs->fs_magic == FS_UFS1_MAGIC || 524*4a5d661aSToomas Soome (fs->fs_magic == FS_UFS2_MAGIC && 525*4a5d661aSToomas Soome fs->fs_sblockloc == sblock_try[i])) && 526*4a5d661aSToomas Soome buf_size == SBLOCKSIZE && 527*4a5d661aSToomas Soome fs->fs_bsize <= MAXBSIZE && 528*4a5d661aSToomas Soome fs->fs_bsize >= sizeof(struct fs)) 529*4a5d661aSToomas Soome break; 530*4a5d661aSToomas Soome } 531*4a5d661aSToomas Soome if (sblock_try[i] == -1) { 532*4a5d661aSToomas Soome rc = EINVAL; 533*4a5d661aSToomas Soome goto out; 534*4a5d661aSToomas Soome } 535*4a5d661aSToomas Soome /* 536*4a5d661aSToomas Soome * Calculate indirect block levels. 537*4a5d661aSToomas Soome */ 538*4a5d661aSToomas Soome { 539*4a5d661aSToomas Soome ufs2_daddr_t mult; 540*4a5d661aSToomas Soome int level; 541*4a5d661aSToomas Soome 542*4a5d661aSToomas Soome mult = 1; 543*4a5d661aSToomas Soome for (level = 0; level < NIADDR; level++) { 544*4a5d661aSToomas Soome mult *= NINDIR(fs); 545*4a5d661aSToomas Soome fp->f_nindir[level] = mult; 546*4a5d661aSToomas Soome } 547*4a5d661aSToomas Soome } 548*4a5d661aSToomas Soome 549*4a5d661aSToomas Soome inumber = ROOTINO; 550*4a5d661aSToomas Soome if ((rc = read_inode(inumber, f)) != 0) 551*4a5d661aSToomas Soome goto out; 552*4a5d661aSToomas Soome 553*4a5d661aSToomas Soome cp = path = strdup(upath); 554*4a5d661aSToomas Soome if (path == NULL) { 555*4a5d661aSToomas Soome rc = ENOMEM; 556*4a5d661aSToomas Soome goto out; 557*4a5d661aSToomas Soome } 558*4a5d661aSToomas Soome while (*cp) { 559*4a5d661aSToomas Soome 560*4a5d661aSToomas Soome /* 561*4a5d661aSToomas Soome * Remove extra separators 562*4a5d661aSToomas Soome */ 563*4a5d661aSToomas Soome while (*cp == '/') 564*4a5d661aSToomas Soome cp++; 565*4a5d661aSToomas Soome if (*cp == '\0') 566*4a5d661aSToomas Soome break; 567*4a5d661aSToomas Soome 568*4a5d661aSToomas Soome /* 569*4a5d661aSToomas Soome * Check that current node is a directory. 570*4a5d661aSToomas Soome */ 571*4a5d661aSToomas Soome if ((DIP(fp, di_mode) & IFMT) != IFDIR) { 572*4a5d661aSToomas Soome rc = ENOTDIR; 573*4a5d661aSToomas Soome goto out; 574*4a5d661aSToomas Soome } 575*4a5d661aSToomas Soome 576*4a5d661aSToomas Soome /* 577*4a5d661aSToomas Soome * Get next component of path name. 578*4a5d661aSToomas Soome */ 579*4a5d661aSToomas Soome { 580*4a5d661aSToomas Soome int len = 0; 581*4a5d661aSToomas Soome 582*4a5d661aSToomas Soome ncp = cp; 583*4a5d661aSToomas Soome while ((c = *cp) != '\0' && c != '/') { 584*4a5d661aSToomas Soome if (++len > MAXNAMLEN) { 585*4a5d661aSToomas Soome rc = ENOENT; 586*4a5d661aSToomas Soome goto out; 587*4a5d661aSToomas Soome } 588*4a5d661aSToomas Soome cp++; 589*4a5d661aSToomas Soome } 590*4a5d661aSToomas Soome *cp = '\0'; 591*4a5d661aSToomas Soome } 592*4a5d661aSToomas Soome 593*4a5d661aSToomas Soome /* 594*4a5d661aSToomas Soome * Look up component in current directory. 595*4a5d661aSToomas Soome * Save directory inumber in case we find a 596*4a5d661aSToomas Soome * symbolic link. 597*4a5d661aSToomas Soome */ 598*4a5d661aSToomas Soome parent_inumber = inumber; 599*4a5d661aSToomas Soome rc = search_directory(ncp, f, &inumber); 600*4a5d661aSToomas Soome *cp = c; 601*4a5d661aSToomas Soome if (rc) 602*4a5d661aSToomas Soome goto out; 603*4a5d661aSToomas Soome 604*4a5d661aSToomas Soome /* 605*4a5d661aSToomas Soome * Open next component. 606*4a5d661aSToomas Soome */ 607*4a5d661aSToomas Soome if ((rc = read_inode(inumber, f)) != 0) 608*4a5d661aSToomas Soome goto out; 609*4a5d661aSToomas Soome 610*4a5d661aSToomas Soome /* 611*4a5d661aSToomas Soome * Check for symbolic link. 612*4a5d661aSToomas Soome */ 613*4a5d661aSToomas Soome if ((DIP(fp, di_mode) & IFMT) == IFLNK) { 614*4a5d661aSToomas Soome int link_len = DIP(fp, di_size); 615*4a5d661aSToomas Soome int len; 616*4a5d661aSToomas Soome 617*4a5d661aSToomas Soome len = strlen(cp); 618*4a5d661aSToomas Soome 619*4a5d661aSToomas Soome if (link_len + len > MAXPATHLEN || 620*4a5d661aSToomas Soome ++nlinks > MAXSYMLINKS) { 621*4a5d661aSToomas Soome rc = ENOENT; 622*4a5d661aSToomas Soome goto out; 623*4a5d661aSToomas Soome } 624*4a5d661aSToomas Soome 625*4a5d661aSToomas Soome bcopy(cp, &namebuf[link_len], len + 1); 626*4a5d661aSToomas Soome 627*4a5d661aSToomas Soome if (link_len < fs->fs_maxsymlinklen) { 628*4a5d661aSToomas Soome if (fp->f_fs->fs_magic == FS_UFS1_MAGIC) 629*4a5d661aSToomas Soome cp = (caddr_t)(fp->f_di.di1.di_db); 630*4a5d661aSToomas Soome else 631*4a5d661aSToomas Soome cp = (caddr_t)(fp->f_di.di2.di_db); 632*4a5d661aSToomas Soome bcopy(cp, namebuf, (unsigned) link_len); 633*4a5d661aSToomas Soome } else { 634*4a5d661aSToomas Soome /* 635*4a5d661aSToomas Soome * Read file for symbolic link 636*4a5d661aSToomas Soome */ 637*4a5d661aSToomas Soome size_t buf_size; 638*4a5d661aSToomas Soome ufs2_daddr_t disk_block; 639*4a5d661aSToomas Soome struct fs *fs = fp->f_fs; 640*4a5d661aSToomas Soome 641*4a5d661aSToomas Soome if (!buf) 642*4a5d661aSToomas Soome buf = malloc(fs->fs_bsize); 643*4a5d661aSToomas Soome rc = block_map(f, (ufs2_daddr_t)0, &disk_block); 644*4a5d661aSToomas Soome if (rc) 645*4a5d661aSToomas Soome goto out; 646*4a5d661aSToomas Soome 647*4a5d661aSToomas Soome twiddle(1); 648*4a5d661aSToomas Soome rc = (f->f_dev->dv_strategy)(f->f_devdata, 649*4a5d661aSToomas Soome F_READ, fsbtodb(fs, disk_block), 0, 650*4a5d661aSToomas Soome fs->fs_bsize, buf, &buf_size); 651*4a5d661aSToomas Soome if (rc) 652*4a5d661aSToomas Soome goto out; 653*4a5d661aSToomas Soome 654*4a5d661aSToomas Soome bcopy((char *)buf, namebuf, (unsigned)link_len); 655*4a5d661aSToomas Soome } 656*4a5d661aSToomas Soome 657*4a5d661aSToomas Soome /* 658*4a5d661aSToomas Soome * If relative pathname, restart at parent directory. 659*4a5d661aSToomas Soome * If absolute pathname, restart at root. 660*4a5d661aSToomas Soome */ 661*4a5d661aSToomas Soome cp = namebuf; 662*4a5d661aSToomas Soome if (*cp != '/') 663*4a5d661aSToomas Soome inumber = parent_inumber; 664*4a5d661aSToomas Soome else 665*4a5d661aSToomas Soome inumber = (ino_t)ROOTINO; 666*4a5d661aSToomas Soome 667*4a5d661aSToomas Soome if ((rc = read_inode(inumber, f)) != 0) 668*4a5d661aSToomas Soome goto out; 669*4a5d661aSToomas Soome } 670*4a5d661aSToomas Soome } 671*4a5d661aSToomas Soome 672*4a5d661aSToomas Soome /* 673*4a5d661aSToomas Soome * Found terminal component. 674*4a5d661aSToomas Soome */ 675*4a5d661aSToomas Soome rc = 0; 676*4a5d661aSToomas Soome fp->f_seekp = 0; 677*4a5d661aSToomas Soome out: 678*4a5d661aSToomas Soome if (buf) 679*4a5d661aSToomas Soome free(buf); 680*4a5d661aSToomas Soome if (path) 681*4a5d661aSToomas Soome free(path); 682*4a5d661aSToomas Soome if (rc) { 683*4a5d661aSToomas Soome if (fp->f_buf) 684*4a5d661aSToomas Soome free(fp->f_buf); 685*4a5d661aSToomas Soome free(fp->f_fs); 686*4a5d661aSToomas Soome free(fp); 687*4a5d661aSToomas Soome } 688*4a5d661aSToomas Soome return (rc); 689*4a5d661aSToomas Soome } 690*4a5d661aSToomas Soome 691*4a5d661aSToomas Soome static int 692*4a5d661aSToomas Soome ufs_close(f) 693*4a5d661aSToomas Soome struct open_file *f; 694*4a5d661aSToomas Soome { 695*4a5d661aSToomas Soome struct file *fp = (struct file *)f->f_fsdata; 696*4a5d661aSToomas Soome int level; 697*4a5d661aSToomas Soome 698*4a5d661aSToomas Soome f->f_fsdata = (void *)0; 699*4a5d661aSToomas Soome if (fp == (struct file *)0) 700*4a5d661aSToomas Soome return (0); 701*4a5d661aSToomas Soome 702*4a5d661aSToomas Soome for (level = 0; level < NIADDR; level++) { 703*4a5d661aSToomas Soome if (fp->f_blk[level]) 704*4a5d661aSToomas Soome free(fp->f_blk[level]); 705*4a5d661aSToomas Soome } 706*4a5d661aSToomas Soome if (fp->f_buf) 707*4a5d661aSToomas Soome free(fp->f_buf); 708*4a5d661aSToomas Soome free(fp->f_fs); 709*4a5d661aSToomas Soome free(fp); 710*4a5d661aSToomas Soome return (0); 711*4a5d661aSToomas Soome } 712*4a5d661aSToomas Soome 713*4a5d661aSToomas Soome /* 714*4a5d661aSToomas Soome * Copy a portion of a file into kernel memory. 715*4a5d661aSToomas Soome * Cross block boundaries when necessary. 716*4a5d661aSToomas Soome */ 717*4a5d661aSToomas Soome static int 718*4a5d661aSToomas Soome ufs_read(f, start, size, resid) 719*4a5d661aSToomas Soome struct open_file *f; 720*4a5d661aSToomas Soome void *start; 721*4a5d661aSToomas Soome size_t size; 722*4a5d661aSToomas Soome size_t *resid; /* out */ 723*4a5d661aSToomas Soome { 724*4a5d661aSToomas Soome struct file *fp = (struct file *)f->f_fsdata; 725*4a5d661aSToomas Soome size_t csize; 726*4a5d661aSToomas Soome char *buf; 727*4a5d661aSToomas Soome size_t buf_size; 728*4a5d661aSToomas Soome int rc = 0; 729*4a5d661aSToomas Soome char *addr = start; 730*4a5d661aSToomas Soome 731*4a5d661aSToomas Soome while (size != 0) { 732*4a5d661aSToomas Soome if (fp->f_seekp >= DIP(fp, di_size)) 733*4a5d661aSToomas Soome break; 734*4a5d661aSToomas Soome 735*4a5d661aSToomas Soome rc = buf_read_file(f, &buf, &buf_size); 736*4a5d661aSToomas Soome if (rc) 737*4a5d661aSToomas Soome break; 738*4a5d661aSToomas Soome 739*4a5d661aSToomas Soome csize = size; 740*4a5d661aSToomas Soome if (csize > buf_size) 741*4a5d661aSToomas Soome csize = buf_size; 742*4a5d661aSToomas Soome 743*4a5d661aSToomas Soome bcopy(buf, addr, csize); 744*4a5d661aSToomas Soome 745*4a5d661aSToomas Soome fp->f_seekp += csize; 746*4a5d661aSToomas Soome addr += csize; 747*4a5d661aSToomas Soome size -= csize; 748*4a5d661aSToomas Soome } 749*4a5d661aSToomas Soome if (resid) 750*4a5d661aSToomas Soome *resid = size; 751*4a5d661aSToomas Soome return (rc); 752*4a5d661aSToomas Soome } 753*4a5d661aSToomas Soome 754*4a5d661aSToomas Soome /* 755*4a5d661aSToomas Soome * Write to a portion of an already allocated file. 756*4a5d661aSToomas Soome * Cross block boundaries when necessary. Can not 757*4a5d661aSToomas Soome * extend the file. 758*4a5d661aSToomas Soome */ 759*4a5d661aSToomas Soome static int 760*4a5d661aSToomas Soome ufs_write(f, start, size, resid) 761*4a5d661aSToomas Soome struct open_file *f; 762*4a5d661aSToomas Soome void *start; 763*4a5d661aSToomas Soome size_t size; 764*4a5d661aSToomas Soome size_t *resid; /* out */ 765*4a5d661aSToomas Soome { 766*4a5d661aSToomas Soome struct file *fp = (struct file *)f->f_fsdata; 767*4a5d661aSToomas Soome size_t csize; 768*4a5d661aSToomas Soome int rc = 0; 769*4a5d661aSToomas Soome char *addr = start; 770*4a5d661aSToomas Soome 771*4a5d661aSToomas Soome csize = size; 772*4a5d661aSToomas Soome while ((size != 0) && (csize != 0)) { 773*4a5d661aSToomas Soome if (fp->f_seekp >= DIP(fp, di_size)) 774*4a5d661aSToomas Soome break; 775*4a5d661aSToomas Soome 776*4a5d661aSToomas Soome if (csize >= 512) csize = 512; /* XXX */ 777*4a5d661aSToomas Soome 778*4a5d661aSToomas Soome rc = buf_write_file(f, addr, &csize); 779*4a5d661aSToomas Soome if (rc) 780*4a5d661aSToomas Soome break; 781*4a5d661aSToomas Soome 782*4a5d661aSToomas Soome fp->f_seekp += csize; 783*4a5d661aSToomas Soome addr += csize; 784*4a5d661aSToomas Soome size -= csize; 785*4a5d661aSToomas Soome } 786*4a5d661aSToomas Soome if (resid) 787*4a5d661aSToomas Soome *resid = size; 788*4a5d661aSToomas Soome return (rc); 789*4a5d661aSToomas Soome } 790*4a5d661aSToomas Soome 791*4a5d661aSToomas Soome static off_t 792*4a5d661aSToomas Soome ufs_seek(f, offset, where) 793*4a5d661aSToomas Soome struct open_file *f; 794*4a5d661aSToomas Soome off_t offset; 795*4a5d661aSToomas Soome int where; 796*4a5d661aSToomas Soome { 797*4a5d661aSToomas Soome struct file *fp = (struct file *)f->f_fsdata; 798*4a5d661aSToomas Soome 799*4a5d661aSToomas Soome switch (where) { 800*4a5d661aSToomas Soome case SEEK_SET: 801*4a5d661aSToomas Soome fp->f_seekp = offset; 802*4a5d661aSToomas Soome break; 803*4a5d661aSToomas Soome case SEEK_CUR: 804*4a5d661aSToomas Soome fp->f_seekp += offset; 805*4a5d661aSToomas Soome break; 806*4a5d661aSToomas Soome case SEEK_END: 807*4a5d661aSToomas Soome fp->f_seekp = DIP(fp, di_size) - offset; 808*4a5d661aSToomas Soome break; 809*4a5d661aSToomas Soome default: 810*4a5d661aSToomas Soome errno = EINVAL; 811*4a5d661aSToomas Soome return (-1); 812*4a5d661aSToomas Soome } 813*4a5d661aSToomas Soome return (fp->f_seekp); 814*4a5d661aSToomas Soome } 815*4a5d661aSToomas Soome 816*4a5d661aSToomas Soome static int 817*4a5d661aSToomas Soome ufs_stat(f, sb) 818*4a5d661aSToomas Soome struct open_file *f; 819*4a5d661aSToomas Soome struct stat *sb; 820*4a5d661aSToomas Soome { 821*4a5d661aSToomas Soome struct file *fp = (struct file *)f->f_fsdata; 822*4a5d661aSToomas Soome 823*4a5d661aSToomas Soome /* only important stuff */ 824*4a5d661aSToomas Soome sb->st_mode = DIP(fp, di_mode); 825*4a5d661aSToomas Soome sb->st_uid = DIP(fp, di_uid); 826*4a5d661aSToomas Soome sb->st_gid = DIP(fp, di_gid); 827*4a5d661aSToomas Soome sb->st_size = DIP(fp, di_size); 828*4a5d661aSToomas Soome return (0); 829*4a5d661aSToomas Soome } 830*4a5d661aSToomas Soome 831*4a5d661aSToomas Soome static int 832*4a5d661aSToomas Soome ufs_readdir(struct open_file *f, struct dirent *d) 833*4a5d661aSToomas Soome { 834*4a5d661aSToomas Soome struct file *fp = (struct file *)f->f_fsdata; 835*4a5d661aSToomas Soome struct direct *dp; 836*4a5d661aSToomas Soome char *buf; 837*4a5d661aSToomas Soome size_t buf_size; 838*4a5d661aSToomas Soome int error; 839*4a5d661aSToomas Soome 840*4a5d661aSToomas Soome /* 841*4a5d661aSToomas Soome * assume that a directory entry will not be split across blocks 842*4a5d661aSToomas Soome */ 843*4a5d661aSToomas Soome again: 844*4a5d661aSToomas Soome if (fp->f_seekp >= DIP(fp, di_size)) 845*4a5d661aSToomas Soome return (ENOENT); 846*4a5d661aSToomas Soome error = buf_read_file(f, &buf, &buf_size); 847*4a5d661aSToomas Soome if (error) 848*4a5d661aSToomas Soome return (error); 849*4a5d661aSToomas Soome dp = (struct direct *)buf; 850*4a5d661aSToomas Soome fp->f_seekp += dp->d_reclen; 851*4a5d661aSToomas Soome if (dp->d_ino == (ino_t)0) 852*4a5d661aSToomas Soome goto again; 853*4a5d661aSToomas Soome 854*4a5d661aSToomas Soome d->d_type = 0; /* illumos ufs does not have type in direct */ 855*4a5d661aSToomas Soome strcpy(d->d_name, dp->d_name); 856*4a5d661aSToomas Soome return (0); 857*4a5d661aSToomas Soome } 858