Annotation of prex-old/usr/server/fs/arfs/arfs_vnops.c, Revision 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