Prex Home / Browse Source - Prex Version: 0.9.0

root/usr/server/fs/arfs/arfs_vnops.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. arfs_readblk
  2. arfs_lookup
  3. arfs_read
  4. arfs_seek
  5. arfs_readdir
  6. arfs_init

   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 <sys/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 error;
 122 
 123         /*
 124          * Read two blocks for archive header
 125          */
 126         if ((error = bread(mp->m_dev, blkno, &bp)) != 0)
 127                 return error;
 128         memcpy(iobuf, bp->b_data, BSIZE);
 129         brelse(bp);
 130 
 131         if ((error = bread(mp->m_dev, blkno + 1, &bp)) != 0)
 132                 return error;
 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, error;
 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         error = 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 = (mode_t)(S_IRUSR | S_IXUSR);
 195         vp->v_size = size;
 196         vp->v_blkno = blkno;
 197         vp->v_data = (void *)(off + sizeof(struct ar_hdr));
 198         error = 0;
 199  out:
 200         mutex_unlock(&arfs_lock);
 201         DPRINTF(("arfs_lookup: error=%d\n\n", error));
 202         return error;
 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, error;
 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                 error = 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 ((error = 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         error = 0;
 264  out:
 265         mutex_unlock(&arfs_lock);
 266         DPRINTF(("arfs_read: error=%d\n\n", error));
 267         return error;
 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, error;
 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 ((error = 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                         error = 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         strlcpy((char *)&dir->d_name, (char *)&hdr->ar_name,
 329                 sizeof(dir->d_name));
 330         dir->d_namlen = (uint16_t)strlen(dir->d_name);
 331         dir->d_fileno = (uint32_t)fp->f_offset;
 332         dir->d_type = DT_REG;
 333 
 334         fp->f_offset++;
 335         error = 0;
 336  out:
 337         mutex_unlock(&arfs_lock);
 338         return error;
 339 }
 340 
 341 
 342 int
 343 arfs_init(void)
 344 {
 345         return 0;
 346 }

/* [<][>][^][v][top][bottom][index][help] */