163280Smckusick /*- 2*63370Sbostic * Copyright (c) 1993 3*63370Sbostic * The Regents of the University of California. All rights reserved. 463280Smckusick * 563280Smckusick * This code is derived from software contributed to Berkeley by 663280Smckusick * The Mach Operating System project at Carnegie-Mellon University. 763280Smckusick * 863280Smckusick * %sccs.include.redist.c% 963280Smckusick * 10*63370Sbostic * @(#)ufs.c 8.1 (Berkeley) 06/11/93 1163280Smckusick * 1263280Smckusick * 1363280Smckusick * Copyright (c) 1990, 1991 Carnegie Mellon University 1463280Smckusick * All Rights Reserved. 1563280Smckusick * 1663280Smckusick * Author: David Golub 1763280Smckusick * 1863280Smckusick * Permission to use, copy, modify and distribute this software and its 1963280Smckusick * documentation is hereby granted, provided that both the copyright 2063280Smckusick * notice and this permission notice appear in all copies of the 2163280Smckusick * software, derivative works or modified versions, and any portions 2263280Smckusick * thereof, and that both notices appear in supporting documentation. 2363280Smckusick * 2463280Smckusick * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" 2563280Smckusick * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR 2663280Smckusick * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. 2763280Smckusick * 2863280Smckusick * Carnegie Mellon requests users of this software to return to 2963280Smckusick * 3063280Smckusick * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU 3163280Smckusick * School of Computer Science 3263280Smckusick * Carnegie Mellon University 3363280Smckusick * Pittsburgh PA 15213-3890 3463280Smckusick * 3563280Smckusick * any improvements or extensions that they make and grant Carnegie the 3663280Smckusick * rights to redistribute these changes. 3763280Smckusick */ 3863280Smckusick 3963280Smckusick /* 4063280Smckusick * Stand-alone file reading package. 4163280Smckusick */ 4263280Smckusick 4363280Smckusick #include <sys/param.h> 4463280Smckusick #include <sys/time.h> 4563280Smckusick #include <ufs/ffs/fs.h> 4663280Smckusick #include <ufs/ufs/dinode.h> 4763280Smckusick #include <ufs/ufs/dir.h> 4863280Smckusick #include <stand/stand.h> 4963280Smckusick 5063280Smckusick /* 5163280Smckusick * In-core open file. 5263280Smckusick */ 5363280Smckusick struct file { 5463280Smckusick off_t f_seekp; /* seek pointer */ 5563280Smckusick struct fs *f_fs; /* pointer to super-block */ 5663280Smckusick struct dinode f_di; /* copy of on-disk inode */ 5763280Smckusick int f_nindir[NIADDR]; 5863280Smckusick /* number of blocks mapped by 5963280Smckusick indirect block at level i */ 6063280Smckusick char *f_blk[NIADDR]; /* buffer for indirect block at 6163280Smckusick level i */ 6263280Smckusick u_long f_blksize[NIADDR]; 6363280Smckusick /* size of buffer */ 6463280Smckusick daddr_t f_blkno[NIADDR];/* disk address of block in buffer */ 6563280Smckusick char *f_buf; /* buffer for data block */ 6663280Smckusick u_int f_buf_size; /* size of data block */ 6763280Smckusick daddr_t f_buf_blkno; /* block number of data block */ 6863280Smckusick }; 6963280Smckusick 7063280Smckusick /* 7163280Smckusick * Read a new inode into a file structure. 7263280Smckusick */ 7363280Smckusick static int 7463280Smckusick read_inode(inumber, f) 7563280Smckusick ino_t inumber; 7663280Smckusick struct open_file *f; 7763280Smckusick { 7863280Smckusick register struct file *fp = (struct file *)f->f_fsdata; 7963280Smckusick register struct fs *fs = fp->f_fs; 8063280Smckusick char *buf; 8163280Smckusick u_int rsize; 8263280Smckusick int rc; 8363280Smckusick 8463280Smckusick /* 8563280Smckusick * Read inode and save it. 8663280Smckusick */ 8763280Smckusick buf = alloc(fs->fs_bsize); 8863280Smckusick rc = (f->f_dev->dv_strategy)(f->f_devdata, F_READ, 8963280Smckusick fsbtodb(fs, itod(fs, inumber)), fs->fs_bsize, buf, &rsize); 9063280Smckusick if (rc) 9163280Smckusick goto out; 9263280Smckusick if (rsize != fs->fs_bsize) { 9363280Smckusick rc = EIO; 9463280Smckusick goto out; 9563280Smckusick } 9663280Smckusick 9763280Smckusick { 9863280Smckusick register struct dinode *dp; 9963280Smckusick 10063280Smckusick dp = (struct dinode *)buf; 10163280Smckusick fp->f_di = dp[itoo(fs, inumber)]; 10263280Smckusick } 10363280Smckusick 10463280Smckusick /* 10563280Smckusick * Clear out the old buffers 10663280Smckusick */ 10763280Smckusick { 10863280Smckusick register int level; 10963280Smckusick 11063280Smckusick for (level = 0; level < NIADDR; level++) 11163280Smckusick fp->f_blkno[level] = -1; 11263280Smckusick fp->f_buf_blkno = -1; 11363280Smckusick } 11463280Smckusick out: 11563280Smckusick free(buf, fs->fs_bsize); 11663280Smckusick return (0); 11763280Smckusick } 11863280Smckusick 11963280Smckusick /* 12063280Smckusick * Given an offset in a file, find the disk block number that 12163280Smckusick * contains that block. 12263280Smckusick */ 12363280Smckusick static int 12463280Smckusick block_map(f, file_block, disk_block_p) 12563280Smckusick struct open_file *f; 12663280Smckusick daddr_t file_block; 12763280Smckusick daddr_t *disk_block_p; /* out */ 12863280Smckusick { 12963280Smckusick register struct file *fp = (struct file *)f->f_fsdata; 13063280Smckusick register struct fs *fs = fp->f_fs; 13163280Smckusick int level; 13263280Smckusick int idx; 13363280Smckusick daddr_t ind_block_num; 13463280Smckusick daddr_t *ind_p; 13563280Smckusick int rc; 13663280Smckusick 13763280Smckusick /* 13863280Smckusick * Index structure of an inode: 13963280Smckusick * 14063280Smckusick * di_db[0..NDADDR-1] hold block numbers for blocks 14163280Smckusick * 0..NDADDR-1 14263280Smckusick * 14363280Smckusick * di_ib[0] index block 0 is the single indirect block 14463280Smckusick * holds block numbers for blocks 14563280Smckusick * NDADDR .. NDADDR + NINDIR(fs)-1 14663280Smckusick * 14763280Smckusick * di_ib[1] index block 1 is the double indirect block 14863280Smckusick * holds block numbers for INDEX blocks for blocks 14963280Smckusick * NDADDR + NINDIR(fs) .. 15063280Smckusick * NDADDR + NINDIR(fs) + NINDIR(fs)**2 - 1 15163280Smckusick * 15263280Smckusick * di_ib[2] index block 2 is the triple indirect block 15363280Smckusick * holds block numbers for double-indirect 15463280Smckusick * blocks for blocks 15563280Smckusick * NDADDR + NINDIR(fs) + NINDIR(fs)**2 .. 15663280Smckusick * NDADDR + NINDIR(fs) + NINDIR(fs)**2 15763280Smckusick * + NINDIR(fs)**3 - 1 15863280Smckusick */ 15963280Smckusick 16063280Smckusick if (file_block < NDADDR) { 16163280Smckusick /* Direct block. */ 16263280Smckusick *disk_block_p = fp->f_di.di_db[file_block]; 16363280Smckusick return (0); 16463280Smckusick } 16563280Smckusick 16663280Smckusick file_block -= NDADDR; 16763280Smckusick 16863280Smckusick /* 16963280Smckusick * nindir[0] = NINDIR 17063280Smckusick * nindir[1] = NINDIR**2 17163280Smckusick * nindir[2] = NINDIR**3 17263280Smckusick * etc 17363280Smckusick */ 17463280Smckusick for (level = 0; level < NIADDR; level++) { 17563280Smckusick if (file_block < fp->f_nindir[level]) 17663280Smckusick break; 17763280Smckusick file_block -= fp->f_nindir[level]; 17863280Smckusick } 17963280Smckusick if (level == NIADDR) { 18063280Smckusick /* Block number too high */ 18163280Smckusick return (EFBIG); 18263280Smckusick } 18363280Smckusick 18463280Smckusick ind_block_num = fp->f_di.di_ib[level]; 18563280Smckusick 18663280Smckusick for (; level >= 0; level--) { 18763280Smckusick if (ind_block_num == 0) { 18863280Smckusick *disk_block_p = 0; /* missing */ 18963280Smckusick return (0); 19063280Smckusick } 19163280Smckusick 19263280Smckusick if (fp->f_blkno[level] != ind_block_num) { 19363280Smckusick if (fp->f_blk[level] == (char *)0) 19463280Smckusick fp->f_blk[level] = 19563280Smckusick alloc(fs->fs_bsize); 19663280Smckusick rc = (f->f_dev->dv_strategy)(f->f_devdata, F_READ, 19763280Smckusick fsbtodb(fp->f_fs, ind_block_num), 19863280Smckusick fs->fs_bsize, 19963280Smckusick fp->f_blk[level], 20063280Smckusick &fp->f_blksize[level]); 20163280Smckusick if (rc) 20263280Smckusick return (rc); 20363280Smckusick if (fp->f_blksize[level] != fs->fs_bsize) 20463280Smckusick return (EIO); 20563280Smckusick fp->f_blkno[level] = ind_block_num; 20663280Smckusick } 20763280Smckusick 20863280Smckusick ind_p = (daddr_t *)fp->f_blk[level]; 20963280Smckusick 21063280Smckusick if (level > 0) { 21163280Smckusick idx = file_block / fp->f_nindir[level - 1]; 21263280Smckusick file_block %= fp->f_nindir[level - 1]; 21363280Smckusick } else 21463280Smckusick idx = file_block; 21563280Smckusick 21663280Smckusick ind_block_num = ind_p[idx]; 21763280Smckusick } 21863280Smckusick 21963280Smckusick *disk_block_p = ind_block_num; 22063280Smckusick 22163280Smckusick return (0); 22263280Smckusick } 22363280Smckusick 22463280Smckusick /* 22563280Smckusick * Read a portion of a file into an internal buffer. Return 22663280Smckusick * the location in the buffer and the amount in the buffer. 22763280Smckusick */ 22863280Smckusick static int 22963280Smckusick buf_read_file(f, buf_p, size_p) 23063280Smckusick struct open_file *f; 23163280Smckusick char **buf_p; /* out */ 23263280Smckusick u_int *size_p; /* out */ 23363280Smckusick { 23463280Smckusick register struct file *fp = (struct file *)f->f_fsdata; 23563280Smckusick register struct fs *fs = fp->f_fs; 23663280Smckusick long off; 23763280Smckusick register daddr_t file_block; 23863280Smckusick daddr_t disk_block; 23963280Smckusick long block_size; 24063280Smckusick int rc; 24163280Smckusick 24263280Smckusick off = blkoff(fs, fp->f_seekp); 24363280Smckusick file_block = lblkno(fs, fp->f_seekp); 24463280Smckusick block_size = dblksize(fs, &fp->f_di, file_block); 24563280Smckusick 24663280Smckusick if (file_block != fp->f_buf_blkno) { 24763280Smckusick rc = block_map(f, file_block, &disk_block); 24863280Smckusick if (rc) 24963280Smckusick return (rc); 25063280Smckusick 25163280Smckusick if (fp->f_buf == (char *)0) 25263280Smckusick fp->f_buf = alloc(fs->fs_bsize); 25363280Smckusick 25463280Smckusick if (disk_block == 0) { 25563280Smckusick bzero(fp->f_buf, block_size); 25663280Smckusick fp->f_buf_size = block_size; 25763280Smckusick } else { 25863280Smckusick rc = (f->f_dev->dv_strategy)(f->f_devdata, F_READ, 25963280Smckusick fsbtodb(fs, disk_block), 26063280Smckusick block_size, fp->f_buf, &fp->f_buf_size); 26163280Smckusick if (rc) 26263280Smckusick return (rc); 26363280Smckusick } 26463280Smckusick 26563280Smckusick fp->f_buf_blkno = file_block; 26663280Smckusick } 26763280Smckusick 26863280Smckusick /* 26963280Smckusick * Return address of byte in buffer corresponding to 27063280Smckusick * offset, and size of remainder of buffer after that 27163280Smckusick * byte. 27263280Smckusick */ 27363280Smckusick *buf_p = fp->f_buf + off; 27463280Smckusick *size_p = block_size - off; 27563280Smckusick 27663280Smckusick /* 27763280Smckusick * But truncate buffer at end of file. 27863280Smckusick */ 27963280Smckusick if (*size_p > fp->f_di.di_size - fp->f_seekp) 28063280Smckusick *size_p = fp->f_di.di_size - fp->f_seekp; 28163280Smckusick 28263280Smckusick return (0); 28363280Smckusick } 28463280Smckusick 28563280Smckusick /* 28663280Smckusick * Search a directory for a name and return its 28763280Smckusick * i_number. 28863280Smckusick */ 28963280Smckusick static int 29063280Smckusick search_directory(name, f, inumber_p) 29163280Smckusick char *name; 29263280Smckusick struct open_file *f; 29363280Smckusick ino_t *inumber_p; /* out */ 29463280Smckusick { 29563280Smckusick register struct file *fp = (struct file *)f->f_fsdata; 29663280Smckusick register struct direct *dp; 29763280Smckusick struct direct *edp; 29863280Smckusick char *buf; 29963280Smckusick u_int buf_size; 30063280Smckusick int namlen, length; 30163280Smckusick int rc; 30263280Smckusick 30363280Smckusick length = strlen(name); 30463280Smckusick 30563280Smckusick fp->f_seekp = 0; 30663280Smckusick while (fp->f_seekp < fp->f_di.di_size) { 30763280Smckusick rc = buf_read_file(f, &buf, &buf_size); 30863280Smckusick if (rc) 30963280Smckusick return (rc); 31063280Smckusick 31163280Smckusick dp = (struct direct *)buf; 31263280Smckusick edp = (struct direct *)(buf + buf_size); 31363280Smckusick while (dp < edp) { 31463280Smckusick if (dp->d_ino == (ino_t)0) 31563280Smckusick goto next; 31663280Smckusick #if BYTE_ORDER == LITTLE_ENDIAN 31763280Smckusick if (fp->f_fs->fs_maxsymlinklen <= 0) 31863280Smckusick namlen = dp->d_type; 31963280Smckusick else 32063280Smckusick #endif 32163280Smckusick namlen = dp->d_namlen; 32263280Smckusick if (namlen == length && 32363280Smckusick !strcmp(name, dp->d_name)) { 32463280Smckusick /* found entry */ 32563280Smckusick *inumber_p = dp->d_ino; 32663280Smckusick return (0); 32763280Smckusick } 32863280Smckusick next: 32963280Smckusick dp = (struct direct *)((char *)dp + dp->d_reclen); 33063280Smckusick } 33163280Smckusick fp->f_seekp += buf_size; 33263280Smckusick } 33363280Smckusick return (ENOENT); 33463280Smckusick } 33563280Smckusick 33663280Smckusick /* 33763280Smckusick * Open a file. 33863280Smckusick */ 33963280Smckusick int 34063280Smckusick ufs_open(path, f) 34163280Smckusick char *path; 34263280Smckusick struct open_file *f; 34363280Smckusick { 34463280Smckusick register char *cp, *ncp; 34563280Smckusick register int c; 34663280Smckusick ino_t inumber, parent_inumber; 34763280Smckusick int nlinks = 0; 34863280Smckusick struct file *fp; 34963280Smckusick struct fs *fs; 35063280Smckusick int rc; 35163280Smckusick u_int buf_size; 35263280Smckusick #if 0 35363280Smckusick char namebuf[MAXPATHLEN+1]; 35463280Smckusick #endif 35563280Smckusick 35663280Smckusick /* allocate file system specific data structure */ 35763280Smckusick fp = alloc(sizeof(struct file)); 35863280Smckusick bzero(fp, sizeof(struct file)); 35963280Smckusick f->f_fsdata = (void *)fp; 36063280Smckusick 36163280Smckusick /* allocate space and read super block */ 36263280Smckusick fs = alloc(SBSIZE); 36363280Smckusick fp->f_fs = fs; 36463280Smckusick rc = (f->f_dev->dv_strategy)(f->f_devdata, F_READ, 36563280Smckusick SBLOCK, SBSIZE, (char *)fs, &buf_size); 36663280Smckusick if (rc) 36763280Smckusick goto out; 36863280Smckusick 36963280Smckusick if (buf_size != SBSIZE || fs->fs_magic != FS_MAGIC || 37063280Smckusick fs->fs_bsize > MAXBSIZE || fs->fs_bsize < sizeof(struct fs)) { 37163280Smckusick rc = EINVAL; 37263280Smckusick goto out; 37363280Smckusick } 37463280Smckusick 37563280Smckusick /* 37663280Smckusick * Calculate indirect block levels. 37763280Smckusick */ 37863280Smckusick { 37963280Smckusick register int mult; 38063280Smckusick register int level; 38163280Smckusick 38263280Smckusick mult = 1; 38363280Smckusick for (level = 0; level < NIADDR; level++) { 38463280Smckusick mult *= NINDIR(fs); 38563280Smckusick fp->f_nindir[level] = mult; 38663280Smckusick } 38763280Smckusick } 38863280Smckusick 38963280Smckusick inumber = ROOTINO; 39063280Smckusick if ((rc = read_inode(inumber, f)) != 0) 39163280Smckusick goto out; 39263280Smckusick 39363280Smckusick cp = path; 39463280Smckusick while (*cp) { 39563280Smckusick 39663280Smckusick /* 39763280Smckusick * Remove extra separators 39863280Smckusick */ 39963280Smckusick while (*cp == '/') 40063280Smckusick cp++; 40163280Smckusick if (*cp == '\0') 40263280Smckusick break; 40363280Smckusick 40463280Smckusick /* 40563280Smckusick * Check that current node is a directory. 40663280Smckusick */ 40763280Smckusick if ((fp->f_di.di_mode & IFMT) != IFDIR) { 40863280Smckusick rc = ENOTDIR; 40963280Smckusick goto out; 41063280Smckusick } 41163280Smckusick 41263280Smckusick /* 41363280Smckusick * Get next component of path name. 41463280Smckusick */ 41563280Smckusick { 41663280Smckusick register int len = 0; 41763280Smckusick 41863280Smckusick ncp = cp; 41963280Smckusick while ((c = *cp) != '\0' && c != '/') { 42063280Smckusick if (++len > MAXNAMLEN) { 42163280Smckusick rc = ENOENT; 42263280Smckusick goto out; 42363280Smckusick } 42463280Smckusick cp++; 42563280Smckusick } 42663280Smckusick *cp = '\0'; 42763280Smckusick } 42863280Smckusick 42963280Smckusick /* 43063280Smckusick * Look up component in current directory. 43163280Smckusick * Save directory inumber in case we find a 43263280Smckusick * symbolic link. 43363280Smckusick */ 43463280Smckusick parent_inumber = inumber; 43563280Smckusick rc = search_directory(ncp, f, &inumber); 43663280Smckusick *cp = c; 43763280Smckusick if (rc) 43863280Smckusick goto out; 43963280Smckusick 44063280Smckusick /* 44163280Smckusick * Open next component. 44263280Smckusick */ 44363280Smckusick if ((rc = read_inode(inumber, f)) != 0) 44463280Smckusick goto out; 44563280Smckusick 44663280Smckusick #if 0 44763280Smckusick /* 44863280Smckusick * Check for symbolic link. 44963280Smckusick */ 45063280Smckusick if ((fp->i_mode & IFMT) == IFLNK) { 45163280Smckusick int link_len = fp->f_di.di_size; 45263280Smckusick int len; 45363280Smckusick 45463280Smckusick len = strlen(cp) + 1; 45563280Smckusick 45663280Smckusick if (fp->f_di.di_size >= MAXPATHLEN - 1 || 45763280Smckusick ++nlinks > MAXSYMLINKS) { 45863280Smckusick rc = ENOENT; 45963280Smckusick goto out; 46063280Smckusick } 46163280Smckusick 46263280Smckusick strcpy(&namebuf[link_len], cp); 46363280Smckusick 46463280Smckusick if ((fp->i_flags & IC_FASTLINK) != 0) { 46563280Smckusick bcopy(fp->i_symlink, namebuf, (unsigned) link_len); 46663280Smckusick } else { 46763280Smckusick /* 46863280Smckusick * Read file for symbolic link 46963280Smckusick */ 47063280Smckusick char *buf; 47163280Smckusick u_int buf_size; 47263280Smckusick daddr_t disk_block; 47363280Smckusick register struct fs *fs = fp->f_fs; 47463280Smckusick 47563280Smckusick (void) block_map(f, (daddr_t)0, &disk_block); 47663280Smckusick rc = device_read(&fp->f_dev, 47763280Smckusick fsbtodb(fs, disk_block), 47863280Smckusick blksize(fs, fp, 0), 47963280Smckusick &buf, &buf_size); 48063280Smckusick if (rc) 48163280Smckusick goto out; 48263280Smckusick 48363280Smckusick bcopy((char *)buf, namebuf, (unsigned)link_len); 48463280Smckusick free(buf, buf_size); 48563280Smckusick } 48663280Smckusick 48763280Smckusick /* 48863280Smckusick * If relative pathname, restart at parent directory. 48963280Smckusick * If absolute pathname, restart at root. 49063280Smckusick */ 49163280Smckusick cp = namebuf; 49263280Smckusick if (*cp != '/') 49363280Smckusick inumber = parent_inumber; 49463280Smckusick else 49563280Smckusick inumber = (ino_t)ROOTINO; 49663280Smckusick 49763280Smckusick if ((rc = read_inode(inumber, fp)) != 0) 49863280Smckusick goto out; 49963280Smckusick } 50063280Smckusick #endif 50163280Smckusick } 50263280Smckusick 50363280Smckusick /* 50463280Smckusick * Found terminal component. 50563280Smckusick */ 50663280Smckusick rc = 0; 50763280Smckusick out: 50863280Smckusick if (rc) 50963280Smckusick free(fp, sizeof(struct file)); 51063280Smckusick return (rc); 51163280Smckusick } 51263280Smckusick 51363280Smckusick int 51463280Smckusick ufs_close(f) 51563280Smckusick struct open_file *f; 51663280Smckusick { 51763280Smckusick register struct file *fp = (struct file *)f->f_fsdata; 51863280Smckusick int level; 51963280Smckusick 52063280Smckusick f->f_fsdata = (void *)0; 52163280Smckusick if (fp == (struct file *)0) 52263280Smckusick return (0); 52363280Smckusick 52463280Smckusick for (level = 0; level < NIADDR; level++) { 52563280Smckusick if (fp->f_blk[level]) 52663280Smckusick free(fp->f_blk[level], fp->f_fs->fs_bsize); 52763280Smckusick } 52863280Smckusick if (fp->f_buf) 52963280Smckusick free(fp->f_buf, fp->f_fs->fs_bsize); 53063280Smckusick free(fp->f_fs, SBSIZE); 53163280Smckusick free(fp, sizeof(struct file)); 53263280Smckusick return (0); 53363280Smckusick } 53463280Smckusick 53563280Smckusick /* 53663280Smckusick * Copy a portion of a file into kernel memory. 53763280Smckusick * Cross block boundaries when necessary. 53863280Smckusick */ 53963280Smckusick int 54063280Smckusick ufs_read(f, start, size, resid) 54163280Smckusick struct open_file *f; 54263280Smckusick char *start; 54363280Smckusick u_int size; 54463280Smckusick u_int *resid; /* out */ 54563280Smckusick { 54663280Smckusick register struct file *fp = (struct file *)f->f_fsdata; 54763280Smckusick register u_int csize; 54863280Smckusick char *buf; 54963280Smckusick u_int buf_size; 55063280Smckusick int rc = 0; 55163280Smckusick 55263280Smckusick while (size != 0) { 55363280Smckusick if (fp->f_seekp >= fp->f_di.di_size) 55463280Smckusick break; 55563280Smckusick 55663280Smckusick rc = buf_read_file(f, &buf, &buf_size); 55763280Smckusick if (rc) 55863280Smckusick break; 55963280Smckusick 56063280Smckusick csize = size; 56163280Smckusick if (csize > buf_size) 56263280Smckusick csize = buf_size; 56363280Smckusick 56463280Smckusick bcopy(buf, start, csize); 56563280Smckusick 56663280Smckusick fp->f_seekp += csize; 56763280Smckusick start += csize; 56863280Smckusick size -= csize; 56963280Smckusick } 57063280Smckusick if (resid) 57163280Smckusick *resid = size; 57263280Smckusick return (rc); 57363280Smckusick } 57463280Smckusick 57563280Smckusick /* 57663280Smckusick * Not implemented. 57763280Smckusick */ 57863280Smckusick int 57963280Smckusick ufs_write(f, start, size, resid) 58063280Smckusick struct open_file *f; 58163280Smckusick char *start; 58263280Smckusick u_int size; 58363280Smckusick u_int *resid; /* out */ 58463280Smckusick { 58563280Smckusick 58663280Smckusick return (EROFS); 58763280Smckusick } 58863280Smckusick 58963280Smckusick off_t 59063280Smckusick ufs_seek(f, offset, where) 59163280Smckusick struct open_file *f; 59263280Smckusick off_t offset; 59363280Smckusick int where; 59463280Smckusick { 59563280Smckusick register struct file *fp = (struct file *)f->f_fsdata; 59663280Smckusick 59763280Smckusick switch (where) { 59863280Smckusick case SEEK_SET: 59963280Smckusick fp->f_seekp = offset; 60063280Smckusick break; 60163280Smckusick case SEEK_CUR: 60263280Smckusick fp->f_seekp += offset; 60363280Smckusick break; 60463280Smckusick case SEEK_END: 60563280Smckusick fp->f_seekp = fp->f_di.di_size - offset; 60663280Smckusick break; 60763280Smckusick default: 60863280Smckusick return (-1); 60963280Smckusick } 61063280Smckusick return (fp->f_seekp); 61163280Smckusick } 61263280Smckusick 61363280Smckusick int 61463280Smckusick ufs_stat(f, sb) 61563280Smckusick struct open_file *f; 61663280Smckusick struct stat *sb; 61763280Smckusick { 61863280Smckusick register struct file *fp = (struct file *)f->f_fsdata; 61963280Smckusick 62063280Smckusick /* only important stuff */ 62163280Smckusick sb->st_mode = fp->f_di.di_mode; 62263280Smckusick sb->st_uid = fp->f_di.di_uid; 62363280Smckusick sb->st_gid = fp->f_di.di_gid; 62463280Smckusick sb->st_size = fp->f_di.di_size; 62563280Smckusick return (0); 62663280Smckusick } 627