163280Smckusick /*-
263370Sbostic * Copyright (c) 1993
363370Sbostic * 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*64985Smckusick * @(#)ufs.c 8.2 (Berkeley) 11/30/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 */
62*64985Smckusick u_int 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
read_inode(inumber,f)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,
89*64985Smckusick fsbtodb(fs, ino_to_fsba(fs, inumber)), fs->fs_bsize,
90*64985Smckusick buf, &rsize);
9163280Smckusick if (rc)
9263280Smckusick goto out;
9363280Smckusick if (rsize != fs->fs_bsize) {
9463280Smckusick rc = EIO;
9563280Smckusick goto out;
9663280Smckusick }
9763280Smckusick
9863280Smckusick {
9963280Smckusick register struct dinode *dp;
10063280Smckusick
10163280Smckusick dp = (struct dinode *)buf;
102*64985Smckusick fp->f_di = dp[ino_to_fsbo(fs, inumber)];
10363280Smckusick }
10463280Smckusick
10563280Smckusick /*
10663280Smckusick * Clear out the old buffers
10763280Smckusick */
10863280Smckusick {
10963280Smckusick register int level;
11063280Smckusick
11163280Smckusick for (level = 0; level < NIADDR; level++)
11263280Smckusick fp->f_blkno[level] = -1;
11363280Smckusick fp->f_buf_blkno = -1;
11463280Smckusick }
11563280Smckusick out:
11663280Smckusick free(buf, fs->fs_bsize);
11763280Smckusick return (0);
11863280Smckusick }
11963280Smckusick
12063280Smckusick /*
12163280Smckusick * Given an offset in a file, find the disk block number that
12263280Smckusick * contains that block.
12363280Smckusick */
12463280Smckusick static int
block_map(f,file_block,disk_block_p)12563280Smckusick block_map(f, file_block, disk_block_p)
12663280Smckusick struct open_file *f;
12763280Smckusick daddr_t file_block;
12863280Smckusick daddr_t *disk_block_p; /* out */
12963280Smckusick {
13063280Smckusick register struct file *fp = (struct file *)f->f_fsdata;
13163280Smckusick register struct fs *fs = fp->f_fs;
13263280Smckusick int level;
13363280Smckusick int idx;
13463280Smckusick daddr_t ind_block_num;
13563280Smckusick daddr_t *ind_p;
13663280Smckusick int rc;
13763280Smckusick
13863280Smckusick /*
13963280Smckusick * Index structure of an inode:
14063280Smckusick *
14163280Smckusick * di_db[0..NDADDR-1] hold block numbers for blocks
14263280Smckusick * 0..NDADDR-1
14363280Smckusick *
14463280Smckusick * di_ib[0] index block 0 is the single indirect block
14563280Smckusick * holds block numbers for blocks
14663280Smckusick * NDADDR .. NDADDR + NINDIR(fs)-1
14763280Smckusick *
14863280Smckusick * di_ib[1] index block 1 is the double indirect block
14963280Smckusick * holds block numbers for INDEX blocks for blocks
15063280Smckusick * NDADDR + NINDIR(fs) ..
15163280Smckusick * NDADDR + NINDIR(fs) + NINDIR(fs)**2 - 1
15263280Smckusick *
15363280Smckusick * di_ib[2] index block 2 is the triple indirect block
15463280Smckusick * holds block numbers for double-indirect
15563280Smckusick * blocks for blocks
15663280Smckusick * NDADDR + NINDIR(fs) + NINDIR(fs)**2 ..
15763280Smckusick * NDADDR + NINDIR(fs) + NINDIR(fs)**2
15863280Smckusick * + NINDIR(fs)**3 - 1
15963280Smckusick */
16063280Smckusick
16163280Smckusick if (file_block < NDADDR) {
16263280Smckusick /* Direct block. */
16363280Smckusick *disk_block_p = fp->f_di.di_db[file_block];
16463280Smckusick return (0);
16563280Smckusick }
16663280Smckusick
16763280Smckusick file_block -= NDADDR;
16863280Smckusick
16963280Smckusick /*
17063280Smckusick * nindir[0] = NINDIR
17163280Smckusick * nindir[1] = NINDIR**2
17263280Smckusick * nindir[2] = NINDIR**3
17363280Smckusick * etc
17463280Smckusick */
17563280Smckusick for (level = 0; level < NIADDR; level++) {
17663280Smckusick if (file_block < fp->f_nindir[level])
17763280Smckusick break;
17863280Smckusick file_block -= fp->f_nindir[level];
17963280Smckusick }
18063280Smckusick if (level == NIADDR) {
18163280Smckusick /* Block number too high */
18263280Smckusick return (EFBIG);
18363280Smckusick }
18463280Smckusick
18563280Smckusick ind_block_num = fp->f_di.di_ib[level];
18663280Smckusick
18763280Smckusick for (; level >= 0; level--) {
18863280Smckusick if (ind_block_num == 0) {
18963280Smckusick *disk_block_p = 0; /* missing */
19063280Smckusick return (0);
19163280Smckusick }
19263280Smckusick
19363280Smckusick if (fp->f_blkno[level] != ind_block_num) {
19463280Smckusick if (fp->f_blk[level] == (char *)0)
19563280Smckusick fp->f_blk[level] =
19663280Smckusick alloc(fs->fs_bsize);
19763280Smckusick rc = (f->f_dev->dv_strategy)(f->f_devdata, F_READ,
19863280Smckusick fsbtodb(fp->f_fs, ind_block_num),
19963280Smckusick fs->fs_bsize,
20063280Smckusick fp->f_blk[level],
20163280Smckusick &fp->f_blksize[level]);
20263280Smckusick if (rc)
20363280Smckusick return (rc);
20463280Smckusick if (fp->f_blksize[level] != fs->fs_bsize)
20563280Smckusick return (EIO);
20663280Smckusick fp->f_blkno[level] = ind_block_num;
20763280Smckusick }
20863280Smckusick
20963280Smckusick ind_p = (daddr_t *)fp->f_blk[level];
21063280Smckusick
21163280Smckusick if (level > 0) {
21263280Smckusick idx = file_block / fp->f_nindir[level - 1];
21363280Smckusick file_block %= fp->f_nindir[level - 1];
21463280Smckusick } else
21563280Smckusick idx = file_block;
21663280Smckusick
21763280Smckusick ind_block_num = ind_p[idx];
21863280Smckusick }
21963280Smckusick
22063280Smckusick *disk_block_p = ind_block_num;
22163280Smckusick
22263280Smckusick return (0);
22363280Smckusick }
22463280Smckusick
22563280Smckusick /*
22663280Smckusick * Read a portion of a file into an internal buffer. Return
22763280Smckusick * the location in the buffer and the amount in the buffer.
22863280Smckusick */
22963280Smckusick static int
buf_read_file(f,buf_p,size_p)23063280Smckusick buf_read_file(f, buf_p, size_p)
23163280Smckusick struct open_file *f;
23263280Smckusick char **buf_p; /* out */
23363280Smckusick u_int *size_p; /* out */
23463280Smckusick {
23563280Smckusick register struct file *fp = (struct file *)f->f_fsdata;
23663280Smckusick register struct fs *fs = fp->f_fs;
23763280Smckusick long off;
23863280Smckusick register daddr_t file_block;
23963280Smckusick daddr_t disk_block;
24063280Smckusick long block_size;
24163280Smckusick int rc;
24263280Smckusick
24363280Smckusick off = blkoff(fs, fp->f_seekp);
24463280Smckusick file_block = lblkno(fs, fp->f_seekp);
24563280Smckusick block_size = dblksize(fs, &fp->f_di, file_block);
24663280Smckusick
24763280Smckusick if (file_block != fp->f_buf_blkno) {
24863280Smckusick rc = block_map(f, file_block, &disk_block);
24963280Smckusick if (rc)
25063280Smckusick return (rc);
25163280Smckusick
25263280Smckusick if (fp->f_buf == (char *)0)
25363280Smckusick fp->f_buf = alloc(fs->fs_bsize);
25463280Smckusick
25563280Smckusick if (disk_block == 0) {
25663280Smckusick bzero(fp->f_buf, block_size);
25763280Smckusick fp->f_buf_size = block_size;
25863280Smckusick } else {
25963280Smckusick rc = (f->f_dev->dv_strategy)(f->f_devdata, F_READ,
26063280Smckusick fsbtodb(fs, disk_block),
26163280Smckusick block_size, fp->f_buf, &fp->f_buf_size);
26263280Smckusick if (rc)
26363280Smckusick return (rc);
26463280Smckusick }
26563280Smckusick
26663280Smckusick fp->f_buf_blkno = file_block;
26763280Smckusick }
26863280Smckusick
26963280Smckusick /*
27063280Smckusick * Return address of byte in buffer corresponding to
27163280Smckusick * offset, and size of remainder of buffer after that
27263280Smckusick * byte.
27363280Smckusick */
27463280Smckusick *buf_p = fp->f_buf + off;
27563280Smckusick *size_p = block_size - off;
27663280Smckusick
27763280Smckusick /*
27863280Smckusick * But truncate buffer at end of file.
27963280Smckusick */
28063280Smckusick if (*size_p > fp->f_di.di_size - fp->f_seekp)
28163280Smckusick *size_p = fp->f_di.di_size - fp->f_seekp;
28263280Smckusick
28363280Smckusick return (0);
28463280Smckusick }
28563280Smckusick
28663280Smckusick /*
28763280Smckusick * Search a directory for a name and return its
28863280Smckusick * i_number.
28963280Smckusick */
29063280Smckusick static int
search_directory(name,f,inumber_p)29163280Smckusick search_directory(name, f, inumber_p)
29263280Smckusick char *name;
29363280Smckusick struct open_file *f;
29463280Smckusick ino_t *inumber_p; /* out */
29563280Smckusick {
29663280Smckusick register struct file *fp = (struct file *)f->f_fsdata;
29763280Smckusick register struct direct *dp;
29863280Smckusick struct direct *edp;
29963280Smckusick char *buf;
30063280Smckusick u_int buf_size;
30163280Smckusick int namlen, length;
30263280Smckusick int rc;
30363280Smckusick
30463280Smckusick length = strlen(name);
30563280Smckusick
30663280Smckusick fp->f_seekp = 0;
30763280Smckusick while (fp->f_seekp < fp->f_di.di_size) {
30863280Smckusick rc = buf_read_file(f, &buf, &buf_size);
30963280Smckusick if (rc)
31063280Smckusick return (rc);
31163280Smckusick
31263280Smckusick dp = (struct direct *)buf;
31363280Smckusick edp = (struct direct *)(buf + buf_size);
31463280Smckusick while (dp < edp) {
31563280Smckusick if (dp->d_ino == (ino_t)0)
31663280Smckusick goto next;
31763280Smckusick #if BYTE_ORDER == LITTLE_ENDIAN
31863280Smckusick if (fp->f_fs->fs_maxsymlinklen <= 0)
31963280Smckusick namlen = dp->d_type;
32063280Smckusick else
32163280Smckusick #endif
32263280Smckusick namlen = dp->d_namlen;
32363280Smckusick if (namlen == length &&
32463280Smckusick !strcmp(name, dp->d_name)) {
32563280Smckusick /* found entry */
32663280Smckusick *inumber_p = dp->d_ino;
32763280Smckusick return (0);
32863280Smckusick }
32963280Smckusick next:
33063280Smckusick dp = (struct direct *)((char *)dp + dp->d_reclen);
33163280Smckusick }
33263280Smckusick fp->f_seekp += buf_size;
33363280Smckusick }
33463280Smckusick return (ENOENT);
33563280Smckusick }
33663280Smckusick
33763280Smckusick /*
33863280Smckusick * Open a file.
33963280Smckusick */
34063280Smckusick int
ufs_open(path,f)34163280Smckusick ufs_open(path, f)
34263280Smckusick char *path;
34363280Smckusick struct open_file *f;
34463280Smckusick {
34563280Smckusick register char *cp, *ncp;
34663280Smckusick register int c;
34763280Smckusick ino_t inumber, parent_inumber;
34863280Smckusick int nlinks = 0;
34963280Smckusick struct file *fp;
35063280Smckusick struct fs *fs;
35163280Smckusick int rc;
35263280Smckusick u_int buf_size;
35363280Smckusick #if 0
35463280Smckusick char namebuf[MAXPATHLEN+1];
35563280Smckusick #endif
35663280Smckusick
35763280Smckusick /* allocate file system specific data structure */
35863280Smckusick fp = alloc(sizeof(struct file));
35963280Smckusick bzero(fp, sizeof(struct file));
36063280Smckusick f->f_fsdata = (void *)fp;
36163280Smckusick
36263280Smckusick /* allocate space and read super block */
36363280Smckusick fs = alloc(SBSIZE);
36463280Smckusick fp->f_fs = fs;
36563280Smckusick rc = (f->f_dev->dv_strategy)(f->f_devdata, F_READ,
36663280Smckusick SBLOCK, SBSIZE, (char *)fs, &buf_size);
36763280Smckusick if (rc)
36863280Smckusick goto out;
36963280Smckusick
37063280Smckusick if (buf_size != SBSIZE || fs->fs_magic != FS_MAGIC ||
37163280Smckusick fs->fs_bsize > MAXBSIZE || fs->fs_bsize < sizeof(struct fs)) {
37263280Smckusick rc = EINVAL;
37363280Smckusick goto out;
37463280Smckusick }
37563280Smckusick
37663280Smckusick /*
37763280Smckusick * Calculate indirect block levels.
37863280Smckusick */
37963280Smckusick {
38063280Smckusick register int mult;
38163280Smckusick register int level;
38263280Smckusick
38363280Smckusick mult = 1;
38463280Smckusick for (level = 0; level < NIADDR; level++) {
38563280Smckusick mult *= NINDIR(fs);
38663280Smckusick fp->f_nindir[level] = mult;
38763280Smckusick }
38863280Smckusick }
38963280Smckusick
39063280Smckusick inumber = ROOTINO;
39163280Smckusick if ((rc = read_inode(inumber, f)) != 0)
39263280Smckusick goto out;
39363280Smckusick
39463280Smckusick cp = path;
39563280Smckusick while (*cp) {
39663280Smckusick
39763280Smckusick /*
39863280Smckusick * Remove extra separators
39963280Smckusick */
40063280Smckusick while (*cp == '/')
40163280Smckusick cp++;
40263280Smckusick if (*cp == '\0')
40363280Smckusick break;
40463280Smckusick
40563280Smckusick /*
40663280Smckusick * Check that current node is a directory.
40763280Smckusick */
40863280Smckusick if ((fp->f_di.di_mode & IFMT) != IFDIR) {
40963280Smckusick rc = ENOTDIR;
41063280Smckusick goto out;
41163280Smckusick }
41263280Smckusick
41363280Smckusick /*
41463280Smckusick * Get next component of path name.
41563280Smckusick */
41663280Smckusick {
41763280Smckusick register int len = 0;
41863280Smckusick
41963280Smckusick ncp = cp;
42063280Smckusick while ((c = *cp) != '\0' && c != '/') {
42163280Smckusick if (++len > MAXNAMLEN) {
42263280Smckusick rc = ENOENT;
42363280Smckusick goto out;
42463280Smckusick }
42563280Smckusick cp++;
42663280Smckusick }
42763280Smckusick *cp = '\0';
42863280Smckusick }
42963280Smckusick
43063280Smckusick /*
43163280Smckusick * Look up component in current directory.
43263280Smckusick * Save directory inumber in case we find a
43363280Smckusick * symbolic link.
43463280Smckusick */
43563280Smckusick parent_inumber = inumber;
43663280Smckusick rc = search_directory(ncp, f, &inumber);
43763280Smckusick *cp = c;
43863280Smckusick if (rc)
43963280Smckusick goto out;
44063280Smckusick
44163280Smckusick /*
44263280Smckusick * Open next component.
44363280Smckusick */
44463280Smckusick if ((rc = read_inode(inumber, f)) != 0)
44563280Smckusick goto out;
44663280Smckusick
44763280Smckusick #if 0
44863280Smckusick /*
44963280Smckusick * Check for symbolic link.
45063280Smckusick */
45163280Smckusick if ((fp->i_mode & IFMT) == IFLNK) {
45263280Smckusick int link_len = fp->f_di.di_size;
45363280Smckusick int len;
45463280Smckusick
45563280Smckusick len = strlen(cp) + 1;
45663280Smckusick
45763280Smckusick if (fp->f_di.di_size >= MAXPATHLEN - 1 ||
45863280Smckusick ++nlinks > MAXSYMLINKS) {
45963280Smckusick rc = ENOENT;
46063280Smckusick goto out;
46163280Smckusick }
46263280Smckusick
46363280Smckusick strcpy(&namebuf[link_len], cp);
46463280Smckusick
46563280Smckusick if ((fp->i_flags & IC_FASTLINK) != 0) {
46663280Smckusick bcopy(fp->i_symlink, namebuf, (unsigned) link_len);
46763280Smckusick } else {
46863280Smckusick /*
46963280Smckusick * Read file for symbolic link
47063280Smckusick */
47163280Smckusick char *buf;
47263280Smckusick u_int buf_size;
47363280Smckusick daddr_t disk_block;
47463280Smckusick register struct fs *fs = fp->f_fs;
47563280Smckusick
47663280Smckusick (void) block_map(f, (daddr_t)0, &disk_block);
47763280Smckusick rc = device_read(&fp->f_dev,
47863280Smckusick fsbtodb(fs, disk_block),
47963280Smckusick blksize(fs, fp, 0),
48063280Smckusick &buf, &buf_size);
48163280Smckusick if (rc)
48263280Smckusick goto out;
48363280Smckusick
48463280Smckusick bcopy((char *)buf, namebuf, (unsigned)link_len);
48563280Smckusick free(buf, buf_size);
48663280Smckusick }
48763280Smckusick
48863280Smckusick /*
48963280Smckusick * If relative pathname, restart at parent directory.
49063280Smckusick * If absolute pathname, restart at root.
49163280Smckusick */
49263280Smckusick cp = namebuf;
49363280Smckusick if (*cp != '/')
49463280Smckusick inumber = parent_inumber;
49563280Smckusick else
49663280Smckusick inumber = (ino_t)ROOTINO;
49763280Smckusick
49863280Smckusick if ((rc = read_inode(inumber, fp)) != 0)
49963280Smckusick goto out;
50063280Smckusick }
50163280Smckusick #endif
50263280Smckusick }
50363280Smckusick
50463280Smckusick /*
50563280Smckusick * Found terminal component.
50663280Smckusick */
50763280Smckusick rc = 0;
50863280Smckusick out:
50963280Smckusick if (rc)
51063280Smckusick free(fp, sizeof(struct file));
51163280Smckusick return (rc);
51263280Smckusick }
51363280Smckusick
51463280Smckusick int
ufs_close(f)51563280Smckusick ufs_close(f)
51663280Smckusick struct open_file *f;
51763280Smckusick {
51863280Smckusick register struct file *fp = (struct file *)f->f_fsdata;
51963280Smckusick int level;
52063280Smckusick
52163280Smckusick f->f_fsdata = (void *)0;
52263280Smckusick if (fp == (struct file *)0)
52363280Smckusick return (0);
52463280Smckusick
52563280Smckusick for (level = 0; level < NIADDR; level++) {
52663280Smckusick if (fp->f_blk[level])
52763280Smckusick free(fp->f_blk[level], fp->f_fs->fs_bsize);
52863280Smckusick }
52963280Smckusick if (fp->f_buf)
53063280Smckusick free(fp->f_buf, fp->f_fs->fs_bsize);
53163280Smckusick free(fp->f_fs, SBSIZE);
53263280Smckusick free(fp, sizeof(struct file));
53363280Smckusick return (0);
53463280Smckusick }
53563280Smckusick
53663280Smckusick /*
53763280Smckusick * Copy a portion of a file into kernel memory.
53863280Smckusick * Cross block boundaries when necessary.
53963280Smckusick */
54063280Smckusick int
ufs_read(f,start,size,resid)54163280Smckusick ufs_read(f, start, size, resid)
54263280Smckusick struct open_file *f;
54363280Smckusick char *start;
54463280Smckusick u_int size;
54563280Smckusick u_int *resid; /* out */
54663280Smckusick {
54763280Smckusick register struct file *fp = (struct file *)f->f_fsdata;
54863280Smckusick register u_int csize;
54963280Smckusick char *buf;
55063280Smckusick u_int buf_size;
55163280Smckusick int rc = 0;
55263280Smckusick
55363280Smckusick while (size != 0) {
55463280Smckusick if (fp->f_seekp >= fp->f_di.di_size)
55563280Smckusick break;
55663280Smckusick
55763280Smckusick rc = buf_read_file(f, &buf, &buf_size);
55863280Smckusick if (rc)
55963280Smckusick break;
56063280Smckusick
56163280Smckusick csize = size;
56263280Smckusick if (csize > buf_size)
56363280Smckusick csize = buf_size;
56463280Smckusick
56563280Smckusick bcopy(buf, start, csize);
56663280Smckusick
56763280Smckusick fp->f_seekp += csize;
56863280Smckusick start += csize;
56963280Smckusick size -= csize;
57063280Smckusick }
57163280Smckusick if (resid)
57263280Smckusick *resid = size;
57363280Smckusick return (rc);
57463280Smckusick }
57563280Smckusick
57663280Smckusick /*
57763280Smckusick * Not implemented.
57863280Smckusick */
57963280Smckusick int
ufs_write(f,start,size,resid)58063280Smckusick ufs_write(f, start, size, resid)
58163280Smckusick struct open_file *f;
58263280Smckusick char *start;
58363280Smckusick u_int size;
58463280Smckusick u_int *resid; /* out */
58563280Smckusick {
58663280Smckusick
58763280Smckusick return (EROFS);
58863280Smckusick }
58963280Smckusick
59063280Smckusick off_t
ufs_seek(f,offset,where)59163280Smckusick ufs_seek(f, offset, where)
59263280Smckusick struct open_file *f;
59363280Smckusick off_t offset;
59463280Smckusick int where;
59563280Smckusick {
59663280Smckusick register struct file *fp = (struct file *)f->f_fsdata;
59763280Smckusick
59863280Smckusick switch (where) {
59963280Smckusick case SEEK_SET:
60063280Smckusick fp->f_seekp = offset;
60163280Smckusick break;
60263280Smckusick case SEEK_CUR:
60363280Smckusick fp->f_seekp += offset;
60463280Smckusick break;
60563280Smckusick case SEEK_END:
60663280Smckusick fp->f_seekp = fp->f_di.di_size - offset;
60763280Smckusick break;
60863280Smckusick default:
60963280Smckusick return (-1);
61063280Smckusick }
61163280Smckusick return (fp->f_seekp);
61263280Smckusick }
61363280Smckusick
61463280Smckusick int
ufs_stat(f,sb)61563280Smckusick ufs_stat(f, sb)
61663280Smckusick struct open_file *f;
61763280Smckusick struct stat *sb;
61863280Smckusick {
61963280Smckusick register struct file *fp = (struct file *)f->f_fsdata;
62063280Smckusick
62163280Smckusick /* only important stuff */
62263280Smckusick sb->st_mode = fp->f_di.di_mode;
62363280Smckusick sb->st_uid = fp->f_di.di_uid;
62463280Smckusick sb->st_gid = fp->f_di.di_gid;
62563280Smckusick sb->st_size = fp->f_di.di_size;
62663280Smckusick return (0);
62763280Smckusick }
628