[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Minios-devel] [UNIKRAFT PATCH 1/6] lib/ramfs: initial import from OSv



git tag: v0.52.0
commit: 00299190414e4c7c5b0f2d74cd11763dac34e5b9

Signed-off-by: Yuri Volchkov <yuri.volchkov@xxxxxxxxx>
---
 lib/ramfs/ramfs.h        |  68 ++++
 lib/ramfs/ramfs_vfsops.c |  90 ++++++
 lib/ramfs/ramfs_vnops.c  | 669 +++++++++++++++++++++++++++++++++++++++
 3 files changed, 827 insertions(+)
 create mode 100644 lib/ramfs/ramfs.h
 create mode 100644 lib/ramfs/ramfs_vfsops.c
 create mode 100644 lib/ramfs/ramfs_vnops.c

diff --git a/lib/ramfs/ramfs.h b/lib/ramfs/ramfs.h
new file mode 100644
index 00000000..88ccbe72
--- /dev/null
+++ b/lib/ramfs/ramfs.h
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2006-2007, Kohsuke Ohtani
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the author nor the names of any co-contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _RAMFS_H
+#define _RAMFS_H
+
+#include <osv/prex.h>
+
+/* #define DEBUG_RAMFS 1 */
+
+#ifdef DEBUG_RAMFS
+#define DPRINTF(a)     dprintf a
+#else
+#define DPRINTF(a)    do {} while (0)
+#endif
+
+#define ASSERT(e)    assert(e)
+
+/*
+ * File/directory node for RAMFS
+ */
+struct ramfs_node {
+    struct ramfs_node *rn_next;   /* next node in the same directory */
+    struct ramfs_node *rn_child;  /* first child node */
+    int rn_type;    /* file or directory */
+    char *rn_name;    /* name (null-terminated) */
+    size_t rn_namelen;    /* length of name not including terminator */
+    size_t rn_size;    /* file size */
+    char *rn_buf;    /* buffer to the file data */
+    size_t rn_bufsize;    /* allocated buffer size */
+    struct timespec rn_ctime;
+    struct timespec rn_atime;
+    struct timespec rn_mtime;
+    int rn_mode;
+    bool rn_owns_buf;
+};
+
+struct ramfs_node *ramfs_allocate_node(const char *name, int type);
+
+void ramfs_free_node(struct ramfs_node *node);
+
+#endif /* !_RAMFS_H */
diff --git a/lib/ramfs/ramfs_vfsops.c b/lib/ramfs/ramfs_vfsops.c
new file mode 100644
index 00000000..72fe7edb
--- /dev/null
+++ b/lib/ramfs/ramfs_vfsops.c
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2006-2007, Kohsuke Ohtani
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the author nor the names of any co-contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <errno.h>
+
+#include <osv/vnode.h>
+#include <osv/mount.h>
+#include <osv/dentry.h>
+
+#include "ramfs.h"
+
+extern struct vnops ramfs_vnops;
+
+static int ramfs_mount(struct mount *mp, const char *dev, int flags, const 
void *data);
+
+static int ramfs_unmount(struct mount *mp, int flags);
+
+#define ramfs_sync    ((vfsop_sync_t)vfs_nullop)
+#define ramfs_vget    ((vfsop_vget_t)vfs_nullop)
+#define ramfs_statfs    ((vfsop_statfs_t)vfs_nullop)
+
+/*
+ * File system operations
+ */
+struct vfsops ramfs_vfsops = {
+        ramfs_mount,       /* mount */
+        ramfs_unmount,     /* unmount */
+        ramfs_sync,        /* sync */
+        ramfs_vget,        /* vget */
+        ramfs_statfs,      /* statfs */
+        &ramfs_vnops,      /* vnops */
+};
+
+/*
+ * Mount a file system.
+ */
+static int
+ramfs_mount(struct mount *mp, const char *dev, int flags, const void *data)
+{
+    struct ramfs_node *np;
+
+    DPRINTF(("ramfs_mount: dev=%s\n", dev));
+
+    /* Create a root node */
+    np = ramfs_allocate_node("/", VDIR);
+    if (np == NULL)
+        return ENOMEM;
+    mp->m_root->d_vnode->v_data = np;
+    return 0;
+}
+
+/*
+ * Unmount a file system.
+ *
+ * NOTE: Currently, we don't support unmounting of the RAMFS. This is
+ *       because we have to deallocate all nodes included in all sub
+ *       directories, and it requires more work...
+ */
+static int
+ramfs_unmount(struct mount *mp, int flags)
+{
+    release_mp_dentries(mp);
+    return 0;
+}
diff --git a/lib/ramfs/ramfs_vnops.c b/lib/ramfs/ramfs_vnops.c
new file mode 100644
index 00000000..9291a4ec
--- /dev/null
+++ b/lib/ramfs/ramfs_vnops.c
@@ -0,0 +1,669 @@
+/*
+ * Copyright (c) 2006-2007, Kohsuke Ohtani
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the author nor the names of any co-contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * rmafs_vnops.c - vnode operations for RAM file system.
+ */
+
+#include <sys/stat.h>
+#include <dirent.h>
+#include <sys/param.h>
+
+#include <errno.h>
+#include <string.h>
+#include <stdlib.h>
+#include <fcntl.h>
+
+#include <osv/prex.h>
+#include <osv/vnode.h>
+#include <osv/file.h>
+#include <osv/mount.h>
+#include <osv/vnode_attr.h>
+
+#include "ramfs.h"
+
+static mutex_t ramfs_lock = MUTEX_INITIALIZER;
+static uint64_t inode_count = 1; /* inode 0 is reserved to root */
+
+static void
+set_times_to_now(struct timespec *time1, struct timespec *time2 = nullptr, 
struct timespec *time3 = nullptr)
+{
+    struct timespec now;
+    clock_gettime(CLOCK_REALTIME, &now);
+    if (time1) {
+        memcpy(time1, &now, sizeof(struct timespec));
+    }
+    if (time2) {
+        memcpy(time2, &now, sizeof(struct timespec));
+    }
+    if (time3) {
+        memcpy(time3, &now, sizeof(struct timespec));
+    }
+}
+
+struct ramfs_node *
+ramfs_allocate_node(const char *name, int type)
+{
+    struct ramfs_node *np;
+
+    np = (ramfs_node *) malloc(sizeof(struct ramfs_node));
+    if (np == NULL)
+        return NULL;
+    memset(np, 0, sizeof(struct ramfs_node));
+
+    np->rn_namelen = strlen(name);
+    np->rn_name = (char *) malloc(np->rn_namelen + 1);
+    if (np->rn_name == NULL) {
+        free(np);
+        return NULL;
+    }
+    strlcpy(np->rn_name, name, np->rn_namelen + 1);
+    np->rn_type = type;
+
+    if (type == VDIR)
+        np->rn_mode = S_IFDIR|0777;
+    else if (type == VLNK)
+        np->rn_mode = S_IFLNK|0777;
+    else
+        np->rn_mode = S_IFREG|0777;
+
+    set_times_to_now(&(np->rn_ctime), &(np->rn_atime), &(np->rn_mtime));
+    np->rn_owns_buf = true;
+
+    return np;
+}
+
+void
+ramfs_free_node(struct ramfs_node *np)
+{
+    if (np->rn_buf != NULL && np->rn_owns_buf)
+        free(np->rn_buf);
+
+    free(np->rn_name);
+    free(np);
+}
+
+static struct ramfs_node *
+ramfs_add_node(struct ramfs_node *dnp, char *name, int type)
+{
+    struct ramfs_node *np, *prev;
+
+    np = ramfs_allocate_node(name, type);
+    if (np == NULL)
+        return NULL;
+
+    mutex_lock(&ramfs_lock);
+
+    /* Link to the directory list */
+    if (dnp->rn_child == NULL) {
+        dnp->rn_child = np;
+    } else {
+        prev = dnp->rn_child;
+        while (prev->rn_next != NULL)
+            prev = prev->rn_next;
+        prev->rn_next = np;
+    }
+
+    set_times_to_now(&(dnp->rn_mtime), &(dnp->rn_ctime));
+
+    mutex_unlock(&ramfs_lock);
+    return np;
+}
+
+static int
+ramfs_remove_node(struct ramfs_node *dnp, struct ramfs_node *np)
+{
+    struct ramfs_node *prev;
+
+    if (dnp->rn_child == NULL)
+        return EBUSY;
+
+    mutex_lock(&ramfs_lock);
+
+    /* Unlink from the directory list */
+    if (dnp->rn_child == np) {
+        dnp->rn_child = np->rn_next;
+    } else {
+        for (prev = dnp->rn_child; prev->rn_next != np;
+             prev = prev->rn_next) {
+            if (prev->rn_next == NULL) {
+                mutex_unlock(&ramfs_lock);
+                return ENOENT;
+            }
+        }
+        prev->rn_next = np->rn_next;
+    }
+    ramfs_free_node(np);
+
+    set_times_to_now(&(dnp->rn_mtime), &(dnp->rn_ctime));
+
+    mutex_unlock(&ramfs_lock);
+    return 0;
+}
+
+static int
+ramfs_rename_node(struct ramfs_node *np, char *name)
+{
+    size_t len;
+    char *tmp;
+
+    len = strlen(name);
+    if (len > NAME_MAX) {
+        return ENAMETOOLONG;
+    }
+    if (len <= np->rn_namelen) {
+        /* Reuse current name buffer */
+        strlcpy(np->rn_name, name, np->rn_namelen + 1);
+    } else {
+        /* Expand name buffer */
+        tmp = (char *) malloc(len + 1);
+        if (tmp == NULL)
+            return ENOMEM;
+        strlcpy(tmp, name, len + 1);
+        free(np->rn_name);
+        np->rn_name = tmp;
+    }
+    np->rn_namelen = len;
+    set_times_to_now(&(np->rn_ctime));
+    return 0;
+}
+
+static int
+ramfs_lookup(struct vnode *dvp, char *name, struct vnode **vpp)
+{
+    struct ramfs_node *np, *dnp;
+    struct vnode *vp;
+    size_t len;
+    int found;
+
+    *vpp = NULL;
+
+    if (*name == '\0')
+        return ENOENT;
+
+    mutex_lock(&ramfs_lock);
+
+    len = strlen(name);
+    dnp = (ramfs_node *) dvp->v_data;
+    found = 0;
+    for (np = dnp->rn_child; np != NULL; np = np->rn_next) {
+        if (np->rn_namelen == len &&
+            memcmp(name, np->rn_name, len) == 0) {
+            found = 1;
+            break;
+        }
+    }
+    if (found == 0) {
+        mutex_unlock(&ramfs_lock);
+        return ENOENT;
+    }
+    if (vget(dvp->v_mount, inode_count++, &vp)) {
+        /* found in cache */
+        *vpp = vp;
+        mutex_unlock(&ramfs_lock);
+        return 0;
+    }
+    if (!vp) {
+        mutex_unlock(&ramfs_lock);
+        return ENOMEM;
+    }
+    vp->v_data = np;
+    vp->v_mode = ALLPERMS;
+    vp->v_type = np->rn_type;
+    vp->v_size = np->rn_size;
+
+    mutex_unlock(&ramfs_lock);
+
+    *vpp = vp;
+
+    return 0;
+}
+
+static int
+ramfs_mkdir(struct vnode *dvp, char *name, mode_t mode)
+{
+    struct ramfs_node *np;
+
+    DPRINTF(("mkdir %s\n", name));
+    if (strlen(name) > NAME_MAX) {
+        return ENAMETOOLONG;
+    }
+
+    if (!S_ISDIR(mode))
+        return EINVAL;
+
+    np = (ramfs_node *) ramfs_add_node((ramfs_node *) dvp->v_data, name, VDIR);
+    if (np == NULL)
+        return ENOMEM;
+    np->rn_size = 0;
+
+    return 0;
+}
+
+static int
+ramfs_symlink(struct vnode *dvp, char *name, char *link)
+{
+    if (strlen(name) > NAME_MAX) {
+        return ENAMETOOLONG;
+    }
+    auto np = ramfs_add_node((ramfs_node *) dvp->v_data, name, VLNK);
+    if (np == NULL)
+        return ENOMEM;
+    // Save the link target without the final null, as readlink() wants it.
+    size_t len = strlen(link);
+    np->rn_buf = strndup(link, len);
+    np->rn_bufsize = np->rn_size = len;
+
+    return 0;
+}
+
+static int
+ramfs_readlink(struct vnode *vp, struct uio *uio)
+{
+    struct ramfs_node *np = (ramfs_node *) vp->v_data;
+    size_t len;
+
+    if (vp->v_type != VLNK) {
+        return EINVAL;
+    }
+    if (uio->uio_offset < 0) {
+        return EINVAL;
+    }
+    if (uio->uio_resid == 0) {
+        return 0;
+    }
+    if (uio->uio_offset >= (off_t) vp->v_size)
+        return 0;
+    if (vp->v_size - uio->uio_offset < uio->uio_resid)
+        len = vp->v_size - uio->uio_offset;
+    else
+        len = uio->uio_resid;
+
+    set_times_to_now( &(np->rn_atime));
+    return uiomove(np->rn_buf + uio->uio_offset, len, uio);
+}
+
+/* Remove a directory */
+static int
+ramfs_rmdir(struct vnode *dvp, struct vnode *vp, char *name)
+{
+    return ramfs_remove_node((ramfs_node *) dvp->v_data, (ramfs_node *) 
vp->v_data);
+}
+
+/* Remove a file */
+static int
+ramfs_remove(struct vnode *dvp, struct vnode *vp, char *name)
+{
+    DPRINTF(("remove %s in %s\n", name, dvp->v_path));
+    return ramfs_remove_node((ramfs_node *) dvp->v_data, (ramfs_node *) 
vp->v_data);
+}
+
+/* Truncate file */
+static int
+ramfs_truncate(struct vnode *vp, off_t length)
+{
+    struct ramfs_node *np;
+    void *new_buf;
+    size_t new_size;
+
+    DPRINTF(("truncate %s length=%d\n", vp->v_path, length));
+    np = (ramfs_node *) vp->v_data;
+
+    if (length == 0) {
+        if (np->rn_buf != NULL) {
+            if(np->rn_owns_buf)
+                free(np->rn_buf);
+            np->rn_buf = NULL;
+            np->rn_bufsize = 0;
+        }
+    } else if (size_t(length) > np->rn_bufsize) {
+        // XXX: this could use a page level allocator
+        new_size = round_page(length);
+        new_buf = malloc(new_size);
+        if (!new_buf)
+            return EIO;
+        if (np->rn_size != 0) {
+            memcpy(new_buf, np->rn_buf, vp->v_size);
+            if(np->rn_owns_buf)
+                free(np->rn_buf);
+        }
+        np->rn_buf = (char *) new_buf;
+        np->rn_bufsize = new_size;
+        np->rn_owns_buf = true;
+    }
+    np->rn_size = length;
+    vp->v_size = length;
+    set_times_to_now(&(np->rn_mtime), &(np->rn_ctime));
+    return 0;
+}
+
+/*
+ * Create empty file.
+ */
+static int
+ramfs_create(struct vnode *dvp, char *name, mode_t mode)
+{
+    struct ramfs_node *np;
+
+    if (strlen(name) > NAME_MAX) {
+        return ENAMETOOLONG;
+    }
+
+    DPRINTF(("create %s in %s\n", name, dvp->v_path));
+    if (!S_ISREG(mode))
+        return EINVAL;
+
+    np = ramfs_add_node((ramfs_node *) dvp->v_data, name, VREG);
+    if (np == NULL)
+        return ENOMEM;
+    return 0;
+}
+
+static int
+ramfs_read(struct vnode *vp, struct file *fp, struct uio *uio, int ioflag)
+{
+    struct ramfs_node *np = (ramfs_node *) vp->v_data;
+    size_t len;
+
+    if (vp->v_type == VDIR) {
+        return EISDIR;
+    }
+    if (vp->v_type != VREG) {
+        return EINVAL;
+    }
+    if (uio->uio_offset < 0) {
+        return EINVAL;
+    }
+    if (uio->uio_resid == 0) {
+        return 0;
+    }
+
+    if (uio->uio_offset >= (off_t) vp->v_size)
+        return 0;
+
+    if (vp->v_size - uio->uio_offset < uio->uio_resid)
+        len = vp->v_size - uio->uio_offset;
+    else
+        len = uio->uio_resid;
+
+    set_times_to_now(&(np->rn_atime));
+
+    return uiomove(np->rn_buf + uio->uio_offset, len, uio);
+}
+
+int
+ramfs_set_file_data(struct vnode *vp, const void *data, size_t size)
+{
+    struct ramfs_node *np = (ramfs_node *) vp->v_data;
+
+    if (vp->v_type == VDIR) {
+        return EISDIR;
+    }
+    if (vp->v_type != VREG) {
+        return EINVAL;
+    }
+    if (np->rn_buf) {
+        return EINVAL;
+    }
+
+    np->rn_buf = (char *) data;
+    np->rn_bufsize = size;
+    np->rn_size = size;
+    vp->v_size = size;
+    np->rn_owns_buf = false;
+
+    return 0;
+}
+
+static int
+ramfs_write(struct vnode *vp, struct uio *uio, int ioflag)
+{
+    struct ramfs_node *np = (ramfs_node *) vp->v_data;
+
+    if (vp->v_type == VDIR) {
+        return EISDIR;
+    }
+    if (vp->v_type != VREG) {
+        return EINVAL;
+    }
+    if (uio->uio_offset < 0) {
+        return EINVAL;
+    }
+    if (uio->uio_offset >= LONG_MAX) {
+        return EFBIG;
+    }
+    if (uio->uio_resid == 0) {
+        return 0;
+    }
+
+    if (ioflag & IO_APPEND)
+        uio->uio_offset = np->rn_size;
+
+    if (size_t(uio->uio_offset + uio->uio_resid) > (size_t) vp->v_size) {
+        /* Expand the file size before writing to it */
+        off_t end_pos = uio->uio_offset + uio->uio_resid;
+        if (end_pos > (off_t) np->rn_bufsize) {
+            // XXX: this could use a page level allocator
+            size_t new_size = round_page(end_pos);
+            void *new_buf = malloc(new_size);
+            if (!new_buf)
+                return EIO;
+            if (np->rn_size != 0) {
+                memcpy(new_buf, np->rn_buf, vp->v_size);
+                if(np->rn_owns_buf)
+                    free(np->rn_buf);
+            }
+            np->rn_buf = (char *) new_buf;
+            np->rn_bufsize = new_size;
+        }
+        np->rn_size = end_pos;
+        vp->v_size = end_pos;
+        np->rn_owns_buf = true;
+    }
+
+    set_times_to_now(&(np->rn_mtime), &(np->rn_ctime));
+    return uiomove(np->rn_buf + uio->uio_offset, uio->uio_resid, uio);
+}
+
+static int
+ramfs_rename(struct vnode *dvp1, struct vnode *vp1, char *name1,
+             struct vnode *dvp2, struct vnode *vp2, char *name2)
+{
+    struct ramfs_node *np, *old_np;
+    int error;
+
+    if (vp2) {
+        /* Remove destination file, first */
+        error = ramfs_remove_node((ramfs_node *) dvp2->v_data, (ramfs_node *) 
vp2->v_data);
+        if (error)
+            return error;
+    }
+    /* Same directory ? */
+    if (dvp1 == dvp2) {
+        /* Change the name of existing file */
+        error = ramfs_rename_node((ramfs_node *) vp1->v_data, name2);
+        if (error)
+            return error;
+    } else {
+        /* Create new file or directory */
+        old_np = (ramfs_node *) vp1->v_data;
+        np = ramfs_add_node((ramfs_node *) dvp2->v_data, name2, 
old_np->rn_type);
+        if (np == NULL)
+            return ENOMEM;
+
+        if (old_np->rn_buf) {
+            /* Copy file data */
+            np->rn_buf = old_np->rn_buf;
+            np->rn_size = old_np->rn_size;
+            np->rn_bufsize = old_np->rn_bufsize;
+            old_np->rn_buf = NULL;
+        }
+        /* Remove source file */
+        ramfs_remove_node((ramfs_node *) dvp1->v_data, (ramfs_node *) 
vp1->v_data);
+    }
+    return 0;
+}
+
+/*
+ * @vp: vnode of the directory.
+ */
+static int
+ramfs_readdir(struct vnode *vp, struct file *fp, struct dirent *dir)
+{
+    struct ramfs_node *np, *dnp;
+    int i;
+
+    mutex_lock(&ramfs_lock);
+
+    set_times_to_now(&(((ramfs_node *) vp->v_data)->rn_atime));
+
+    if (fp->f_offset == 0) {
+        dir->d_type = DT_DIR;
+        strlcpy((char *) &dir->d_name, ".", sizeof(dir->d_name));
+    } else if (fp->f_offset == 1) {
+        dir->d_type = DT_DIR;
+        strlcpy((char *) &dir->d_name, "..", sizeof(dir->d_name));
+    } else {
+        dnp = (ramfs_node *) vp->v_data;
+        np = dnp->rn_child;
+        if (np == NULL) {
+            mutex_unlock(&ramfs_lock);
+            return ENOENT;
+        }
+
+        for (i = 0; i != (fp->f_offset - 2); i++) {
+            np = np->rn_next;
+            if (np == NULL) {
+                mutex_unlock(&ramfs_lock);
+                return ENOENT;
+            }
+        }
+        if (np->rn_type == VDIR)
+            dir->d_type = DT_DIR;
+        else if (np->rn_type == VLNK)
+            dir->d_type = DT_LNK;
+        else
+            dir->d_type = DT_REG;
+        strlcpy((char *) &dir->d_name, np->rn_name,
+                sizeof(dir->d_name));
+    }
+    dir->d_fileno = fp->f_offset;
+//     dir->d_namelen = strlen(dir->d_name);
+
+    fp->f_offset++;
+
+    mutex_unlock(&ramfs_lock);
+    return 0;
+}
+
+int
+ramfs_init(void)
+{
+    return 0;
+}
+
+static int
+ramfs_getattr(struct vnode *vnode, struct vattr *attr)
+{
+    attr->va_nodeid = vnode->v_ino;
+    attr->va_size = vnode->v_size;
+
+    struct ramfs_node *np = (ramfs_node *) vnode->v_data;
+    attr->va_type = (vtype) np->rn_type;
+
+    memcpy(&(attr->va_atime), &(np->rn_atime), sizeof(struct timespec));
+    memcpy(&(attr->va_ctime), &(np->rn_ctime), sizeof(struct timespec));
+    memcpy(&(attr->va_mtime), &(np->rn_mtime), sizeof(struct timespec));
+
+    attr->va_mode = np->rn_mode;
+
+    return 0;
+}
+
+static int
+ramfs_setattr(struct vnode *vnode, struct vattr *attr) {
+    struct ramfs_node *np = (ramfs_node *) vnode->v_data;
+
+    if (attr->va_mask & AT_ATIME) {
+        memcpy(&(np->rn_atime), &(attr->va_atime), sizeof(struct timespec));
+    }
+
+    if (attr->va_mask & AT_CTIME) {
+        memcpy(&(np->rn_ctime), &(attr->va_ctime), sizeof(struct timespec));
+    }
+
+    if (attr->va_mask & AT_MTIME) {
+        memcpy(&(np->rn_mtime), &(attr->va_mtime), sizeof(struct timespec));
+    }
+
+    if (attr->va_mask & AT_MODE) {
+        np->rn_mode = attr->va_mode;
+    }
+
+    return 0;
+}
+
+#define ramfs_open      ((vnop_open_t)vop_nullop)
+#define ramfs_close     ((vnop_close_t)vop_nullop)
+#define ramfs_seek      ((vnop_seek_t)vop_nullop)
+#define ramfs_ioctl     ((vnop_ioctl_t)vop_einval)
+#define ramfs_fsync     ((vnop_fsync_t)vop_nullop)
+#define ramfs_inactive  ((vnop_inactive_t)vop_nullop)
+#define ramfs_link      ((vnop_link_t)vop_eperm)
+#define ramfs_fallocate ((vnop_fallocate_t)vop_nullop)
+
+/*
+ * vnode operations
+ */
+struct vnops ramfs_vnops = {
+        ramfs_open,             /* open */
+        ramfs_close,            /* close */
+        ramfs_read,             /* read */
+        ramfs_write,            /* write */
+        ramfs_seek,             /* seek */
+        ramfs_ioctl,            /* ioctl */
+        ramfs_fsync,            /* fsync */
+        ramfs_readdir,          /* readdir */
+        ramfs_lookup,           /* lookup */
+        ramfs_create,           /* create */
+        ramfs_remove,           /* remove */
+        ramfs_rename,           /* remame */
+        ramfs_mkdir,            /* mkdir */
+        ramfs_rmdir,            /* rmdir */
+        ramfs_getattr,          /* getattr */
+        ramfs_setattr,          /* setattr */
+        ramfs_inactive,         /* inactive */
+        ramfs_truncate,         /* truncate */
+        ramfs_link,             /* link */
+        (vnop_cache_t) nullptr, /* arc */
+        ramfs_fallocate,        /* fallocate */
+        ramfs_readlink,         /* read link */
+        ramfs_symlink,          /* symbolic link */
+};
+
-- 
2.19.2


_______________________________________________
Minios-devel mailing list
Minios-devel@xxxxxxxxxxxxxxxxxxxx
https://lists.xenproject.org/mailman/listinfo/minios-devel

 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.