1*63280Smckusick /*- 2*63280Smckusick * Copyright (c) 1993 The Regents of the University of California. 3*63280Smckusick * All rights reserved. 4*63280Smckusick * 5*63280Smckusick * This code is derived from software contributed to Berkeley by 6*63280Smckusick * The Mach Operating System project at Carnegie-Mellon University. 7*63280Smckusick * 8*63280Smckusick * %sccs.include.redist.c% 9*63280Smckusick * 10*63280Smckusick * @(#)ufs.c 7.1 (Berkeley) 06/11/93 11*63280Smckusick * 12*63280Smckusick * 13*63280Smckusick * Copyright (c) 1990, 1991 Carnegie Mellon University 14*63280Smckusick * All Rights Reserved. 15*63280Smckusick * 16*63280Smckusick * Author: David Golub 17*63280Smckusick * 18*63280Smckusick * Permission to use, copy, modify and distribute this software and its 19*63280Smckusick * documentation is hereby granted, provided that both the copyright 20*63280Smckusick * notice and this permission notice appear in all copies of the 21*63280Smckusick * software, derivative works or modified versions, and any portions 22*63280Smckusick * thereof, and that both notices appear in supporting documentation. 23*63280Smckusick * 24*63280Smckusick * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" 25*63280Smckusick * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR 26*63280Smckusick * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. 27*63280Smckusick * 28*63280Smckusick * Carnegie Mellon requests users of this software to return to 29*63280Smckusick * 30*63280Smckusick * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU 31*63280Smckusick * School of Computer Science 32*63280Smckusick * Carnegie Mellon University 33*63280Smckusick * Pittsburgh PA 15213-3890 34*63280Smckusick * 35*63280Smckusick * any improvements or extensions that they make and grant Carnegie the 36*63280Smckusick * rights to redistribute these changes. 37*63280Smckusick */ 38*63280Smckusick 39*63280Smckusick /* 40*63280Smckusick * Stand-alone file reading package. 41*63280Smckusick */ 42*63280Smckusick 43*63280Smckusick #include <sys/param.h> 44*63280Smckusick #include <sys/time.h> 45*63280Smckusick #include <ufs/ffs/fs.h> 46*63280Smckusick #include <ufs/ufs/dinode.h> 47*63280Smckusick #include <ufs/ufs/dir.h> 48*63280Smckusick #include <stand/stand.h> 49*63280Smckusick 50*63280Smckusick /* 51*63280Smckusick * In-core open file. 52*63280Smckusick */ 53*63280Smckusick struct file { 54*63280Smckusick off_t f_seekp; /* seek pointer */ 55*63280Smckusick struct fs *f_fs; /* pointer to super-block */ 56*63280Smckusick struct dinode f_di; /* copy of on-disk inode */ 57*63280Smckusick int f_nindir[NIADDR]; 58*63280Smckusick /* number of blocks mapped by 59*63280Smckusick indirect block at level i */ 60*63280Smckusick char *f_blk[NIADDR]; /* buffer for indirect block at 61*63280Smckusick level i */ 62*63280Smckusick u_long f_blksize[NIADDR]; 63*63280Smckusick /* size of buffer */ 64*63280Smckusick daddr_t f_blkno[NIADDR];/* disk address of block in buffer */ 65*63280Smckusick char *f_buf; /* buffer for data block */ 66*63280Smckusick u_int f_buf_size; /* size of data block */ 67*63280Smckusick daddr_t f_buf_blkno; /* block number of data block */ 68*63280Smckusick }; 69*63280Smckusick 70*63280Smckusick /* 71*63280Smckusick * Read a new inode into a file structure. 72*63280Smckusick */ 73*63280Smckusick static int 74*63280Smckusick read_inode(inumber, f) 75*63280Smckusick ino_t inumber; 76*63280Smckusick struct open_file *f; 77*63280Smckusick { 78*63280Smckusick register struct file *fp = (struct file *)f->f_fsdata; 79*63280Smckusick register struct fs *fs = fp->f_fs; 80*63280Smckusick char *buf; 81*63280Smckusick u_int rsize; 82*63280Smckusick int rc; 83*63280Smckusick 84*63280Smckusick /* 85*63280Smckusick * Read inode and save it. 86*63280Smckusick */ 87*63280Smckusick buf = alloc(fs->fs_bsize); 88*63280Smckusick rc = (f->f_dev->dv_strategy)(f->f_devdata, F_READ, 89*63280Smckusick fsbtodb(fs, itod(fs, inumber)), fs->fs_bsize, buf, &rsize); 90*63280Smckusick if (rc) 91*63280Smckusick goto out; 92*63280Smckusick if (rsize != fs->fs_bsize) { 93*63280Smckusick rc = EIO; 94*63280Smckusick goto out; 95*63280Smckusick } 96*63280Smckusick 97*63280Smckusick { 98*63280Smckusick register struct dinode *dp; 99*63280Smckusick 100*63280Smckusick dp = (struct dinode *)buf; 101*63280Smckusick fp->f_di = dp[itoo(fs, inumber)]; 102*63280Smckusick } 103*63280Smckusick 104*63280Smckusick /* 105*63280Smckusick * Clear out the old buffers 106*63280Smckusick */ 107*63280Smckusick { 108*63280Smckusick register int level; 109*63280Smckusick 110*63280Smckusick for (level = 0; level < NIADDR; level++) 111*63280Smckusick fp->f_blkno[level] = -1; 112*63280Smckusick fp->f_buf_blkno = -1; 113*63280Smckusick } 114*63280Smckusick out: 115*63280Smckusick free(buf, fs->fs_bsize); 116*63280Smckusick return (0); 117*63280Smckusick } 118*63280Smckusick 119*63280Smckusick /* 120*63280Smckusick * Given an offset in a file, find the disk block number that 121*63280Smckusick * contains that block. 122*63280Smckusick */ 123*63280Smckusick static int 124*63280Smckusick block_map(f, file_block, disk_block_p) 125*63280Smckusick struct open_file *f; 126*63280Smckusick daddr_t file_block; 127*63280Smckusick daddr_t *disk_block_p; /* out */ 128*63280Smckusick { 129*63280Smckusick register struct file *fp = (struct file *)f->f_fsdata; 130*63280Smckusick register struct fs *fs = fp->f_fs; 131*63280Smckusick int level; 132*63280Smckusick int idx; 133*63280Smckusick daddr_t ind_block_num; 134*63280Smckusick daddr_t *ind_p; 135*63280Smckusick int rc; 136*63280Smckusick 137*63280Smckusick /* 138*63280Smckusick * Index structure of an inode: 139*63280Smckusick * 140*63280Smckusick * di_db[0..NDADDR-1] hold block numbers for blocks 141*63280Smckusick * 0..NDADDR-1 142*63280Smckusick * 143*63280Smckusick * di_ib[0] index block 0 is the single indirect block 144*63280Smckusick * holds block numbers for blocks 145*63280Smckusick * NDADDR .. NDADDR + NINDIR(fs)-1 146*63280Smckusick * 147*63280Smckusick * di_ib[1] index block 1 is the double indirect block 148*63280Smckusick * holds block numbers for INDEX blocks for blocks 149*63280Smckusick * NDADDR + NINDIR(fs) .. 150*63280Smckusick * NDADDR + NINDIR(fs) + NINDIR(fs)**2 - 1 151*63280Smckusick * 152*63280Smckusick * di_ib[2] index block 2 is the triple indirect block 153*63280Smckusick * holds block numbers for double-indirect 154*63280Smckusick * blocks for blocks 155*63280Smckusick * NDADDR + NINDIR(fs) + NINDIR(fs)**2 .. 156*63280Smckusick * NDADDR + NINDIR(fs) + NINDIR(fs)**2 157*63280Smckusick * + NINDIR(fs)**3 - 1 158*63280Smckusick */ 159*63280Smckusick 160*63280Smckusick if (file_block < NDADDR) { 161*63280Smckusick /* Direct block. */ 162*63280Smckusick *disk_block_p = fp->f_di.di_db[file_block]; 163*63280Smckusick return (0); 164*63280Smckusick } 165*63280Smckusick 166*63280Smckusick file_block -= NDADDR; 167*63280Smckusick 168*63280Smckusick /* 169*63280Smckusick * nindir[0] = NINDIR 170*63280Smckusick * nindir[1] = NINDIR**2 171*63280Smckusick * nindir[2] = NINDIR**3 172*63280Smckusick * etc 173*63280Smckusick */ 174*63280Smckusick for (level = 0; level < NIADDR; level++) { 175*63280Smckusick if (file_block < fp->f_nindir[level]) 176*63280Smckusick break; 177*63280Smckusick file_block -= fp->f_nindir[level]; 178*63280Smckusick } 179*63280Smckusick if (level == NIADDR) { 180*63280Smckusick /* Block number too high */ 181*63280Smckusick return (EFBIG); 182*63280Smckusick } 183*63280Smckusick 184*63280Smckusick ind_block_num = fp->f_di.di_ib[level]; 185*63280Smckusick 186*63280Smckusick for (; level >= 0; level--) { 187*63280Smckusick if (ind_block_num == 0) { 188*63280Smckusick *disk_block_p = 0; /* missing */ 189*63280Smckusick return (0); 190*63280Smckusick } 191*63280Smckusick 192*63280Smckusick if (fp->f_blkno[level] != ind_block_num) { 193*63280Smckusick if (fp->f_blk[level] == (char *)0) 194*63280Smckusick fp->f_blk[level] = 195*63280Smckusick alloc(fs->fs_bsize); 196*63280Smckusick rc = (f->f_dev->dv_strategy)(f->f_devdata, F_READ, 197*63280Smckusick fsbtodb(fp->f_fs, ind_block_num), 198*63280Smckusick fs->fs_bsize, 199*63280Smckusick fp->f_blk[level], 200*63280Smckusick &fp->f_blksize[level]); 201*63280Smckusick if (rc) 202*63280Smckusick return (rc); 203*63280Smckusick if (fp->f_blksize[level] != fs->fs_bsize) 204*63280Smckusick return (EIO); 205*63280Smckusick fp->f_blkno[level] = ind_block_num; 206*63280Smckusick } 207*63280Smckusick 208*63280Smckusick ind_p = (daddr_t *)fp->f_blk[level]; 209*63280Smckusick 210*63280Smckusick if (level > 0) { 211*63280Smckusick idx = file_block / fp->f_nindir[level - 1]; 212*63280Smckusick file_block %= fp->f_nindir[level - 1]; 213*63280Smckusick } else 214*63280Smckusick idx = file_block; 215*63280Smckusick 216*63280Smckusick ind_block_num = ind_p[idx]; 217*63280Smckusick } 218*63280Smckusick 219*63280Smckusick *disk_block_p = ind_block_num; 220*63280Smckusick 221*63280Smckusick return (0); 222*63280Smckusick } 223*63280Smckusick 224*63280Smckusick /* 225*63280Smckusick * Read a portion of a file into an internal buffer. Return 226*63280Smckusick * the location in the buffer and the amount in the buffer. 227*63280Smckusick */ 228*63280Smckusick static int 229*63280Smckusick buf_read_file(f, buf_p, size_p) 230*63280Smckusick struct open_file *f; 231*63280Smckusick char **buf_p; /* out */ 232*63280Smckusick u_int *size_p; /* out */ 233*63280Smckusick { 234*63280Smckusick register struct file *fp = (struct file *)f->f_fsdata; 235*63280Smckusick register struct fs *fs = fp->f_fs; 236*63280Smckusick long off; 237*63280Smckusick register daddr_t file_block; 238*63280Smckusick daddr_t disk_block; 239*63280Smckusick long block_size; 240*63280Smckusick int rc; 241*63280Smckusick 242*63280Smckusick off = blkoff(fs, fp->f_seekp); 243*63280Smckusick file_block = lblkno(fs, fp->f_seekp); 244*63280Smckusick block_size = dblksize(fs, &fp->f_di, file_block); 245*63280Smckusick 246*63280Smckusick if (file_block != fp->f_buf_blkno) { 247*63280Smckusick rc = block_map(f, file_block, &disk_block); 248*63280Smckusick if (rc) 249*63280Smckusick return (rc); 250*63280Smckusick 251*63280Smckusick if (fp->f_buf == (char *)0) 252*63280Smckusick fp->f_buf = alloc(fs->fs_bsize); 253*63280Smckusick 254*63280Smckusick if (disk_block == 0) { 255*63280Smckusick bzero(fp->f_buf, block_size); 256*63280Smckusick fp->f_buf_size = block_size; 257*63280Smckusick } else { 258*63280Smckusick rc = (f->f_dev->dv_strategy)(f->f_devdata, F_READ, 259*63280Smckusick fsbtodb(fs, disk_block), 260*63280Smckusick block_size, fp->f_buf, &fp->f_buf_size); 261*63280Smckusick if (rc) 262*63280Smckusick return (rc); 263*63280Smckusick } 264*63280Smckusick 265*63280Smckusick fp->f_buf_blkno = file_block; 266*63280Smckusick } 267*63280Smckusick 268*63280Smckusick /* 269*63280Smckusick * Return address of byte in buffer corresponding to 270*63280Smckusick * offset, and size of remainder of buffer after that 271*63280Smckusick * byte. 272*63280Smckusick */ 273*63280Smckusick *buf_p = fp->f_buf + off; 274*63280Smckusick *size_p = block_size - off; 275*63280Smckusick 276*63280Smckusick /* 277*63280Smckusick * But truncate buffer at end of file. 278*63280Smckusick */ 279*63280Smckusick if (*size_p > fp->f_di.di_size - fp->f_seekp) 280*63280Smckusick *size_p = fp->f_di.di_size - fp->f_seekp; 281*63280Smckusick 282*63280Smckusick return (0); 283*63280Smckusick } 284*63280Smckusick 285*63280Smckusick /* 286*63280Smckusick * Search a directory for a name and return its 287*63280Smckusick * i_number. 288*63280Smckusick */ 289*63280Smckusick static int 290*63280Smckusick search_directory(name, f, inumber_p) 291*63280Smckusick char *name; 292*63280Smckusick struct open_file *f; 293*63280Smckusick ino_t *inumber_p; /* out */ 294*63280Smckusick { 295*63280Smckusick register struct file *fp = (struct file *)f->f_fsdata; 296*63280Smckusick register struct direct *dp; 297*63280Smckusick struct direct *edp; 298*63280Smckusick char *buf; 299*63280Smckusick u_int buf_size; 300*63280Smckusick int namlen, length; 301*63280Smckusick int rc; 302*63280Smckusick 303*63280Smckusick length = strlen(name); 304*63280Smckusick 305*63280Smckusick fp->f_seekp = 0; 306*63280Smckusick while (fp->f_seekp < fp->f_di.di_size) { 307*63280Smckusick rc = buf_read_file(f, &buf, &buf_size); 308*63280Smckusick if (rc) 309*63280Smckusick return (rc); 310*63280Smckusick 311*63280Smckusick dp = (struct direct *)buf; 312*63280Smckusick edp = (struct direct *)(buf + buf_size); 313*63280Smckusick while (dp < edp) { 314*63280Smckusick if (dp->d_ino == (ino_t)0) 315*63280Smckusick goto next; 316*63280Smckusick #if BYTE_ORDER == LITTLE_ENDIAN 317*63280Smckusick if (fp->f_fs->fs_maxsymlinklen <= 0) 318*63280Smckusick namlen = dp->d_type; 319*63280Smckusick else 320*63280Smckusick #endif 321*63280Smckusick namlen = dp->d_namlen; 322*63280Smckusick if (namlen == length && 323*63280Smckusick !strcmp(name, dp->d_name)) { 324*63280Smckusick /* found entry */ 325*63280Smckusick *inumber_p = dp->d_ino; 326*63280Smckusick return (0); 327*63280Smckusick } 328*63280Smckusick next: 329*63280Smckusick dp = (struct direct *)((char *)dp + dp->d_reclen); 330*63280Smckusick } 331*63280Smckusick fp->f_seekp += buf_size; 332*63280Smckusick } 333*63280Smckusick return (ENOENT); 334*63280Smckusick } 335*63280Smckusick 336*63280Smckusick /* 337*63280Smckusick * Open a file. 338*63280Smckusick */ 339*63280Smckusick int 340*63280Smckusick ufs_open(path, f) 341*63280Smckusick char *path; 342*63280Smckusick struct open_file *f; 343*63280Smckusick { 344*63280Smckusick register char *cp, *ncp; 345*63280Smckusick register int c; 346*63280Smckusick ino_t inumber, parent_inumber; 347*63280Smckusick int nlinks = 0; 348*63280Smckusick struct file *fp; 349*63280Smckusick struct fs *fs; 350*63280Smckusick int rc; 351*63280Smckusick u_int buf_size; 352*63280Smckusick #if 0 353*63280Smckusick char namebuf[MAXPATHLEN+1]; 354*63280Smckusick #endif 355*63280Smckusick 356*63280Smckusick /* allocate file system specific data structure */ 357*63280Smckusick fp = alloc(sizeof(struct file)); 358*63280Smckusick bzero(fp, sizeof(struct file)); 359*63280Smckusick f->f_fsdata = (void *)fp; 360*63280Smckusick 361*63280Smckusick /* allocate space and read super block */ 362*63280Smckusick fs = alloc(SBSIZE); 363*63280Smckusick fp->f_fs = fs; 364*63280Smckusick rc = (f->f_dev->dv_strategy)(f->f_devdata, F_READ, 365*63280Smckusick SBLOCK, SBSIZE, (char *)fs, &buf_size); 366*63280Smckusick if (rc) 367*63280Smckusick goto out; 368*63280Smckusick 369*63280Smckusick if (buf_size != SBSIZE || fs->fs_magic != FS_MAGIC || 370*63280Smckusick fs->fs_bsize > MAXBSIZE || fs->fs_bsize < sizeof(struct fs)) { 371*63280Smckusick rc = EINVAL; 372*63280Smckusick goto out; 373*63280Smckusick } 374*63280Smckusick 375*63280Smckusick /* 376*63280Smckusick * Calculate indirect block levels. 377*63280Smckusick */ 378*63280Smckusick { 379*63280Smckusick register int mult; 380*63280Smckusick register int level; 381*63280Smckusick 382*63280Smckusick mult = 1; 383*63280Smckusick for (level = 0; level < NIADDR; level++) { 384*63280Smckusick mult *= NINDIR(fs); 385*63280Smckusick fp->f_nindir[level] = mult; 386*63280Smckusick } 387*63280Smckusick } 388*63280Smckusick 389*63280Smckusick inumber = ROOTINO; 390*63280Smckusick if ((rc = read_inode(inumber, f)) != 0) 391*63280Smckusick goto out; 392*63280Smckusick 393*63280Smckusick cp = path; 394*63280Smckusick while (*cp) { 395*63280Smckusick 396*63280Smckusick /* 397*63280Smckusick * Remove extra separators 398*63280Smckusick */ 399*63280Smckusick while (*cp == '/') 400*63280Smckusick cp++; 401*63280Smckusick if (*cp == '\0') 402*63280Smckusick break; 403*63280Smckusick 404*63280Smckusick /* 405*63280Smckusick * Check that current node is a directory. 406*63280Smckusick */ 407*63280Smckusick if ((fp->f_di.di_mode & IFMT) != IFDIR) { 408*63280Smckusick rc = ENOTDIR; 409*63280Smckusick goto out; 410*63280Smckusick } 411*63280Smckusick 412*63280Smckusick /* 413*63280Smckusick * Get next component of path name. 414*63280Smckusick */ 415*63280Smckusick { 416*63280Smckusick register int len = 0; 417*63280Smckusick 418*63280Smckusick ncp = cp; 419*63280Smckusick while ((c = *cp) != '\0' && c != '/') { 420*63280Smckusick if (++len > MAXNAMLEN) { 421*63280Smckusick rc = ENOENT; 422*63280Smckusick goto out; 423*63280Smckusick } 424*63280Smckusick cp++; 425*63280Smckusick } 426*63280Smckusick *cp = '\0'; 427*63280Smckusick } 428*63280Smckusick 429*63280Smckusick /* 430*63280Smckusick * Look up component in current directory. 431*63280Smckusick * Save directory inumber in case we find a 432*63280Smckusick * symbolic link. 433*63280Smckusick */ 434*63280Smckusick parent_inumber = inumber; 435*63280Smckusick rc = search_directory(ncp, f, &inumber); 436*63280Smckusick *cp = c; 437*63280Smckusick if (rc) 438*63280Smckusick goto out; 439*63280Smckusick 440*63280Smckusick /* 441*63280Smckusick * Open next component. 442*63280Smckusick */ 443*63280Smckusick if ((rc = read_inode(inumber, f)) != 0) 444*63280Smckusick goto out; 445*63280Smckusick 446*63280Smckusick #if 0 447*63280Smckusick /* 448*63280Smckusick * Check for symbolic link. 449*63280Smckusick */ 450*63280Smckusick if ((fp->i_mode & IFMT) == IFLNK) { 451*63280Smckusick int link_len = fp->f_di.di_size; 452*63280Smckusick int len; 453*63280Smckusick 454*63280Smckusick len = strlen(cp) + 1; 455*63280Smckusick 456*63280Smckusick if (fp->f_di.di_size >= MAXPATHLEN - 1 || 457*63280Smckusick ++nlinks > MAXSYMLINKS) { 458*63280Smckusick rc = ENOENT; 459*63280Smckusick goto out; 460*63280Smckusick } 461*63280Smckusick 462*63280Smckusick strcpy(&namebuf[link_len], cp); 463*63280Smckusick 464*63280Smckusick if ((fp->i_flags & IC_FASTLINK) != 0) { 465*63280Smckusick bcopy(fp->i_symlink, namebuf, (unsigned) link_len); 466*63280Smckusick } else { 467*63280Smckusick /* 468*63280Smckusick * Read file for symbolic link 469*63280Smckusick */ 470*63280Smckusick char *buf; 471*63280Smckusick u_int buf_size; 472*63280Smckusick daddr_t disk_block; 473*63280Smckusick register struct fs *fs = fp->f_fs; 474*63280Smckusick 475*63280Smckusick (void) block_map(f, (daddr_t)0, &disk_block); 476*63280Smckusick rc = device_read(&fp->f_dev, 477*63280Smckusick fsbtodb(fs, disk_block), 478*63280Smckusick blksize(fs, fp, 0), 479*63280Smckusick &buf, &buf_size); 480*63280Smckusick if (rc) 481*63280Smckusick goto out; 482*63280Smckusick 483*63280Smckusick bcopy((char *)buf, namebuf, (unsigned)link_len); 484*63280Smckusick free(buf, buf_size); 485*63280Smckusick } 486*63280Smckusick 487*63280Smckusick /* 488*63280Smckusick * If relative pathname, restart at parent directory. 489*63280Smckusick * If absolute pathname, restart at root. 490*63280Smckusick */ 491*63280Smckusick cp = namebuf; 492*63280Smckusick if (*cp != '/') 493*63280Smckusick inumber = parent_inumber; 494*63280Smckusick else 495*63280Smckusick inumber = (ino_t)ROOTINO; 496*63280Smckusick 497*63280Smckusick if ((rc = read_inode(inumber, fp)) != 0) 498*63280Smckusick goto out; 499*63280Smckusick } 500*63280Smckusick #endif 501*63280Smckusick } 502*63280Smckusick 503*63280Smckusick /* 504*63280Smckusick * Found terminal component. 505*63280Smckusick */ 506*63280Smckusick rc = 0; 507*63280Smckusick out: 508*63280Smckusick if (rc) 509*63280Smckusick free(fp, sizeof(struct file)); 510*63280Smckusick return (rc); 511*63280Smckusick } 512*63280Smckusick 513*63280Smckusick int 514*63280Smckusick ufs_close(f) 515*63280Smckusick struct open_file *f; 516*63280Smckusick { 517*63280Smckusick register struct file *fp = (struct file *)f->f_fsdata; 518*63280Smckusick int level; 519*63280Smckusick 520*63280Smckusick f->f_fsdata = (void *)0; 521*63280Smckusick if (fp == (struct file *)0) 522*63280Smckusick return (0); 523*63280Smckusick 524*63280Smckusick for (level = 0; level < NIADDR; level++) { 525*63280Smckusick if (fp->f_blk[level]) 526*63280Smckusick free(fp->f_blk[level], fp->f_fs->fs_bsize); 527*63280Smckusick } 528*63280Smckusick if (fp->f_buf) 529*63280Smckusick free(fp->f_buf, fp->f_fs->fs_bsize); 530*63280Smckusick free(fp->f_fs, SBSIZE); 531*63280Smckusick free(fp, sizeof(struct file)); 532*63280Smckusick return (0); 533*63280Smckusick } 534*63280Smckusick 535*63280Smckusick /* 536*63280Smckusick * Copy a portion of a file into kernel memory. 537*63280Smckusick * Cross block boundaries when necessary. 538*63280Smckusick */ 539*63280Smckusick int 540*63280Smckusick ufs_read(f, start, size, resid) 541*63280Smckusick struct open_file *f; 542*63280Smckusick char *start; 543*63280Smckusick u_int size; 544*63280Smckusick u_int *resid; /* out */ 545*63280Smckusick { 546*63280Smckusick register struct file *fp = (struct file *)f->f_fsdata; 547*63280Smckusick register u_int csize; 548*63280Smckusick char *buf; 549*63280Smckusick u_int buf_size; 550*63280Smckusick int rc = 0; 551*63280Smckusick 552*63280Smckusick while (size != 0) { 553*63280Smckusick if (fp->f_seekp >= fp->f_di.di_size) 554*63280Smckusick break; 555*63280Smckusick 556*63280Smckusick rc = buf_read_file(f, &buf, &buf_size); 557*63280Smckusick if (rc) 558*63280Smckusick break; 559*63280Smckusick 560*63280Smckusick csize = size; 561*63280Smckusick if (csize > buf_size) 562*63280Smckusick csize = buf_size; 563*63280Smckusick 564*63280Smckusick bcopy(buf, start, csize); 565*63280Smckusick 566*63280Smckusick fp->f_seekp += csize; 567*63280Smckusick start += csize; 568*63280Smckusick size -= csize; 569*63280Smckusick } 570*63280Smckusick if (resid) 571*63280Smckusick *resid = size; 572*63280Smckusick return (rc); 573*63280Smckusick } 574*63280Smckusick 575*63280Smckusick /* 576*63280Smckusick * Not implemented. 577*63280Smckusick */ 578*63280Smckusick int 579*63280Smckusick ufs_write(f, start, size, resid) 580*63280Smckusick struct open_file *f; 581*63280Smckusick char *start; 582*63280Smckusick u_int size; 583*63280Smckusick u_int *resid; /* out */ 584*63280Smckusick { 585*63280Smckusick 586*63280Smckusick return (EROFS); 587*63280Smckusick } 588*63280Smckusick 589*63280Smckusick off_t 590*63280Smckusick ufs_seek(f, offset, where) 591*63280Smckusick struct open_file *f; 592*63280Smckusick off_t offset; 593*63280Smckusick int where; 594*63280Smckusick { 595*63280Smckusick register struct file *fp = (struct file *)f->f_fsdata; 596*63280Smckusick 597*63280Smckusick switch (where) { 598*63280Smckusick case SEEK_SET: 599*63280Smckusick fp->f_seekp = offset; 600*63280Smckusick break; 601*63280Smckusick case SEEK_CUR: 602*63280Smckusick fp->f_seekp += offset; 603*63280Smckusick break; 604*63280Smckusick case SEEK_END: 605*63280Smckusick fp->f_seekp = fp->f_di.di_size - offset; 606*63280Smckusick break; 607*63280Smckusick default: 608*63280Smckusick return (-1); 609*63280Smckusick } 610*63280Smckusick return (fp->f_seekp); 611*63280Smckusick } 612*63280Smckusick 613*63280Smckusick int 614*63280Smckusick ufs_stat(f, sb) 615*63280Smckusick struct open_file *f; 616*63280Smckusick struct stat *sb; 617*63280Smckusick { 618*63280Smckusick register struct file *fp = (struct file *)f->f_fsdata; 619*63280Smckusick 620*63280Smckusick /* only important stuff */ 621*63280Smckusick sb->st_mode = fp->f_di.di_mode; 622*63280Smckusick sb->st_uid = fp->f_di.di_uid; 623*63280Smckusick sb->st_gid = fp->f_di.di_gid; 624*63280Smckusick sb->st_size = fp->f_di.di_size; 625*63280Smckusick return (0); 626*63280Smckusick } 627