|
|||
Prex Home / Browse Source - Prex Version: 0.9.0 |
|||
root/usr/server/fs/arfs/arfs_vnops.c/* [<][>][^][v][top][bottom][index][help] */DEFINITIONSThis source file includes following definitions.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] */ | |||
Copyright© 2005-2009 Kohsuke Ohtani |