Annotation of prex-old/usr/server/fs/arfs/arfs_vnops.c, Revision 1.1.1.1
1.1 nbrk 1: /*
2: * Copyright (c) 2006-2007, Kohsuke Ohtani
3: * All rights reserved.
4: *
5: * Redistribution and use in source and binary forms, with or without
6: * modification, are permitted provided that the following conditions
7: * are met:
8: * 1. Redistributions of source code must retain the above copyright
9: * notice, this list of conditions and the following disclaimer.
10: * 2. Redistributions in binary form must reproduce the above copyright
11: * notice, this list of conditions and the following disclaimer in the
12: * documentation and/or other materials provided with the distribution.
13: * 3. Neither the name of the author nor the names of any co-contributors
14: * may be used to endorse or promote products derived from this software
15: * without specific prior written permission.
16: *
17: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20: * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27: * SUCH DAMAGE.
28: */
29:
30: /*
31: * arfs_vnops.c - vnode operations for archive file system.
32: */
33:
34: #include <prex/prex.h>
35: #include <sys/stat.h>
36: #include <sys/vnode.h>
37: #include <sys/file.h>
38: #include <sys/mount.h>
39: #include <sys/param.h>
40: #include <sys/dirent.h>
41: #include <sys/buf.h>
42:
43: #include <ctype.h>
44: #include <unistd.h>
45: #include <errno.h>
46: #include <string.h>
47: #include <stdlib.h>
48: #include <limits.h>
49: #include <fcntl.h>
50: #include <ar.h>
51:
52: #include "arfs.h"
53:
54: #define arfs_open ((vnop_open_t)vop_nullop)
55: #define arfs_close ((vnop_close_t)vop_nullop)
56: static int arfs_read(vnode_t, file_t, void *, size_t, size_t *);
57: #define arfs_write ((vnop_write_t)vop_nullop)
58: static int arfs_seek(vnode_t, file_t, off_t, off_t);
59: #define arfs_ioctl ((vnop_ioctl_t)vop_einval)
60: #define arfs_fsync ((vnop_fsync_t)vop_nullop)
61: static int arfs_readdir(vnode_t, file_t, struct dirent *);
62: static int arfs_lookup(vnode_t, char *, vnode_t);
63: #define arfs_create ((vnop_create_t)vop_einval)
64: #define arfs_remove ((vnop_remove_t)vop_einval)
65: #define arfs_rename ((vnop_rename_t)vop_einval)
66: #define arfs_mkdir ((vnop_mkdir_t)vop_einval)
67: #define arfs_rmdir ((vnop_rmdir_t)vop_einval)
68: #define arfs_getattr ((vnop_getattr_t)vop_nullop)
69: #define arfs_setattr ((vnop_setattr_t)vop_nullop)
70: #define arfs_inactive ((vnop_inactive_t)vop_nullop)
71: #define arfs_truncate ((vnop_truncate_t)vop_nullop)
72:
73: static char iobuf[BSIZE*2];
74:
75: #if CONFIG_FS_THREADS > 1
76: static mutex_t arfs_lock = MUTEX_INITIALIZER;
77: #endif
78:
79: /*
80: * vnode operations
81: */
82: const struct vnops arfs_vnops = {
83: arfs_open, /* open */
84: arfs_close, /* close */
85: arfs_read, /* read */
86: arfs_write, /* write */
87: arfs_seek, /* seek */
88: arfs_ioctl, /* ioctl */
89: arfs_fsync, /* fsync */
90: arfs_readdir, /* readdir */
91: arfs_lookup, /* lookup */
92: arfs_create, /* create */
93: arfs_remove, /* remove */
94: arfs_rename, /* remame */
95: arfs_mkdir, /* mkdir */
96: arfs_rmdir, /* rmdir */
97: arfs_getattr, /* getattr */
98: arfs_setattr, /* setattr */
99: arfs_inactive, /* inactive */
100: arfs_truncate, /* truncate */
101: };
102:
103: /*
104: * Read two blocks.
105: * iobuf is filled by read data.
106: */
107: static int
108: arfs_readblk(mount_t mp, int blkno)
109: {
110: struct buf *bp;
111: int err;
112:
113: /* Read two blocks for archive header */
114: if ((err = bread(mp->m_dev, blkno, &bp)) != 0)
115: return err;
116: memcpy(iobuf, bp->b_data, BSIZE);
117: brelse(bp);
118:
119: if ((err = bread(mp->m_dev, blkno + 1, &bp)) != 0)
120: return err;
121: memcpy(iobuf + BSIZE, bp->b_data, BSIZE);
122: brelse(bp);
123: return 0;
124: }
125:
126: /*
127: * Lookup vnode for the specified file/directory.
128: * The vnode is filled properly.
129: */
130: static int
131: arfs_lookup(vnode_t dvp, char *name, vnode_t vp)
132: {
133: struct ar_hdr *hdr;
134: int blkno, err;
135: off_t off;
136: size_t size;
137: mount_t mp;
138: char *p;
139:
140: dprintf("lookup: name=%s\n", name);
141: if (*name == '\0')
142: return ENOENT;
143:
144: mutex_lock(&arfs_lock);
145:
146: err = ENOENT;
147: mp = vp->v_mount;
148: blkno = 0;
149: off = SARMAG; /* offset in archive image */
150: for (;;) {
151: /* Read two blocks for archive header */
152: if (arfs_readblk(mp, blkno) != 0)
153: goto out;
154:
155: /* Check file header */
156: hdr = (struct ar_hdr *)(iobuf + (off % BSIZE));
157: if (strncmp(hdr->ar_fmag, ARFMAG, sizeof(ARFMAG) - 1))
158: goto out;
159:
160: /* Get file size */
161: size = (size_t)atol((char *)&hdr->ar_size);
162: if (size == 0)
163: goto out;
164:
165: /* Convert archive name */
166: if ((p = memchr(&hdr->ar_name, '/', 16)) != NULL)
167: *p = '\0';
168:
169: if (strncmp(name, (char *)&hdr->ar_name, 16) == 0)
170: break;
171:
172: /* Proceed to next archive header */
173: off += (sizeof(struct ar_hdr) + size);
174: off += (off % 2); /* Pad to even boundary */
175:
176: blkno = (int)(off / BSIZE);
177: }
178: vp->v_type = VREG;
179:
180: /* No write access */
181: vp->v_mode = S_IRUSR | S_IXUSR | S_IRGRP | S_IXGRP
182: | S_IROTH | S_IXOTH;
183: vp->v_size = size;
184: vp->v_blkno = blkno;
185: vp->v_data = (void *)(off + sizeof(struct ar_hdr));
186: err = 0;
187: out:
188: mutex_unlock(&arfs_lock);
189: dprintf("lookup: err=%d\n\n", err);
190: return err;
191: }
192:
193: static int
194: arfs_read(vnode_t vp, file_t fp, void *buf, size_t size, size_t *result)
195: {
196: off_t off, file_pos, buf_pos;
197: int blkno, err;
198: size_t nr_read, nr_copy;
199: mount_t mp;
200: struct buf *bp;
201:
202: dprintf("****read: start size=%d\n", size);
203: mutex_lock(&arfs_lock);
204:
205: *result = 0;
206: mp = vp->v_mount;
207:
208: /* Check if current file position is already end of file. */
209: file_pos = fp->f_offset;
210: if (file_pos >= (off_t)vp->v_size) {
211: err = 0;
212: goto out;
213: }
214: /* Get the actual read size. */
215: if (vp->v_size - file_pos < size)
216: size = vp->v_size - file_pos;
217:
218: /* Read and copy data */
219: off = (off_t)vp->v_data;
220: nr_read = 0;
221: for (;;) {
222: dprintf("file_pos=%d buf=%x size=%d\n", file_pos, buf, size);
223:
224: blkno = (off + file_pos) / BSIZE;
225: buf_pos = (off + file_pos) % BSIZE;
226: if ((err = bread(mp->m_dev, blkno, &bp)) != 0)
227: goto out;
228: nr_copy = BSIZE;
229: if (buf_pos > 0)
230: nr_copy -= buf_pos;
231: if (buf_pos + size < BSIZE)
232: nr_copy = size;
233: ASSERT(nr_copy > 0);
234: memcpy(buf, bp->b_data + buf_pos, nr_copy);
235: brelse(bp);
236:
237: file_pos += nr_copy;
238: dprintf("file_pos=%d nr_copy=%d\n", file_pos, nr_copy);
239:
240: nr_read += nr_copy;
241: size -= nr_copy;
242: if (size <= 0)
243: break;
244: buf = (void *)((u_long)buf + nr_copy);
245: buf_pos = 0;
246: }
247: fp->f_offset = file_pos;
248: *result = nr_read;
249: err = 0;
250: out:
251: mutex_unlock(&arfs_lock);
252: dprintf("read: err=%d\n\n", err);
253: return err;
254: }
255:
256: /*
257: * Check if the seek offset is valid.
258: */
259: static int
260: arfs_seek(vnode_t vp, file_t fp, off_t oldoff, off_t newoff)
261: {
262:
263: if (newoff > (off_t)vp->v_size)
264: return -1;
265:
266: return 0;
267: }
268:
269: static int
270: arfs_readdir(vnode_t vp, file_t fp, struct dirent *dir)
271: {
272: struct ar_hdr *hdr;
273: int blkno, i, err;
274: off_t off;
275: size_t size;
276: mount_t mp;
277: char *p;
278:
279: dprintf("readdir: start\n");
280: mutex_lock(&arfs_lock);
281:
282: i = 0;
283: mp = vp->v_mount;
284: blkno = 0;
285: off = SARMAG; /* offset in archive image */
286: for (;;) {
287: /* Read two blocks for archive header */
288: if ((err = arfs_readblk(mp, blkno)) != 0)
289: goto out;
290:
291: hdr = (struct ar_hdr *)(iobuf + (off % BSIZE));
292:
293: /* Get file size */
294: size = (size_t)atol((char *)&hdr->ar_size);
295: if (size == 0) {
296: err = ENOENT;
297: goto out;
298: }
299: if (i == fp->f_offset)
300: break;
301:
302: /* Proceed to next archive header */
303: off += (sizeof(struct ar_hdr) + size);
304: off += (off % 2); /* Pad to even boundary */
305:
306: blkno = off / BSIZE;
307: i++;
308: }
309:
310: /* Convert archive name */
311: if ((p = memchr(&hdr->ar_name, '/', 16)) != NULL)
312: *p = '\0';
313:
314: strcpy((char *)&dir->d_name, (char *)&hdr->ar_name);
315: dir->d_namlen = strlen(dir->d_name);
316: dir->d_fileno = fp->f_offset;
317: dir->d_type = DT_REG;
318:
319: fp->f_offset++;
320: err = 0;
321: out:
322: mutex_unlock(&arfs_lock);
323: return err;
324: }
325:
326:
327: int
328: arfs_init(void)
329: {
330: return 0;
331: }
CVSweb