Annotation of prex-old/usr/server/fs/ramfs/ramfs_vnops.c, Revision 1.1.1.1.2.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:
1.1.1.1.2.1! nbrk 30: /*
! 31: * rmafs_vnops.c - vnode operations for RAM file system.
! 32: */
! 33:
1.1 nbrk 34: #include <prex/prex.h>
35:
36: #include <sys/stat.h>
37: #include <sys/vnode.h>
38: #include <sys/file.h>
39: #include <sys/mount.h>
40: #include <sys/dirent.h>
41: #include <sys/param.h>
42:
43: #include <errno.h>
44: #include <string.h>
45: #include <stdlib.h>
46: #include <fcntl.h>
47:
48: #include "ramfs.h"
49:
50: #define ramfs_open ((vnop_open_t)vop_nullop)
51: #define ramfs_close ((vnop_close_t)vop_nullop)
1.1.1.1.2.1! nbrk 52: static int ramfs_read (vnode_t, file_t, void *, size_t, size_t *);
! 53: static int ramfs_write (vnode_t, file_t, void *, size_t, size_t *);
1.1 nbrk 54: #define ramfs_seek ((vnop_seek_t)vop_nullop)
55: #define ramfs_ioctl ((vnop_ioctl_t)vop_einval)
56: #define ramfs_fsync ((vnop_fsync_t)vop_nullop)
57: static int ramfs_readdir(vnode_t, file_t, struct dirent *);
1.1.1.1.2.1! nbrk 58: static int ramfs_lookup (vnode_t, char *, vnode_t);
! 59: static int ramfs_create (vnode_t, char *, mode_t);
! 60: static int ramfs_remove (vnode_t, vnode_t, char *);
! 61: static int ramfs_rename (vnode_t, vnode_t, char *, vnode_t, vnode_t, char *);
! 62: static int ramfs_mkdir (vnode_t, char *, mode_t);
! 63: static int ramfs_rmdir (vnode_t, vnode_t, char *);
1.1 nbrk 64: #define ramfs_getattr ((vnop_getattr_t)vop_nullop)
65: #define ramfs_setattr ((vnop_setattr_t)vop_nullop)
66: #define ramfs_inactive ((vnop_inactive_t)vop_nullop)
67: static int ramfs_truncate(vnode_t);
68:
69:
70: #if CONFIG_FS_THREADS > 1
71: static mutex_t ramfs_lock = MUTEX_INITIALIZER;
72: #endif
73:
74: /*
75: * vnode operations
76: */
77: struct vnops ramfs_vnops = {
78: ramfs_open, /* open */
79: ramfs_close, /* close */
80: ramfs_read, /* read */
81: ramfs_write, /* write */
82: ramfs_seek, /* seek */
83: ramfs_ioctl, /* ioctl */
84: ramfs_fsync, /* fsync */
85: ramfs_readdir, /* readdir */
86: ramfs_lookup, /* lookup */
87: ramfs_create, /* create */
88: ramfs_remove, /* remove */
89: ramfs_rename, /* remame */
90: ramfs_mkdir, /* mkdir */
91: ramfs_rmdir, /* rmdir */
92: ramfs_getattr, /* getattr */
93: ramfs_setattr, /* setattr */
94: ramfs_inactive, /* inactive */
95: ramfs_truncate, /* truncate */
96: };
97:
98: struct ramfs_node *
99: ramfs_allocate_node(char *name, int type)
100: {
1.1.1.1.2.1! nbrk 101: struct ramfs_node *np;
1.1 nbrk 102:
1.1.1.1.2.1! nbrk 103: np = malloc(sizeof(struct ramfs_node));
! 104: if (np == NULL)
1.1 nbrk 105: return NULL;
1.1.1.1.2.1! nbrk 106: memset(np, 0, sizeof(struct ramfs_node));
1.1 nbrk 107:
1.1.1.1.2.1! nbrk 108: np->rn_namelen = strlen(name);
! 109: np->rn_name = malloc(np->rn_namelen + 1);
! 110: if (np->rn_name == NULL) {
! 111: free(np);
1.1 nbrk 112: return NULL;
113: }
1.1.1.1.2.1! nbrk 114: strcpy(np->rn_name, name);
! 115: np->rn_type = type;
! 116: return np;
1.1 nbrk 117: }
118:
119: void
1.1.1.1.2.1! nbrk 120: ramfs_free_node(struct ramfs_node *np)
1.1 nbrk 121: {
122:
1.1.1.1.2.1! nbrk 123: free(np->rn_name);
! 124: free(np);
1.1 nbrk 125: }
126:
127: static struct ramfs_node *
1.1.1.1.2.1! nbrk 128: ramfs_add_node(struct ramfs_node *dnp, char *name, int type)
1.1 nbrk 129: {
1.1.1.1.2.1! nbrk 130: struct ramfs_node *np, *prev;
1.1 nbrk 131:
1.1.1.1.2.1! nbrk 132: np = ramfs_allocate_node(name, type);
! 133: if (np == NULL)
1.1 nbrk 134: return NULL;
135:
136: mutex_lock(&ramfs_lock);
137:
138: /* Link to the directory list */
1.1.1.1.2.1! nbrk 139: if (dnp->rn_child == NULL) {
! 140: dnp->rn_child = np;
1.1 nbrk 141: } else {
1.1.1.1.2.1! nbrk 142: prev = dnp->rn_child;
! 143: while (prev->rn_next != NULL)
! 144: prev = prev->rn_next;
! 145: prev->rn_next = np;
1.1 nbrk 146: }
147: mutex_unlock(&ramfs_lock);
1.1.1.1.2.1! nbrk 148: return np;
1.1 nbrk 149: }
150:
151: static int
1.1.1.1.2.1! nbrk 152: ramfs_remove_node(struct ramfs_node *dnp, struct ramfs_node *np)
1.1 nbrk 153: {
154: struct ramfs_node *prev;
155:
1.1.1.1.2.1! nbrk 156: if (dnp->rn_child == NULL)
1.1 nbrk 157: return EBUSY;
158:
159: mutex_lock(&ramfs_lock);
160:
161: /* Unlink from the directory list */
1.1.1.1.2.1! nbrk 162: if (dnp->rn_child == np) {
! 163: dnp->rn_child = np->rn_next;
1.1 nbrk 164: } else {
1.1.1.1.2.1! nbrk 165: for (prev = dnp->rn_child; prev->rn_next != np;
! 166: prev = prev->rn_next) {
! 167: if (prev->rn_next == NULL) {
1.1 nbrk 168: mutex_unlock(&ramfs_lock);
169: return ENOENT;
170: }
171: }
1.1.1.1.2.1! nbrk 172: prev->rn_next = np->rn_next;
1.1 nbrk 173: }
1.1.1.1.2.1! nbrk 174: ramfs_free_node(np);
1.1 nbrk 175:
176: mutex_unlock(&ramfs_lock);
177: return 0;
178: }
179:
180: static int
1.1.1.1.2.1! nbrk 181: ramfs_rename_node(struct ramfs_node *np, char *name)
1.1 nbrk 182: {
183: size_t len;
184: char *tmp;
185:
186: len = strlen(name);
1.1.1.1.2.1! nbrk 187: if (len <= np->rn_namelen) {
1.1 nbrk 188: /* Reuse current name buffer */
1.1.1.1.2.1! nbrk 189: strcpy(np->rn_name, name);
1.1 nbrk 190: } else {
191: /* Expand name buffer */
192: tmp = malloc(len + 1);
193: if (tmp == NULL)
194: return ENOMEM;
195: strcpy(tmp, name);
1.1.1.1.2.1! nbrk 196: free(np->rn_name);
! 197: np->rn_name = tmp;
1.1 nbrk 198: }
1.1.1.1.2.1! nbrk 199: np->rn_namelen = len;
1.1 nbrk 200: return 0;
201: }
202:
203: static int
204: ramfs_lookup(vnode_t dvp, char *name, vnode_t vp)
205: {
1.1.1.1.2.1! nbrk 206: struct ramfs_node *np, *dnp;
1.1 nbrk 207: size_t len;
1.1.1.1.2.1! nbrk 208: int found;
1.1 nbrk 209:
210: if (*name == '\0')
211: return ENOENT;
212:
213: mutex_lock(&ramfs_lock);
214:
215: len = strlen(name);
1.1.1.1.2.1! nbrk 216: dnp = dvp->v_data;
! 217: found = 0;
! 218: for (np = dnp->rn_child; np != NULL; np = np->rn_next) {
! 219: if (np->rn_namelen == len &&
! 220: memcmp(name, np->rn_name, len) == 0) {
! 221: found = 1;
1.1 nbrk 222: break;
1.1.1.1.2.1! nbrk 223: }
1.1 nbrk 224: }
1.1.1.1.2.1! nbrk 225: if (found == 0) {
1.1 nbrk 226: mutex_unlock(&ramfs_lock);
227: return ENOENT;
228: }
1.1.1.1.2.1! nbrk 229: vp->v_data = np;
1.1 nbrk 230: vp->v_mode = ALLPERMS;
1.1.1.1.2.1! nbrk 231: vp->v_type = np->rn_type;
! 232: vp->v_size = np->rn_size;
1.1 nbrk 233:
234: mutex_unlock(&ramfs_lock);
235: return 0;
236: }
237:
238: static int
239: ramfs_mkdir(vnode_t dvp, char *name, mode_t mode)
240: {
1.1.1.1.2.1! nbrk 241: struct ramfs_node *np;
1.1 nbrk 242:
1.1.1.1.2.1! nbrk 243: DPRINTF(("mkdir %s\n", name));
1.1 nbrk 244: if (!S_ISDIR(mode))
245: return EINVAL;
246:
1.1.1.1.2.1! nbrk 247: np = ramfs_add_node(dvp->v_data, name, VDIR);
! 248: if (np == NULL)
1.1 nbrk 249: return ENOMEM;
1.1.1.1.2.1! nbrk 250: np->rn_size = 0;
1.1 nbrk 251: return 0;
252: }
253:
254: /* Remove a directory */
255: static int
256: ramfs_rmdir(vnode_t dvp, vnode_t vp, char *name)
257: {
258:
259: return ramfs_remove_node(dvp->v_data, vp->v_data);
260: }
261:
262: /* Remove a file */
263: static int
264: ramfs_remove(vnode_t dvp, vnode_t vp, char *name)
265: {
1.1.1.1.2.1! nbrk 266: struct ramfs_node *np;
1.1 nbrk 267: int err;
268:
1.1.1.1.2.1! nbrk 269: DPRINTF(("remove %s in %s\n", name, dvp->v_path));
1.1 nbrk 270: err = ramfs_remove_node(dvp->v_data, vp->v_data);
271: if (err)
272: return err;
273:
1.1.1.1.2.1! nbrk 274: np = vp->v_data;
! 275: if (np->rn_buf != NULL)
! 276: vm_free(task_self(), np->rn_buf);
1.1 nbrk 277: return 0;
278: }
279:
280: /* Truncate file */
281: static int
282: ramfs_truncate(vnode_t vp)
283: {
1.1.1.1.2.1! nbrk 284: struct ramfs_node *np;
1.1 nbrk 285:
1.1.1.1.2.1! nbrk 286: DPRINTF(("truncate %s\n", vp->v_path));
! 287: np = vp->v_data;
! 288: if (np->rn_buf != NULL) {
! 289: vm_free(task_self(), np->rn_buf);
! 290: np->rn_buf = NULL;
! 291: np->rn_bufsize = 0;
1.1 nbrk 292: }
293: vp->v_size = 0;
294: return 0;
295: }
296:
297: /*
298: * Create empty file.
299: */
300: static int
301: ramfs_create(vnode_t dvp, char *name, mode_t mode)
302: {
1.1.1.1.2.1! nbrk 303: struct ramfs_node *np;
1.1 nbrk 304:
1.1.1.1.2.1! nbrk 305: DPRINTF(("create %s in %s\n", name, dvp->v_path));
1.1 nbrk 306: if (!S_ISREG(mode))
307: return EINVAL;
308:
1.1.1.1.2.1! nbrk 309: np = ramfs_add_node(dvp->v_data, name, VREG);
! 310: if (np == NULL)
1.1 nbrk 311: return ENOMEM;
312: return 0;
313: }
314:
315: static int
316: ramfs_read(vnode_t vp, file_t fp, void *buf, size_t size, size_t *result)
317: {
1.1.1.1.2.1! nbrk 318: struct ramfs_node *np;
1.1 nbrk 319: off_t off;
320:
321: *result = 0;
322: if (vp->v_type == VDIR)
323: return EISDIR;
324: if (vp->v_type != VREG)
325: return EINVAL;
326:
327: off = fp->f_offset;
328: if (off >= (off_t)vp->v_size)
329: return 0;
330:
331: if (vp->v_size - off < size)
332: size = vp->v_size - off;
333:
1.1.1.1.2.1! nbrk 334: np = vp->v_data;
! 335: memcpy(buf, np->rn_buf + off, size);
1.1 nbrk 336:
337: fp->f_offset += size;
338: *result = size;
339: return 0;
340: }
341:
342: static int
343: ramfs_write(vnode_t vp, file_t fp, void *buf, size_t size, size_t *result)
344: {
1.1.1.1.2.1! nbrk 345: struct ramfs_node *np;
1.1 nbrk 346: off_t file_pos, end_pos;
347: void *new_buf;
348: size_t new_size;
349: task_t task;
350:
351: *result = 0;
352: if (vp->v_type == VDIR)
353: return EISDIR;
354: if (vp->v_type != VREG)
355: return EINVAL;
356:
1.1.1.1.2.1! nbrk 357: np = vp->v_data;
1.1 nbrk 358: /* Check if the file position exceeds the end of file. */
359: end_pos = vp->v_size;
360: file_pos = (fp->f_flags & O_APPEND) ? end_pos : fp->f_offset;
361: if (file_pos + size > (size_t)end_pos) {
362: /* Expand the file size before writing to it */
363: end_pos = file_pos + size;
1.1.1.1.2.1! nbrk 364: if (end_pos > (off_t)np->rn_bufsize) {
1.1 nbrk 365: task = task_self();
366: /*
367: * We allocate the data buffer in page boundary.
368: * So that we can reduce the memory allocation unless
369: * the file size exceeds next page boundary.
370: * This will prevent the memory fragmentation by
371: * many malloc/free calls.
372: */
373: new_size = PAGE_ALIGN(end_pos);
374: if (vm_allocate(task, &new_buf, new_size, 1))
375: return EIO;
1.1.1.1.2.1! nbrk 376: if (np->rn_size != 0) {
! 377: memcpy(new_buf, np->rn_buf, vp->v_size);
! 378: vm_free(task, np->rn_buf);
1.1 nbrk 379: }
1.1.1.1.2.1! nbrk 380: np->rn_buf = new_buf;
! 381: np->rn_bufsize = new_size;
1.1 nbrk 382: }
1.1.1.1.2.1! nbrk 383: np->rn_size = end_pos;
1.1 nbrk 384: vp->v_size = end_pos;
385: }
1.1.1.1.2.1! nbrk 386: memcpy(np->rn_buf + file_pos, buf, size);
1.1 nbrk 387: fp->f_offset += size;
388: *result = size;
389: return 0;
390: }
391:
392: static int
393: ramfs_rename(vnode_t dvp1, vnode_t vp1, char *name1,
394: vnode_t dvp2, vnode_t vp2, char *name2)
395: {
1.1.1.1.2.1! nbrk 396: struct ramfs_node *np, *old_np;
1.1 nbrk 397: int err;
398:
399: if (vp2) {
400: /* Remove destination file, first */
401: err = ramfs_remove_node(dvp2->v_data, vp2->v_data);
402: if (err)
403: return err;
404: }
405: /* Same directory ? */
406: if (dvp1 == dvp2) {
407: /* Change the name of existing file */
408: err = ramfs_rename_node(vp1->v_data, name2);
409: if (err)
410: return err;
411: } else {
412: /* Create new file or directory */
1.1.1.1.2.1! nbrk 413: old_np = vp1->v_data;
! 414: np = ramfs_add_node(dvp2->v_data, name2, VREG);
! 415: if (np == NULL)
1.1 nbrk 416: return ENOMEM;
417:
418: if (vp1->v_type == VREG) {
419: /* Copy file data */
1.1.1.1.2.1! nbrk 420: np->rn_buf = old_np->rn_buf;
! 421: np->rn_size = old_np->rn_size;
! 422: np->rn_bufsize = old_np->rn_bufsize;
1.1 nbrk 423: }
424: /* Remove source file */
425: ramfs_remove_node(dvp1->v_data, vp1->v_data);
426: }
427: return 0;
428: }
429:
430: /*
431: * @vp: vnode of the directory.
432: */
433: static int
434: ramfs_readdir(vnode_t vp, file_t fp, struct dirent *dir)
435: {
1.1.1.1.2.1! nbrk 436: struct ramfs_node *np, *dnp;
1.1 nbrk 437: int i;
438:
439: mutex_lock(&ramfs_lock);
440:
441: if (fp->f_offset == 0) {
442: dir->d_type = DT_DIR;
443: strcpy((char *)&dir->d_name, ".");
444: } else if (fp->f_offset == 1) {
445: dir->d_type = DT_DIR;
446: strcpy((char *)&dir->d_name, "..");
447: } else {
1.1.1.1.2.1! nbrk 448: dnp = vp->v_data;
! 449: np = dnp->rn_child;
! 450: if (np == NULL) {
1.1 nbrk 451: mutex_unlock(&ramfs_lock);
452: return ENOENT;
453: }
454:
455: for (i = 0; i != (fp->f_offset - 2); i++) {
1.1.1.1.2.1! nbrk 456: np = np->rn_next;
! 457: if (np == NULL) {
1.1 nbrk 458: mutex_unlock(&ramfs_lock);
459: return ENOENT;
460: }
461: }
1.1.1.1.2.1! nbrk 462: if (np->rn_type == VDIR)
1.1 nbrk 463: dir->d_type = DT_DIR;
464: else
465: dir->d_type = DT_REG;
1.1.1.1.2.1! nbrk 466: strcpy((char *)&dir->d_name, np->rn_name);
1.1 nbrk 467: }
468: dir->d_fileno = fp->f_offset;
469: dir->d_namlen = strlen(dir->d_name);
470:
471: fp->f_offset++;
472:
473: mutex_unlock(&ramfs_lock);
474: return 0;
475: }
476:
477: int
478: ramfs_init(void)
479: {
480: return 0;
481: }
CVSweb