[BACK]Return to ramfs_vnops.c CVS log [TXT][DIR] Up to [local] / prex-old / usr / server / fs / ramfs

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

CVSweb