Annotation of prex/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: /**
35: * General design:
36: *
37: * ARFS (ARchive File System) is the read-only file system which
38: * handles the generic archive (*.a) file as a file system image.
39: * The file system is typically used for the boot time file system,
40: * and it's mounted to the ram disk device mapped to the pre-loaded
41: * archive file image. All files are placed in one single directory.
42: */
43:
44: #include <prex/prex.h>
45: #include <sys/stat.h>
46: #include <sys/vnode.h>
47: #include <sys/file.h>
48: #include <sys/mount.h>
49: #include <sys/param.h>
50: #include <sys/dirent.h>
51: #include <sys/buf.h>
52:
53: #include <ctype.h>
54: #include <unistd.h>
55: #include <errno.h>
56: #include <string.h>
57: #include <stdlib.h>
58: #include <limits.h>
59: #include <fcntl.h>
60: #include <ar.h>
61:
62: #include "arfs.h"
63:
64: #define arfs_open ((vnop_open_t)vop_nullop)
65: #define arfs_close ((vnop_close_t)vop_nullop)
66: static int arfs_read (vnode_t, file_t, void *, size_t, size_t *);
67: #define arfs_write ((vnop_write_t)vop_nullop)
68: static int arfs_seek (vnode_t, file_t, off_t, off_t);
69: #define arfs_ioctl ((vnop_ioctl_t)vop_einval)
70: #define arfs_fsync ((vnop_fsync_t)vop_nullop)
71: static int arfs_readdir (vnode_t, file_t, struct dirent *);
72: static int arfs_lookup (vnode_t, char *, vnode_t);
73: #define arfs_create ((vnop_create_t)vop_einval)
74: #define arfs_remove ((vnop_remove_t)vop_einval)
75: #define arfs_rename ((vnop_rename_t)vop_einval)
76: #define arfs_mkdir ((vnop_mkdir_t)vop_einval)
77: #define arfs_rmdir ((vnop_rmdir_t)vop_einval)
78: #define arfs_getattr ((vnop_getattr_t)vop_nullop)
79: #define arfs_setattr ((vnop_setattr_t)vop_nullop)
80: #define arfs_inactive ((vnop_inactive_t)vop_nullop)
81: #define arfs_truncate ((vnop_truncate_t)vop_nullop)
82:
83: static char iobuf[BSIZE*2];
84:
85: #if CONFIG_FS_THREADS > 1
86: static mutex_t arfs_lock = MUTEX_INITIALIZER;
87: #endif
88:
89: /*
90: * vnode operations
91: */
92: const struct vnops arfs_vnops = {
93: arfs_open, /* open */
94: arfs_close, /* close */
95: arfs_read, /* read */
96: arfs_write, /* write */
97: arfs_seek, /* seek */
98: arfs_ioctl, /* ioctl */
99: arfs_fsync, /* fsync */
100: arfs_readdir, /* readdir */
101: arfs_lookup, /* lookup */
102: arfs_create, /* create */
103: arfs_remove, /* remove */
104: arfs_rename, /* remame */
105: arfs_mkdir, /* mkdir */
106: arfs_rmdir, /* rmdir */
107: arfs_getattr, /* getattr */
108: arfs_setattr, /* setattr */
109: arfs_inactive, /* inactive */
110: arfs_truncate, /* truncate */
111: };
112:
113: /*
114: * Read blocks.
115: * iobuf is filled by read data.
116: */
117: static int
118: arfs_readblk(mount_t mp, int blkno)
119: {
120: struct buf *bp;
121: int err;
122:
123: /*
124: * Read two blocks for archive header
125: */
126: if ((err = bread(mp->m_dev, blkno, &bp)) != 0)
127: return err;
128: memcpy(iobuf, bp->b_data, BSIZE);
129: brelse(bp);
130:
131: if ((err = bread(mp->m_dev, blkno + 1, &bp)) != 0)
132: return err;
133: memcpy(iobuf + BSIZE, bp->b_data, BSIZE);
134: brelse(bp);
135:
136: return 0;
137: }
138:
139: /*
140: * Lookup vnode for the specified file/directory.
141: * The vnode is filled properly.
142: */
143: static int
144: arfs_lookup(vnode_t dvp, char *name, vnode_t vp)
145: {
146: struct ar_hdr *hdr;
147: int blkno, err;
148: off_t off;
149: size_t size;
150: mount_t mp;
151: char *p;
152:
153: DPRINTF(("arfs_lookup: name=%s\n", name));
154: if (*name == '\0')
155: return ENOENT;
156:
157: mutex_lock(&arfs_lock);
158:
159: err = ENOENT;
160: mp = vp->v_mount;
161: blkno = 0;
162: off = SARMAG; /* offset in archive image */
163: for (;;) {
164: /* Read two blocks for archive header */
165: if (arfs_readblk(mp, blkno) != 0)
166: goto out;
167:
168: /* Check file header */
169: hdr = (struct ar_hdr *)(iobuf + (off % BSIZE));
170: if (strncmp(hdr->ar_fmag, ARFMAG, sizeof(ARFMAG) - 1))
171: goto out;
172:
173: /* Get file size */
174: size = (size_t)atol((char *)&hdr->ar_size);
175: if (size == 0)
176: goto out;
177:
178: /* Convert archive name */
179: if ((p = memchr(&hdr->ar_name, '/', 16)) != NULL)
180: *p = '\0';
181:
182: if (strncmp(name, (char *)&hdr->ar_name, 16) == 0)
183: break;
184:
185: /* Proceed to next archive header */
186: off += (sizeof(struct ar_hdr) + size);
187: off += (off % 2); /* Pad to even boundary */
188:
189: blkno = (int)(off / BSIZE);
190: }
191: vp->v_type = VREG;
192:
193: /* No write access */
194: vp->v_mode = S_IRUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH;
195: vp->v_size = size;
196: vp->v_blkno = blkno;
197: vp->v_data = (void *)(off + sizeof(struct ar_hdr));
198: err = 0;
199: out:
200: mutex_unlock(&arfs_lock);
201: DPRINTF(("arfs_lookup: err=%d\n\n", err));
202: return err;
203: }
204:
205: static int
206: arfs_read(vnode_t vp, file_t fp, void *buf, size_t size, size_t *result)
207: {
208: off_t off, file_pos, buf_pos;
209: int blkno, err;
210: size_t nr_read, nr_copy;
211: mount_t mp;
212: struct buf *bp;
213:
214: DPRINTF(("arfs_read: start size=%d\n", size));
215: mutex_lock(&arfs_lock);
216:
217: *result = 0;
218: mp = vp->v_mount;
219:
220: /* Check if current file position is already end of file. */
221: file_pos = fp->f_offset;
222: if (file_pos >= (off_t)vp->v_size) {
223: err = 0;
224: goto out;
225: }
226: /* Get the actual read size. */
227: if (vp->v_size - file_pos < size)
228: size = vp->v_size - file_pos;
229:
230: /* Read and copy data */
231: off = (off_t)vp->v_data;
232: nr_read = 0;
233: for (;;) {
234: DPRINTF(("arfs_read: file_pos=%d buf=%x size=%d\n",
235: file_pos, buf, size));
236:
237: blkno = (off + file_pos) / BSIZE;
238: buf_pos = (off + file_pos) % BSIZE;
239: if ((err = bread(mp->m_dev, blkno, &bp)) != 0)
240: goto out;
241: nr_copy = BSIZE;
242: if (buf_pos > 0)
243: nr_copy -= buf_pos;
244: if (buf_pos + size < BSIZE)
245: nr_copy = size;
246: ASSERT(nr_copy > 0);
247: memcpy(buf, bp->b_data + buf_pos, nr_copy);
248: brelse(bp);
249:
250: file_pos += nr_copy;
251: DPRINTF(("arfs_read: file_pos=%d nr_copy=%d\n",
252: file_pos, nr_copy));
253:
254: nr_read += nr_copy;
255: size -= nr_copy;
256: if (size <= 0)
257: break;
258: buf = (void *)((u_long)buf + nr_copy);
259: buf_pos = 0;
260: }
261: fp->f_offset = file_pos;
262: *result = nr_read;
263: err = 0;
264: out:
265: mutex_unlock(&arfs_lock);
266: DPRINTF(("arfs_read: err=%d\n\n", err));
267: return err;
268: }
269:
270: /*
271: * Check if the seek offset is valid.
272: */
273: static int
274: arfs_seek(vnode_t vp, file_t fp, off_t oldoff, off_t newoff)
275: {
276:
277: if (newoff > (off_t)vp->v_size)
278: return -1;
279:
280: return 0;
281: }
282:
283: static int
284: arfs_readdir(vnode_t vp, file_t fp, struct dirent *dir)
285: {
286: struct ar_hdr *hdr;
287: int blkno, i, err;
288: off_t off;
289: size_t size;
290: mount_t mp;
291: char *p;
292:
293: DPRINTF(("arfs_readdir: start\n"));
294: mutex_lock(&arfs_lock);
295:
296: i = 0;
297: mp = vp->v_mount;
298: blkno = 0;
299: off = SARMAG; /* offset in archive image */
300: for (;;) {
301: /* Read two blocks for archive header */
302: if ((err = arfs_readblk(mp, blkno)) != 0)
303: goto out;
304:
305: hdr = (struct ar_hdr *)(iobuf + (off % BSIZE));
306:
307: /* Get file size */
308: size = (size_t)atol((char *)&hdr->ar_size);
309: if (size == 0) {
310: err = ENOENT;
311: goto out;
312: }
313: if (i == fp->f_offset)
314: break;
315:
316: /* Proceed to next archive header */
317: off += (sizeof(struct ar_hdr) + size);
318: off += (off % 2); /* Pad to even boundary */
319:
320: blkno = off / BSIZE;
321: i++;
322: }
323:
324: /* Convert archive name */
325: if ((p = memchr(&hdr->ar_name, '/', 16)) != NULL)
326: *p = '\0';
327:
328: strcpy((char *)&dir->d_name, (char *)&hdr->ar_name);
329: dir->d_namlen = strlen(dir->d_name);
330: dir->d_fileno = fp->f_offset;
331: dir->d_type = DT_REG;
332:
333: fp->f_offset++;
334: err = 0;
335: out:
336: mutex_unlock(&arfs_lock);
337: return err;
338: }
339:
340:
341: int
342: arfs_init(void)
343: {
344: return 0;
345: }
CVSweb