1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * CDDL HEADER START 3*7c478bd9Sstevel@tonic-gate * 4*7c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*7c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*7c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*7c478bd9Sstevel@tonic-gate * with the License. 8*7c478bd9Sstevel@tonic-gate * 9*7c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*7c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*7c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 12*7c478bd9Sstevel@tonic-gate * and limitations under the License. 13*7c478bd9Sstevel@tonic-gate * 14*7c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*7c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*7c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*7c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*7c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*7c478bd9Sstevel@tonic-gate * 20*7c478bd9Sstevel@tonic-gate * CDDL HEADER END 21*7c478bd9Sstevel@tonic-gate */ 22*7c478bd9Sstevel@tonic-gate /* 23*7c478bd9Sstevel@tonic-gate * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24*7c478bd9Sstevel@tonic-gate * Use is subject to license terms. 25*7c478bd9Sstevel@tonic-gate */ 26*7c478bd9Sstevel@tonic-gate 27*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 28*7c478bd9Sstevel@tonic-gate 29*7c478bd9Sstevel@tonic-gate #include <sys/types.h> 30*7c478bd9Sstevel@tonic-gate #include <sys/param.h> 31*7c478bd9Sstevel@tonic-gate #include <sys/vnode.h> 32*7c478bd9Sstevel@tonic-gate #include <sys/fs/ufs_fsdir.h> 33*7c478bd9Sstevel@tonic-gate #include <sys/fs/ufs_fs.h> 34*7c478bd9Sstevel@tonic-gate #include <sys/fs/ufs_inode.h> 35*7c478bd9Sstevel@tonic-gate #include <sys/sysmacros.h> 36*7c478bd9Sstevel@tonic-gate #include <sys/bootvfs.h> 37*7c478bd9Sstevel@tonic-gate #include <sys/filep.h> 38*7c478bd9Sstevel@tonic-gate 39*7c478bd9Sstevel@tonic-gate #ifdef _BOOT 40*7c478bd9Sstevel@tonic-gate #include "../common/util.h" 41*7c478bd9Sstevel@tonic-gate #else 42*7c478bd9Sstevel@tonic-gate #include <sys/sunddi.h> 43*7c478bd9Sstevel@tonic-gate #endif 44*7c478bd9Sstevel@tonic-gate 45*7c478bd9Sstevel@tonic-gate extern void *bkmem_alloc(size_t); 46*7c478bd9Sstevel@tonic-gate extern void bkmem_free(void *, size_t); 47*7c478bd9Sstevel@tonic-gate 48*7c478bd9Sstevel@tonic-gate int bootrd_debug; 49*7c478bd9Sstevel@tonic-gate #ifdef _BOOT 50*7c478bd9Sstevel@tonic-gate #define dprintf if (bootrd_debug) printf 51*7c478bd9Sstevel@tonic-gate #else 52*7c478bd9Sstevel@tonic-gate #define printf kobj_printf 53*7c478bd9Sstevel@tonic-gate #define dprintf if (bootrd_debug) kobj_printf 54*7c478bd9Sstevel@tonic-gate 55*7c478bd9Sstevel@tonic-gate /* PRINTLIKE */ 56*7c478bd9Sstevel@tonic-gate extern void kobj_printf(char *, ...); 57*7c478bd9Sstevel@tonic-gate #endif 58*7c478bd9Sstevel@tonic-gate 59*7c478bd9Sstevel@tonic-gate /* 60*7c478bd9Sstevel@tonic-gate * This fd is used when talking to the device file itself. 61*7c478bd9Sstevel@tonic-gate */ 62*7c478bd9Sstevel@tonic-gate static fileid_t *head; 63*7c478bd9Sstevel@tonic-gate 64*7c478bd9Sstevel@tonic-gate /* Only got one of these...ergo, only 1 fs open at once */ 65*7c478bd9Sstevel@tonic-gate /* static */ 66*7c478bd9Sstevel@tonic-gate devid_t *ufs_devp; 67*7c478bd9Sstevel@tonic-gate 68*7c478bd9Sstevel@tonic-gate struct dirinfo { 69*7c478bd9Sstevel@tonic-gate int loc; 70*7c478bd9Sstevel@tonic-gate fileid_t *fi; 71*7c478bd9Sstevel@tonic-gate }; 72*7c478bd9Sstevel@tonic-gate 73*7c478bd9Sstevel@tonic-gate static int bufs_close(int); 74*7c478bd9Sstevel@tonic-gate static void bufs_closeall(int); 75*7c478bd9Sstevel@tonic-gate static ino_t find(fileid_t *filep, char *path); 76*7c478bd9Sstevel@tonic-gate static ino_t dlook(fileid_t *filep, char *path); 77*7c478bd9Sstevel@tonic-gate static daddr32_t sbmap(fileid_t *filep, daddr32_t bn); 78*7c478bd9Sstevel@tonic-gate static struct direct *readdir(struct dirinfo *dstuff); 79*7c478bd9Sstevel@tonic-gate static void set_cache(int, void *, uint_t); 80*7c478bd9Sstevel@tonic-gate static void *get_cache(int); 81*7c478bd9Sstevel@tonic-gate static void free_cache(); 82*7c478bd9Sstevel@tonic-gate 83*7c478bd9Sstevel@tonic-gate /* These are the pools of buffers, etc. */ 84*7c478bd9Sstevel@tonic-gate #define NBUFS (NIADDR+1) 85*7c478bd9Sstevel@tonic-gate /* Compilers like to play with alignment, so force the issue here */ 86*7c478bd9Sstevel@tonic-gate static union { 87*7c478bd9Sstevel@tonic-gate char *blk[NBUFS]; 88*7c478bd9Sstevel@tonic-gate daddr32_t *dummy; 89*7c478bd9Sstevel@tonic-gate } b; 90*7c478bd9Sstevel@tonic-gate daddr32_t blknos[NBUFS]; 91*7c478bd9Sstevel@tonic-gate 92*7c478bd9Sstevel@tonic-gate /* 93*7c478bd9Sstevel@tonic-gate * There is only 1 open (mounted) device at any given time. 94*7c478bd9Sstevel@tonic-gate * So we can keep a single, global devp file descriptor to 95*7c478bd9Sstevel@tonic-gate * use to index into the di[] array. This is not true for the 96*7c478bd9Sstevel@tonic-gate * fi[] array. We can have more than one file open at once, 97*7c478bd9Sstevel@tonic-gate * so there is no global fd for the fi[]. 98*7c478bd9Sstevel@tonic-gate * The user program must save the fd passed back from open() 99*7c478bd9Sstevel@tonic-gate * and use it to do subsequent read()'s. 100*7c478bd9Sstevel@tonic-gate */ 101*7c478bd9Sstevel@tonic-gate 102*7c478bd9Sstevel@tonic-gate static int 103*7c478bd9Sstevel@tonic-gate openi(fileid_t *filep, ino_t inode) 104*7c478bd9Sstevel@tonic-gate { 105*7c478bd9Sstevel@tonic-gate struct dinode *dp; 106*7c478bd9Sstevel@tonic-gate devid_t *devp = filep->fi_devp; 107*7c478bd9Sstevel@tonic-gate 108*7c478bd9Sstevel@tonic-gate filep->fi_inode = get_cache((int)inode); 109*7c478bd9Sstevel@tonic-gate if (filep->fi_inode != 0) 110*7c478bd9Sstevel@tonic-gate return (0); 111*7c478bd9Sstevel@tonic-gate 112*7c478bd9Sstevel@tonic-gate filep->fi_offset = 0; 113*7c478bd9Sstevel@tonic-gate filep->fi_blocknum = fsbtodb(&devp->un_fs.di_fs, 114*7c478bd9Sstevel@tonic-gate itod(&devp->un_fs.di_fs, inode)); 115*7c478bd9Sstevel@tonic-gate 116*7c478bd9Sstevel@tonic-gate /* never more than 1 disk block */ 117*7c478bd9Sstevel@tonic-gate filep->fi_count = devp->un_fs.di_fs.fs_bsize; 118*7c478bd9Sstevel@tonic-gate filep->fi_memp = 0; /* cached read */ 119*7c478bd9Sstevel@tonic-gate if (diskread(filep) != 0) { 120*7c478bd9Sstevel@tonic-gate return (0); 121*7c478bd9Sstevel@tonic-gate } 122*7c478bd9Sstevel@tonic-gate 123*7c478bd9Sstevel@tonic-gate dp = (struct dinode *)filep->fi_memp; 124*7c478bd9Sstevel@tonic-gate filep->fi_inode = (struct inode *) 125*7c478bd9Sstevel@tonic-gate bkmem_alloc(sizeof (struct inode)); 126*7c478bd9Sstevel@tonic-gate bzero((char *)filep->fi_inode, sizeof (struct inode)); 127*7c478bd9Sstevel@tonic-gate filep->fi_inode->i_ic = 128*7c478bd9Sstevel@tonic-gate dp[itoo(&devp->un_fs.di_fs, inode)].di_un.di_icom; 129*7c478bd9Sstevel@tonic-gate filep->fi_inode->i_number = inode; 130*7c478bd9Sstevel@tonic-gate set_cache((int)inode, (void *)filep->fi_inode, sizeof (struct inode)); 131*7c478bd9Sstevel@tonic-gate return (0); 132*7c478bd9Sstevel@tonic-gate } 133*7c478bd9Sstevel@tonic-gate 134*7c478bd9Sstevel@tonic-gate static fileid_t * 135*7c478bd9Sstevel@tonic-gate find_fp(int fd) 136*7c478bd9Sstevel@tonic-gate { 137*7c478bd9Sstevel@tonic-gate fileid_t *filep = head; 138*7c478bd9Sstevel@tonic-gate 139*7c478bd9Sstevel@tonic-gate if (fd >= 0) { 140*7c478bd9Sstevel@tonic-gate while ((filep = filep->fi_forw) != head) 141*7c478bd9Sstevel@tonic-gate if (fd == filep->fi_filedes) 142*7c478bd9Sstevel@tonic-gate return (filep->fi_taken ? filep : 0); 143*7c478bd9Sstevel@tonic-gate } 144*7c478bd9Sstevel@tonic-gate 145*7c478bd9Sstevel@tonic-gate return (0); 146*7c478bd9Sstevel@tonic-gate } 147*7c478bd9Sstevel@tonic-gate 148*7c478bd9Sstevel@tonic-gate static ino_t 149*7c478bd9Sstevel@tonic-gate find(fileid_t *filep, char *path) 150*7c478bd9Sstevel@tonic-gate { 151*7c478bd9Sstevel@tonic-gate char *q; 152*7c478bd9Sstevel@tonic-gate char c; 153*7c478bd9Sstevel@tonic-gate ino_t inode; 154*7c478bd9Sstevel@tonic-gate char lpath[MAXPATHLEN]; 155*7c478bd9Sstevel@tonic-gate char *lpathp = lpath; 156*7c478bd9Sstevel@tonic-gate int len, r; 157*7c478bd9Sstevel@tonic-gate devid_t *devp; 158*7c478bd9Sstevel@tonic-gate 159*7c478bd9Sstevel@tonic-gate if (path == NULL || *path == '\0') { 160*7c478bd9Sstevel@tonic-gate printf("null path\n"); 161*7c478bd9Sstevel@tonic-gate return ((ino_t)0); 162*7c478bd9Sstevel@tonic-gate } 163*7c478bd9Sstevel@tonic-gate 164*7c478bd9Sstevel@tonic-gate dprintf("openi: %s\n", path); 165*7c478bd9Sstevel@tonic-gate 166*7c478bd9Sstevel@tonic-gate bzero(lpath, sizeof (lpath)); 167*7c478bd9Sstevel@tonic-gate bcopy(path, lpath, strlen(path)); 168*7c478bd9Sstevel@tonic-gate devp = filep->fi_devp; 169*7c478bd9Sstevel@tonic-gate while (*lpathp) { 170*7c478bd9Sstevel@tonic-gate /* if at the beginning of pathname get root inode */ 171*7c478bd9Sstevel@tonic-gate r = (lpathp == lpath); 172*7c478bd9Sstevel@tonic-gate if (r && openi(filep, (ino_t)UFSROOTINO)) 173*7c478bd9Sstevel@tonic-gate return ((ino_t)0); 174*7c478bd9Sstevel@tonic-gate while (*lpathp == '/') 175*7c478bd9Sstevel@tonic-gate lpathp++; /* skip leading slashes */ 176*7c478bd9Sstevel@tonic-gate q = lpathp; 177*7c478bd9Sstevel@tonic-gate while (*q != '/' && *q != '\0') 178*7c478bd9Sstevel@tonic-gate q++; /* find end of component */ 179*7c478bd9Sstevel@tonic-gate c = *q; 180*7c478bd9Sstevel@tonic-gate *q = '\0'; /* terminate component */ 181*7c478bd9Sstevel@tonic-gate 182*7c478bd9Sstevel@tonic-gate /* Bail out early if opening root */ 183*7c478bd9Sstevel@tonic-gate if (r && (*lpathp == '\0')) 184*7c478bd9Sstevel@tonic-gate return ((ino_t)UFSROOTINO); 185*7c478bd9Sstevel@tonic-gate if ((inode = dlook(filep, lpathp)) != 0) { 186*7c478bd9Sstevel@tonic-gate if (openi(filep, inode)) 187*7c478bd9Sstevel@tonic-gate return ((ino_t)0); 188*7c478bd9Sstevel@tonic-gate if ((filep->fi_inode->i_smode & IFMT) == IFLNK) { 189*7c478bd9Sstevel@tonic-gate filep->fi_blocknum = 190*7c478bd9Sstevel@tonic-gate fsbtodb(&devp->un_fs.di_fs, 191*7c478bd9Sstevel@tonic-gate filep->fi_inode->i_db[0]); 192*7c478bd9Sstevel@tonic-gate filep->fi_count = DEV_BSIZE; 193*7c478bd9Sstevel@tonic-gate filep->fi_memp = 0; 194*7c478bd9Sstevel@tonic-gate if (diskread(filep) != 0) 195*7c478bd9Sstevel@tonic-gate return ((ino_t)0); 196*7c478bd9Sstevel@tonic-gate len = strlen(filep->fi_memp); 197*7c478bd9Sstevel@tonic-gate if (filep->fi_memp[0] == '/') 198*7c478bd9Sstevel@tonic-gate /* absolute link */ 199*7c478bd9Sstevel@tonic-gate lpathp = lpath; 200*7c478bd9Sstevel@tonic-gate /* copy rest of unprocessed path up */ 201*7c478bd9Sstevel@tonic-gate bcopy(q, lpathp + len, strlen(q + 1) + 2); 202*7c478bd9Sstevel@tonic-gate /* point to unprocessed path */ 203*7c478bd9Sstevel@tonic-gate *(lpathp + len) = c; 204*7c478bd9Sstevel@tonic-gate /* prepend link in before unprocessed path */ 205*7c478bd9Sstevel@tonic-gate bcopy(filep->fi_memp, lpathp, len); 206*7c478bd9Sstevel@tonic-gate lpathp = lpath; 207*7c478bd9Sstevel@tonic-gate continue; 208*7c478bd9Sstevel@tonic-gate } else 209*7c478bd9Sstevel@tonic-gate *q = c; 210*7c478bd9Sstevel@tonic-gate if (c == '\0') 211*7c478bd9Sstevel@tonic-gate break; 212*7c478bd9Sstevel@tonic-gate lpathp = q; 213*7c478bd9Sstevel@tonic-gate continue; 214*7c478bd9Sstevel@tonic-gate } else { 215*7c478bd9Sstevel@tonic-gate return ((ino_t)0); 216*7c478bd9Sstevel@tonic-gate } 217*7c478bd9Sstevel@tonic-gate } 218*7c478bd9Sstevel@tonic-gate return (inode); 219*7c478bd9Sstevel@tonic-gate } 220*7c478bd9Sstevel@tonic-gate 221*7c478bd9Sstevel@tonic-gate static daddr32_t 222*7c478bd9Sstevel@tonic-gate sbmap(fileid_t *filep, daddr32_t bn) 223*7c478bd9Sstevel@tonic-gate { 224*7c478bd9Sstevel@tonic-gate struct inode *inodep; 225*7c478bd9Sstevel@tonic-gate int i, j, sh; 226*7c478bd9Sstevel@tonic-gate daddr32_t nb, *bap; 227*7c478bd9Sstevel@tonic-gate daddr32_t *db; 228*7c478bd9Sstevel@tonic-gate devid_t *devp; 229*7c478bd9Sstevel@tonic-gate 230*7c478bd9Sstevel@tonic-gate devp = filep->fi_devp; 231*7c478bd9Sstevel@tonic-gate inodep = filep->fi_inode; 232*7c478bd9Sstevel@tonic-gate db = inodep->i_db; 233*7c478bd9Sstevel@tonic-gate 234*7c478bd9Sstevel@tonic-gate /* 235*7c478bd9Sstevel@tonic-gate * blocks 0..NDADDR are direct blocks 236*7c478bd9Sstevel@tonic-gate */ 237*7c478bd9Sstevel@tonic-gate if (bn < NDADDR) { 238*7c478bd9Sstevel@tonic-gate nb = db[bn]; 239*7c478bd9Sstevel@tonic-gate return (nb); 240*7c478bd9Sstevel@tonic-gate } 241*7c478bd9Sstevel@tonic-gate 242*7c478bd9Sstevel@tonic-gate /* 243*7c478bd9Sstevel@tonic-gate * addresses NIADDR have single and double indirect blocks. 244*7c478bd9Sstevel@tonic-gate * the first step is to determine how many levels of indirection. 245*7c478bd9Sstevel@tonic-gate */ 246*7c478bd9Sstevel@tonic-gate sh = 1; 247*7c478bd9Sstevel@tonic-gate bn -= NDADDR; 248*7c478bd9Sstevel@tonic-gate for (j = NIADDR; j > 0; j--) { 249*7c478bd9Sstevel@tonic-gate sh *= NINDIR(&devp->un_fs.di_fs); 250*7c478bd9Sstevel@tonic-gate if (bn < sh) 251*7c478bd9Sstevel@tonic-gate break; 252*7c478bd9Sstevel@tonic-gate bn -= sh; 253*7c478bd9Sstevel@tonic-gate } 254*7c478bd9Sstevel@tonic-gate if (j == 0) { 255*7c478bd9Sstevel@tonic-gate return ((daddr32_t)0); 256*7c478bd9Sstevel@tonic-gate } 257*7c478bd9Sstevel@tonic-gate 258*7c478bd9Sstevel@tonic-gate /* 259*7c478bd9Sstevel@tonic-gate * fetch the first indirect block address from the inode 260*7c478bd9Sstevel@tonic-gate */ 261*7c478bd9Sstevel@tonic-gate nb = inodep->i_ib[NIADDR - j]; 262*7c478bd9Sstevel@tonic-gate if (nb == 0) { 263*7c478bd9Sstevel@tonic-gate return ((daddr32_t)0); 264*7c478bd9Sstevel@tonic-gate } 265*7c478bd9Sstevel@tonic-gate 266*7c478bd9Sstevel@tonic-gate /* 267*7c478bd9Sstevel@tonic-gate * fetch through the indirect blocks 268*7c478bd9Sstevel@tonic-gate */ 269*7c478bd9Sstevel@tonic-gate for (; j <= NIADDR; j++) { 270*7c478bd9Sstevel@tonic-gate if (blknos[j] != nb) { 271*7c478bd9Sstevel@tonic-gate filep->fi_blocknum = fsbtodb(&devp->un_fs.di_fs, nb); 272*7c478bd9Sstevel@tonic-gate filep->fi_count = devp->un_fs.di_fs.fs_bsize; 273*7c478bd9Sstevel@tonic-gate filep->fi_memp = 0; 274*7c478bd9Sstevel@tonic-gate if (diskread(filep) != 0) 275*7c478bd9Sstevel@tonic-gate return (0); 276*7c478bd9Sstevel@tonic-gate b.blk[j] = filep->fi_memp; 277*7c478bd9Sstevel@tonic-gate blknos[j] = nb; 278*7c478bd9Sstevel@tonic-gate } 279*7c478bd9Sstevel@tonic-gate bap = (daddr32_t *)b.blk[j]; 280*7c478bd9Sstevel@tonic-gate sh /= NINDIR(&devp->un_fs.di_fs); 281*7c478bd9Sstevel@tonic-gate i = (bn / sh) % NINDIR(&devp->un_fs.di_fs); 282*7c478bd9Sstevel@tonic-gate nb = bap[i]; 283*7c478bd9Sstevel@tonic-gate if (nb == 0) { 284*7c478bd9Sstevel@tonic-gate return ((daddr32_t)0); 285*7c478bd9Sstevel@tonic-gate } 286*7c478bd9Sstevel@tonic-gate } 287*7c478bd9Sstevel@tonic-gate return (nb); 288*7c478bd9Sstevel@tonic-gate } 289*7c478bd9Sstevel@tonic-gate 290*7c478bd9Sstevel@tonic-gate static ino_t 291*7c478bd9Sstevel@tonic-gate dlook(fileid_t *filep, char *path) 292*7c478bd9Sstevel@tonic-gate { 293*7c478bd9Sstevel@tonic-gate struct direct *dp; 294*7c478bd9Sstevel@tonic-gate struct inode *ip; 295*7c478bd9Sstevel@tonic-gate struct dirinfo dirp; 296*7c478bd9Sstevel@tonic-gate int len; 297*7c478bd9Sstevel@tonic-gate 298*7c478bd9Sstevel@tonic-gate ip = filep->fi_inode; 299*7c478bd9Sstevel@tonic-gate if (path == NULL || *path == '\0') 300*7c478bd9Sstevel@tonic-gate return (0); 301*7c478bd9Sstevel@tonic-gate 302*7c478bd9Sstevel@tonic-gate dprintf("dlook: %s\n", path); 303*7c478bd9Sstevel@tonic-gate 304*7c478bd9Sstevel@tonic-gate if ((ip->i_smode & IFMT) != IFDIR) { 305*7c478bd9Sstevel@tonic-gate return (0); 306*7c478bd9Sstevel@tonic-gate } 307*7c478bd9Sstevel@tonic-gate if (ip->i_size == 0) { 308*7c478bd9Sstevel@tonic-gate return (0); 309*7c478bd9Sstevel@tonic-gate } 310*7c478bd9Sstevel@tonic-gate len = strlen(path); 311*7c478bd9Sstevel@tonic-gate dirp.loc = 0; 312*7c478bd9Sstevel@tonic-gate dirp.fi = filep; 313*7c478bd9Sstevel@tonic-gate for (dp = readdir(&dirp); dp != NULL; dp = readdir(&dirp)) { 314*7c478bd9Sstevel@tonic-gate if (dp->d_ino == 0) 315*7c478bd9Sstevel@tonic-gate continue; 316*7c478bd9Sstevel@tonic-gate if (dp->d_namlen == len && strcmp(path, dp->d_name) == 0) { 317*7c478bd9Sstevel@tonic-gate return (dp->d_ino); 318*7c478bd9Sstevel@tonic-gate } 319*7c478bd9Sstevel@tonic-gate /* Allow "*" to print all names at that level, w/out match */ 320*7c478bd9Sstevel@tonic-gate if (strcmp(path, "*") == 0) 321*7c478bd9Sstevel@tonic-gate dprintf("%s\n", dp->d_name); 322*7c478bd9Sstevel@tonic-gate } 323*7c478bd9Sstevel@tonic-gate return (0); 324*7c478bd9Sstevel@tonic-gate } 325*7c478bd9Sstevel@tonic-gate 326*7c478bd9Sstevel@tonic-gate /* 327*7c478bd9Sstevel@tonic-gate * get next entry in a directory. 328*7c478bd9Sstevel@tonic-gate */ 329*7c478bd9Sstevel@tonic-gate struct direct * 330*7c478bd9Sstevel@tonic-gate readdir(struct dirinfo *dstuff) 331*7c478bd9Sstevel@tonic-gate { 332*7c478bd9Sstevel@tonic-gate struct direct *dp; 333*7c478bd9Sstevel@tonic-gate fileid_t *filep; 334*7c478bd9Sstevel@tonic-gate daddr32_t lbn, d; 335*7c478bd9Sstevel@tonic-gate int off; 336*7c478bd9Sstevel@tonic-gate devid_t *devp; 337*7c478bd9Sstevel@tonic-gate 338*7c478bd9Sstevel@tonic-gate filep = dstuff->fi; 339*7c478bd9Sstevel@tonic-gate devp = filep->fi_devp; 340*7c478bd9Sstevel@tonic-gate for (;;) { 341*7c478bd9Sstevel@tonic-gate if (dstuff->loc >= filep->fi_inode->i_size) { 342*7c478bd9Sstevel@tonic-gate return (NULL); 343*7c478bd9Sstevel@tonic-gate } 344*7c478bd9Sstevel@tonic-gate off = blkoff(&devp->un_fs.di_fs, dstuff->loc); 345*7c478bd9Sstevel@tonic-gate dprintf("readdir: off = 0x%x\n", off); 346*7c478bd9Sstevel@tonic-gate if (off == 0) { 347*7c478bd9Sstevel@tonic-gate lbn = lblkno(&devp->un_fs.di_fs, dstuff->loc); 348*7c478bd9Sstevel@tonic-gate d = sbmap(filep, lbn); 349*7c478bd9Sstevel@tonic-gate 350*7c478bd9Sstevel@tonic-gate if (d == 0) 351*7c478bd9Sstevel@tonic-gate return (NULL); 352*7c478bd9Sstevel@tonic-gate 353*7c478bd9Sstevel@tonic-gate filep->fi_blocknum = fsbtodb(&devp->un_fs.di_fs, d); 354*7c478bd9Sstevel@tonic-gate filep->fi_count = 355*7c478bd9Sstevel@tonic-gate blksize(&devp->un_fs.di_fs, filep->fi_inode, lbn); 356*7c478bd9Sstevel@tonic-gate filep->fi_memp = 0; 357*7c478bd9Sstevel@tonic-gate if (diskread(filep) != 0) { 358*7c478bd9Sstevel@tonic-gate return (NULL); 359*7c478bd9Sstevel@tonic-gate } 360*7c478bd9Sstevel@tonic-gate } 361*7c478bd9Sstevel@tonic-gate dp = (struct direct *)(filep->fi_memp + off); 362*7c478bd9Sstevel@tonic-gate dstuff->loc += dp->d_reclen; 363*7c478bd9Sstevel@tonic-gate if (dp->d_ino == 0) 364*7c478bd9Sstevel@tonic-gate continue; 365*7c478bd9Sstevel@tonic-gate dprintf("readdir: name = %s\n", dp->d_name); 366*7c478bd9Sstevel@tonic-gate return (dp); 367*7c478bd9Sstevel@tonic-gate } 368*7c478bd9Sstevel@tonic-gate } 369*7c478bd9Sstevel@tonic-gate 370*7c478bd9Sstevel@tonic-gate /* 371*7c478bd9Sstevel@tonic-gate * Get the next block of data from the file. If possible, dma right into 372*7c478bd9Sstevel@tonic-gate * user's buffer 373*7c478bd9Sstevel@tonic-gate */ 374*7c478bd9Sstevel@tonic-gate static int 375*7c478bd9Sstevel@tonic-gate getblock(fileid_t *filep, caddr_t buf, int count, int *rcount) 376*7c478bd9Sstevel@tonic-gate { 377*7c478bd9Sstevel@tonic-gate struct fs *fs; 378*7c478bd9Sstevel@tonic-gate caddr_t p; 379*7c478bd9Sstevel@tonic-gate int off, size, diff; 380*7c478bd9Sstevel@tonic-gate daddr32_t lbn; 381*7c478bd9Sstevel@tonic-gate devid_t *devp; 382*7c478bd9Sstevel@tonic-gate 383*7c478bd9Sstevel@tonic-gate dprintf("getblock: buf 0x%p, count 0x%x\n", (void *)buf, count); 384*7c478bd9Sstevel@tonic-gate 385*7c478bd9Sstevel@tonic-gate devp = filep->fi_devp; 386*7c478bd9Sstevel@tonic-gate p = filep->fi_memp; 387*7c478bd9Sstevel@tonic-gate if ((signed)filep->fi_count <= 0) { 388*7c478bd9Sstevel@tonic-gate 389*7c478bd9Sstevel@tonic-gate /* find the amt left to be read in the file */ 390*7c478bd9Sstevel@tonic-gate diff = filep->fi_inode->i_size - filep->fi_offset; 391*7c478bd9Sstevel@tonic-gate if (diff <= 0) { 392*7c478bd9Sstevel@tonic-gate printf("Short read\n"); 393*7c478bd9Sstevel@tonic-gate return (-1); 394*7c478bd9Sstevel@tonic-gate } 395*7c478bd9Sstevel@tonic-gate 396*7c478bd9Sstevel@tonic-gate fs = &devp->un_fs.di_fs; 397*7c478bd9Sstevel@tonic-gate /* which block (or frag) in the file do we read? */ 398*7c478bd9Sstevel@tonic-gate lbn = lblkno(fs, filep->fi_offset); 399*7c478bd9Sstevel@tonic-gate 400*7c478bd9Sstevel@tonic-gate /* which physical block on the device do we read? */ 401*7c478bd9Sstevel@tonic-gate filep->fi_blocknum = fsbtodb(fs, sbmap(filep, lbn)); 402*7c478bd9Sstevel@tonic-gate 403*7c478bd9Sstevel@tonic-gate off = blkoff(fs, filep->fi_offset); 404*7c478bd9Sstevel@tonic-gate 405*7c478bd9Sstevel@tonic-gate /* either blksize or fragsize */ 406*7c478bd9Sstevel@tonic-gate size = blksize(fs, filep->fi_inode, lbn); 407*7c478bd9Sstevel@tonic-gate filep->fi_count = size; 408*7c478bd9Sstevel@tonic-gate filep->fi_memp = filep->fi_buf; 409*7c478bd9Sstevel@tonic-gate 410*7c478bd9Sstevel@tonic-gate /* 411*7c478bd9Sstevel@tonic-gate * optimization if we are reading large blocks of data then 412*7c478bd9Sstevel@tonic-gate * we can go directly to user's buffer 413*7c478bd9Sstevel@tonic-gate */ 414*7c478bd9Sstevel@tonic-gate *rcount = 0; 415*7c478bd9Sstevel@tonic-gate if (off == 0 && count >= size) { 416*7c478bd9Sstevel@tonic-gate filep->fi_memp = buf; 417*7c478bd9Sstevel@tonic-gate if (diskread(filep)) { 418*7c478bd9Sstevel@tonic-gate return (-1); 419*7c478bd9Sstevel@tonic-gate } 420*7c478bd9Sstevel@tonic-gate *rcount = size; 421*7c478bd9Sstevel@tonic-gate filep->fi_count = 0; 422*7c478bd9Sstevel@tonic-gate return (0); 423*7c478bd9Sstevel@tonic-gate } else if (diskread(filep)) 424*7c478bd9Sstevel@tonic-gate return (-1); 425*7c478bd9Sstevel@tonic-gate 426*7c478bd9Sstevel@tonic-gate if (filep->fi_offset - off + size >= filep->fi_inode->i_size) 427*7c478bd9Sstevel@tonic-gate filep->fi_count = diff + off; 428*7c478bd9Sstevel@tonic-gate filep->fi_count -= off; 429*7c478bd9Sstevel@tonic-gate p = &filep->fi_memp[off]; 430*7c478bd9Sstevel@tonic-gate } 431*7c478bd9Sstevel@tonic-gate filep->fi_memp = p; 432*7c478bd9Sstevel@tonic-gate return (0); 433*7c478bd9Sstevel@tonic-gate } 434*7c478bd9Sstevel@tonic-gate 435*7c478bd9Sstevel@tonic-gate 436*7c478bd9Sstevel@tonic-gate /* 437*7c478bd9Sstevel@tonic-gate * This is the high-level read function. It works like this. 438*7c478bd9Sstevel@tonic-gate * We assume that our IO device buffers up some amount of 439*7c478bd9Sstevel@tonic-gate * data and that we can get a ptr to it. Thus we need 440*7c478bd9Sstevel@tonic-gate * to actually call the device func about filesize/blocksize times 441*7c478bd9Sstevel@tonic-gate * and this greatly increases our IO speed. When we already 442*7c478bd9Sstevel@tonic-gate * have data in the buffer, we just return that data (with bcopy() ). 443*7c478bd9Sstevel@tonic-gate */ 444*7c478bd9Sstevel@tonic-gate 445*7c478bd9Sstevel@tonic-gate static ssize_t 446*7c478bd9Sstevel@tonic-gate bufs_read(int fd, caddr_t buf, size_t count) 447*7c478bd9Sstevel@tonic-gate { 448*7c478bd9Sstevel@tonic-gate size_t i, j; 449*7c478bd9Sstevel@tonic-gate caddr_t n; 450*7c478bd9Sstevel@tonic-gate int rcount; 451*7c478bd9Sstevel@tonic-gate fileid_t *filep; 452*7c478bd9Sstevel@tonic-gate 453*7c478bd9Sstevel@tonic-gate if (!(filep = find_fp(fd))) { 454*7c478bd9Sstevel@tonic-gate return (-1); 455*7c478bd9Sstevel@tonic-gate } 456*7c478bd9Sstevel@tonic-gate 457*7c478bd9Sstevel@tonic-gate if (filep->fi_offset + count > filep->fi_inode->i_size) 458*7c478bd9Sstevel@tonic-gate count = filep->fi_inode->i_size - filep->fi_offset; 459*7c478bd9Sstevel@tonic-gate 460*7c478bd9Sstevel@tonic-gate /* that was easy */ 461*7c478bd9Sstevel@tonic-gate if ((i = count) == 0) 462*7c478bd9Sstevel@tonic-gate return (0); 463*7c478bd9Sstevel@tonic-gate 464*7c478bd9Sstevel@tonic-gate n = buf; 465*7c478bd9Sstevel@tonic-gate while (i > 0) { 466*7c478bd9Sstevel@tonic-gate /* If we need to reload the buffer, do so */ 467*7c478bd9Sstevel@tonic-gate if ((j = filep->fi_count) == 0) { 468*7c478bd9Sstevel@tonic-gate (void) getblock(filep, buf, i, &rcount); 469*7c478bd9Sstevel@tonic-gate i -= rcount; 470*7c478bd9Sstevel@tonic-gate buf += rcount; 471*7c478bd9Sstevel@tonic-gate filep->fi_offset += rcount; 472*7c478bd9Sstevel@tonic-gate } else { 473*7c478bd9Sstevel@tonic-gate /* else just bcopy from our buffer */ 474*7c478bd9Sstevel@tonic-gate j = MIN(i, j); 475*7c478bd9Sstevel@tonic-gate bcopy(filep->fi_memp, buf, (unsigned)j); 476*7c478bd9Sstevel@tonic-gate buf += j; 477*7c478bd9Sstevel@tonic-gate filep->fi_memp += j; 478*7c478bd9Sstevel@tonic-gate filep->fi_offset += j; 479*7c478bd9Sstevel@tonic-gate filep->fi_count -= j; 480*7c478bd9Sstevel@tonic-gate i -= j; 481*7c478bd9Sstevel@tonic-gate } 482*7c478bd9Sstevel@tonic-gate } 483*7c478bd9Sstevel@tonic-gate return (buf - n); 484*7c478bd9Sstevel@tonic-gate } 485*7c478bd9Sstevel@tonic-gate 486*7c478bd9Sstevel@tonic-gate /* 487*7c478bd9Sstevel@tonic-gate * This routine will open a device as it is known by the V2 OBP. 488*7c478bd9Sstevel@tonic-gate * Interface Defn: 489*7c478bd9Sstevel@tonic-gate * err = mountroot(string); 490*7c478bd9Sstevel@tonic-gate * err = 0 on success 491*7c478bd9Sstevel@tonic-gate * err = -1 on failure 492*7c478bd9Sstevel@tonic-gate * string: char string describing the properties of the device. 493*7c478bd9Sstevel@tonic-gate * We must not dork with any fi[]'s here. Save that for later. 494*7c478bd9Sstevel@tonic-gate */ 495*7c478bd9Sstevel@tonic-gate 496*7c478bd9Sstevel@tonic-gate static int 497*7c478bd9Sstevel@tonic-gate bufs_mountroot(char *str) 498*7c478bd9Sstevel@tonic-gate { 499*7c478bd9Sstevel@tonic-gate if (ufs_devp) /* already mounted */ 500*7c478bd9Sstevel@tonic-gate return (0); 501*7c478bd9Sstevel@tonic-gate 502*7c478bd9Sstevel@tonic-gate ufs_devp = (devid_t *)bkmem_alloc(sizeof (devid_t)); 503*7c478bd9Sstevel@tonic-gate ufs_devp->di_taken = 1; 504*7c478bd9Sstevel@tonic-gate ufs_devp->di_dcookie = 0; 505*7c478bd9Sstevel@tonic-gate ufs_devp->di_desc = (char *)bkmem_alloc(strlen(str) + 1); 506*7c478bd9Sstevel@tonic-gate (void) strcpy(ufs_devp->di_desc, str); 507*7c478bd9Sstevel@tonic-gate bzero(ufs_devp->un_fs.dummy, SBSIZE); 508*7c478bd9Sstevel@tonic-gate head = (fileid_t *)bkmem_alloc(sizeof (fileid_t)); 509*7c478bd9Sstevel@tonic-gate head->fi_back = head->fi_forw = head; 510*7c478bd9Sstevel@tonic-gate head->fi_filedes = 0; 511*7c478bd9Sstevel@tonic-gate head->fi_taken = 0; 512*7c478bd9Sstevel@tonic-gate 513*7c478bd9Sstevel@tonic-gate /* Setup read of the superblock */ 514*7c478bd9Sstevel@tonic-gate head->fi_devp = ufs_devp; 515*7c478bd9Sstevel@tonic-gate head->fi_blocknum = SBLOCK; 516*7c478bd9Sstevel@tonic-gate head->fi_count = (uint_t)SBSIZE; 517*7c478bd9Sstevel@tonic-gate head->fi_memp = (caddr_t)&(ufs_devp->un_fs.di_fs); 518*7c478bd9Sstevel@tonic-gate head->fi_offset = 0; 519*7c478bd9Sstevel@tonic-gate 520*7c478bd9Sstevel@tonic-gate if (diskread(head)) { 521*7c478bd9Sstevel@tonic-gate printf("failed to read superblock\n"); 522*7c478bd9Sstevel@tonic-gate (void) bufs_closeall(1); 523*7c478bd9Sstevel@tonic-gate return (-1); 524*7c478bd9Sstevel@tonic-gate } 525*7c478bd9Sstevel@tonic-gate 526*7c478bd9Sstevel@tonic-gate if (ufs_devp->un_fs.di_fs.fs_magic != FS_MAGIC) { 527*7c478bd9Sstevel@tonic-gate dprintf("fs magic = 0x%x\n", ufs_devp->un_fs.di_fs.fs_magic); 528*7c478bd9Sstevel@tonic-gate (void) bufs_closeall(1); 529*7c478bd9Sstevel@tonic-gate return (-1); 530*7c478bd9Sstevel@tonic-gate } 531*7c478bd9Sstevel@tonic-gate dprintf("mountroot succeeded\n"); 532*7c478bd9Sstevel@tonic-gate return (0); 533*7c478bd9Sstevel@tonic-gate } 534*7c478bd9Sstevel@tonic-gate 535*7c478bd9Sstevel@tonic-gate /* 536*7c478bd9Sstevel@tonic-gate * Unmount the currently mounted root fs. In practice, this means 537*7c478bd9Sstevel@tonic-gate * closing all open files and releasing resources. All of this 538*7c478bd9Sstevel@tonic-gate * is done by closeall(). 539*7c478bd9Sstevel@tonic-gate */ 540*7c478bd9Sstevel@tonic-gate 541*7c478bd9Sstevel@tonic-gate static int 542*7c478bd9Sstevel@tonic-gate bufs_unmountroot(void) 543*7c478bd9Sstevel@tonic-gate { 544*7c478bd9Sstevel@tonic-gate if (ufs_devp == NULL) 545*7c478bd9Sstevel@tonic-gate return (-1); 546*7c478bd9Sstevel@tonic-gate 547*7c478bd9Sstevel@tonic-gate (void) bufs_closeall(1); 548*7c478bd9Sstevel@tonic-gate 549*7c478bd9Sstevel@tonic-gate return (0); 550*7c478bd9Sstevel@tonic-gate } 551*7c478bd9Sstevel@tonic-gate 552*7c478bd9Sstevel@tonic-gate /* 553*7c478bd9Sstevel@tonic-gate * We allocate an fd here for use when talking 554*7c478bd9Sstevel@tonic-gate * to the file itself. 555*7c478bd9Sstevel@tonic-gate */ 556*7c478bd9Sstevel@tonic-gate 557*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 558*7c478bd9Sstevel@tonic-gate static int 559*7c478bd9Sstevel@tonic-gate bufs_open(char *filename, int flags) 560*7c478bd9Sstevel@tonic-gate { 561*7c478bd9Sstevel@tonic-gate fileid_t *filep; 562*7c478bd9Sstevel@tonic-gate ino_t inode; 563*7c478bd9Sstevel@tonic-gate static int filedes = 1; 564*7c478bd9Sstevel@tonic-gate 565*7c478bd9Sstevel@tonic-gate dprintf("open: %s\n", filename); 566*7c478bd9Sstevel@tonic-gate 567*7c478bd9Sstevel@tonic-gate /* build and link a new file descriptor */ 568*7c478bd9Sstevel@tonic-gate filep = (fileid_t *)bkmem_alloc(sizeof (fileid_t)); 569*7c478bd9Sstevel@tonic-gate filep->fi_back = head->fi_back; 570*7c478bd9Sstevel@tonic-gate filep->fi_forw = head; 571*7c478bd9Sstevel@tonic-gate head->fi_back->fi_forw = filep; 572*7c478bd9Sstevel@tonic-gate head->fi_back = filep; 573*7c478bd9Sstevel@tonic-gate filep->fi_filedes = filedes++; 574*7c478bd9Sstevel@tonic-gate filep->fi_taken = 1; 575*7c478bd9Sstevel@tonic-gate filep->fi_path = (char *)bkmem_alloc(strlen(filename) + 1); 576*7c478bd9Sstevel@tonic-gate (void) strcpy(filep->fi_path, filename); 577*7c478bd9Sstevel@tonic-gate filep->fi_devp = ufs_devp; /* dev is already "mounted" */ 578*7c478bd9Sstevel@tonic-gate filep->fi_inode = NULL; 579*7c478bd9Sstevel@tonic-gate bzero(filep->fi_buf, MAXBSIZE); 580*7c478bd9Sstevel@tonic-gate 581*7c478bd9Sstevel@tonic-gate inode = find(filep, (char *)filename); 582*7c478bd9Sstevel@tonic-gate if (inode == (ino_t)0) { 583*7c478bd9Sstevel@tonic-gate dprintf("open: cannot find %s\n", filename); 584*7c478bd9Sstevel@tonic-gate (void) bufs_close(filep->fi_filedes); 585*7c478bd9Sstevel@tonic-gate return (-1); 586*7c478bd9Sstevel@tonic-gate } 587*7c478bd9Sstevel@tonic-gate if (openi(filep, inode)) { 588*7c478bd9Sstevel@tonic-gate printf("open: cannot open %s\n", filename); 589*7c478bd9Sstevel@tonic-gate (void) bufs_close(filep->fi_filedes); 590*7c478bd9Sstevel@tonic-gate return (-1); 591*7c478bd9Sstevel@tonic-gate } 592*7c478bd9Sstevel@tonic-gate 593*7c478bd9Sstevel@tonic-gate filep->fi_offset = filep->fi_count = 0; 594*7c478bd9Sstevel@tonic-gate 595*7c478bd9Sstevel@tonic-gate return (filep->fi_filedes); 596*7c478bd9Sstevel@tonic-gate } 597*7c478bd9Sstevel@tonic-gate 598*7c478bd9Sstevel@tonic-gate /* 599*7c478bd9Sstevel@tonic-gate * We don't do any IO here. 600*7c478bd9Sstevel@tonic-gate * We just play games with the device pointers. 601*7c478bd9Sstevel@tonic-gate */ 602*7c478bd9Sstevel@tonic-gate 603*7c478bd9Sstevel@tonic-gate static off_t 604*7c478bd9Sstevel@tonic-gate bufs_lseek(int fd, off_t addr, int whence) 605*7c478bd9Sstevel@tonic-gate { 606*7c478bd9Sstevel@tonic-gate fileid_t *filep; 607*7c478bd9Sstevel@tonic-gate 608*7c478bd9Sstevel@tonic-gate /* Make sure user knows what file he is talking to */ 609*7c478bd9Sstevel@tonic-gate if (!(filep = find_fp(fd))) 610*7c478bd9Sstevel@tonic-gate return (-1); 611*7c478bd9Sstevel@tonic-gate 612*7c478bd9Sstevel@tonic-gate switch (whence) { 613*7c478bd9Sstevel@tonic-gate case SEEK_CUR: 614*7c478bd9Sstevel@tonic-gate filep->fi_offset += addr; 615*7c478bd9Sstevel@tonic-gate break; 616*7c478bd9Sstevel@tonic-gate case SEEK_SET: 617*7c478bd9Sstevel@tonic-gate filep->fi_offset = addr; 618*7c478bd9Sstevel@tonic-gate break; 619*7c478bd9Sstevel@tonic-gate default: 620*7c478bd9Sstevel@tonic-gate case SEEK_END: 621*7c478bd9Sstevel@tonic-gate printf("lseek(): invalid whence value %d\n", whence); 622*7c478bd9Sstevel@tonic-gate break; 623*7c478bd9Sstevel@tonic-gate } 624*7c478bd9Sstevel@tonic-gate 625*7c478bd9Sstevel@tonic-gate filep->fi_blocknum = addr / DEV_BSIZE; 626*7c478bd9Sstevel@tonic-gate filep->fi_count = 0; 627*7c478bd9Sstevel@tonic-gate 628*7c478bd9Sstevel@tonic-gate return (0); 629*7c478bd9Sstevel@tonic-gate } 630*7c478bd9Sstevel@tonic-gate 631*7c478bd9Sstevel@tonic-gate static int 632*7c478bd9Sstevel@tonic-gate bufs_close(int fd) 633*7c478bd9Sstevel@tonic-gate { 634*7c478bd9Sstevel@tonic-gate fileid_t *filep; 635*7c478bd9Sstevel@tonic-gate 636*7c478bd9Sstevel@tonic-gate /* Make sure user knows what file he is talking to */ 637*7c478bd9Sstevel@tonic-gate if (!(filep = find_fp(fd))) 638*7c478bd9Sstevel@tonic-gate return (-1); 639*7c478bd9Sstevel@tonic-gate 640*7c478bd9Sstevel@tonic-gate if (filep->fi_taken && (filep != head)) { 641*7c478bd9Sstevel@tonic-gate /* Clear the ranks */ 642*7c478bd9Sstevel@tonic-gate bkmem_free(filep->fi_path, strlen(filep->fi_path)+1); 643*7c478bd9Sstevel@tonic-gate filep->fi_blocknum = filep->fi_count = filep->fi_offset = 0; 644*7c478bd9Sstevel@tonic-gate filep->fi_memp = (caddr_t)0; 645*7c478bd9Sstevel@tonic-gate filep->fi_devp = 0; 646*7c478bd9Sstevel@tonic-gate filep->fi_taken = 0; 647*7c478bd9Sstevel@tonic-gate 648*7c478bd9Sstevel@tonic-gate /* unlink and deallocate node */ 649*7c478bd9Sstevel@tonic-gate filep->fi_forw->fi_back = filep->fi_back; 650*7c478bd9Sstevel@tonic-gate filep->fi_back->fi_forw = filep->fi_forw; 651*7c478bd9Sstevel@tonic-gate bkmem_free((char *)filep, sizeof (fileid_t)); 652*7c478bd9Sstevel@tonic-gate 653*7c478bd9Sstevel@tonic-gate return (0); 654*7c478bd9Sstevel@tonic-gate } else { 655*7c478bd9Sstevel@tonic-gate /* Big problem */ 656*7c478bd9Sstevel@tonic-gate printf("\nFile descrip %d not allocated!", fd); 657*7c478bd9Sstevel@tonic-gate return (-1); 658*7c478bd9Sstevel@tonic-gate } 659*7c478bd9Sstevel@tonic-gate } 660*7c478bd9Sstevel@tonic-gate 661*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 662*7c478bd9Sstevel@tonic-gate static void 663*7c478bd9Sstevel@tonic-gate bufs_closeall(int flag) 664*7c478bd9Sstevel@tonic-gate { 665*7c478bd9Sstevel@tonic-gate fileid_t *filep = head; 666*7c478bd9Sstevel@tonic-gate 667*7c478bd9Sstevel@tonic-gate while ((filep = filep->fi_forw) != head) 668*7c478bd9Sstevel@tonic-gate if (filep->fi_taken) 669*7c478bd9Sstevel@tonic-gate if (bufs_close(filep->fi_filedes)) 670*7c478bd9Sstevel@tonic-gate printf("Filesystem may be inconsistent.\n"); 671*7c478bd9Sstevel@tonic-gate 672*7c478bd9Sstevel@tonic-gate ufs_devp->di_taken = 0; 673*7c478bd9Sstevel@tonic-gate bkmem_free((char *)ufs_devp, sizeof (devid_t)); 674*7c478bd9Sstevel@tonic-gate bkmem_free((char *)head, sizeof (fileid_t)); 675*7c478bd9Sstevel@tonic-gate ufs_devp = (devid_t *)NULL; 676*7c478bd9Sstevel@tonic-gate head = (fileid_t *)NULL; 677*7c478bd9Sstevel@tonic-gate free_cache(); 678*7c478bd9Sstevel@tonic-gate } 679*7c478bd9Sstevel@tonic-gate 680*7c478bd9Sstevel@tonic-gate static struct cache { 681*7c478bd9Sstevel@tonic-gate struct cache *next; 682*7c478bd9Sstevel@tonic-gate void *data; 683*7c478bd9Sstevel@tonic-gate int key; 684*7c478bd9Sstevel@tonic-gate uint_t size; 685*7c478bd9Sstevel@tonic-gate } *icache; 686*7c478bd9Sstevel@tonic-gate 687*7c478bd9Sstevel@tonic-gate void 688*7c478bd9Sstevel@tonic-gate set_cache(int key, void *data, uint_t size) 689*7c478bd9Sstevel@tonic-gate { 690*7c478bd9Sstevel@tonic-gate struct cache *entry = bkmem_alloc(sizeof (*entry)); 691*7c478bd9Sstevel@tonic-gate entry->key = key; 692*7c478bd9Sstevel@tonic-gate entry->data = data; 693*7c478bd9Sstevel@tonic-gate entry->size = size; 694*7c478bd9Sstevel@tonic-gate if (icache) { 695*7c478bd9Sstevel@tonic-gate entry->next = icache; 696*7c478bd9Sstevel@tonic-gate icache = entry; 697*7c478bd9Sstevel@tonic-gate } else { 698*7c478bd9Sstevel@tonic-gate icache = entry; 699*7c478bd9Sstevel@tonic-gate entry->next = 0; 700*7c478bd9Sstevel@tonic-gate } 701*7c478bd9Sstevel@tonic-gate } 702*7c478bd9Sstevel@tonic-gate 703*7c478bd9Sstevel@tonic-gate void * 704*7c478bd9Sstevel@tonic-gate get_cache(int key) 705*7c478bd9Sstevel@tonic-gate { 706*7c478bd9Sstevel@tonic-gate struct cache *entry = icache; 707*7c478bd9Sstevel@tonic-gate while (entry) { 708*7c478bd9Sstevel@tonic-gate if (entry->key == key) 709*7c478bd9Sstevel@tonic-gate return (entry->data); 710*7c478bd9Sstevel@tonic-gate entry = entry->next; 711*7c478bd9Sstevel@tonic-gate } 712*7c478bd9Sstevel@tonic-gate return (NULL); 713*7c478bd9Sstevel@tonic-gate } 714*7c478bd9Sstevel@tonic-gate 715*7c478bd9Sstevel@tonic-gate void 716*7c478bd9Sstevel@tonic-gate free_cache() 717*7c478bd9Sstevel@tonic-gate { 718*7c478bd9Sstevel@tonic-gate struct cache *next, *entry = icache; 719*7c478bd9Sstevel@tonic-gate while (entry) { 720*7c478bd9Sstevel@tonic-gate next = entry->next; 721*7c478bd9Sstevel@tonic-gate bkmem_free(entry->data, entry->size); 722*7c478bd9Sstevel@tonic-gate bkmem_free(entry, sizeof (*entry)); 723*7c478bd9Sstevel@tonic-gate entry = next; 724*7c478bd9Sstevel@tonic-gate } 725*7c478bd9Sstevel@tonic-gate icache = 0; 726*7c478bd9Sstevel@tonic-gate } 727*7c478bd9Sstevel@tonic-gate 728*7c478bd9Sstevel@tonic-gate struct boot_fs_ops bufs_ops = { 729*7c478bd9Sstevel@tonic-gate "boot_ufs", 730*7c478bd9Sstevel@tonic-gate bufs_mountroot, 731*7c478bd9Sstevel@tonic-gate bufs_unmountroot, 732*7c478bd9Sstevel@tonic-gate bufs_open, 733*7c478bd9Sstevel@tonic-gate bufs_close, 734*7c478bd9Sstevel@tonic-gate bufs_read, 735*7c478bd9Sstevel@tonic-gate bufs_lseek, 736*7c478bd9Sstevel@tonic-gate NULL 737*7c478bd9Sstevel@tonic-gate }; 738