This patch enhances ramfs implementation to handle time and 
mode node attributes. Additionally it adds extra checks
in relevant places to enforce maximum name length.

Signed-off-by: Waldemar Kozaczuk <jwkozac...@gmail.com>
---
 fs/ramfs/ramfs.h        |   4 ++
 fs/ramfs/ramfs_vnops.cc | 101 +++++++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 104 insertions(+), 1 deletion(-)

diff --git a/fs/ramfs/ramfs.h b/fs/ramfs/ramfs.h
index 94553ba..f21ff4b 100644
--- a/fs/ramfs/ramfs.h
+++ b/fs/ramfs/ramfs.h
@@ -54,6 +54,10 @@ struct ramfs_node {
     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;
 };
 
 struct ramfs_node *ramfs_allocate_node(const char *name, int type);
diff --git a/fs/ramfs/ramfs_vnops.cc b/fs/ramfs/ramfs_vnops.cc
index f3f3441..6dd1a24 100644
--- a/fs/ramfs/ramfs_vnops.cc
+++ b/fs/ramfs/ramfs_vnops.cc
@@ -44,12 +44,29 @@
 #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)
 {
@@ -68,6 +85,16 @@ ramfs_allocate_node(const char *name, int type)
     }
     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));
+
     return np;
 }
 
@@ -101,6 +128,9 @@ ramfs_add_node(struct ramfs_node *dnp, char *name, int type)
             prev = prev->rn_next;
         prev->rn_next = np;
     }
+
+    set_times_to_now(&(dnp->rn_mtime));
+
     mutex_unlock(&ramfs_lock);
     return np;
 }
@@ -130,6 +160,8 @@ ramfs_remove_node(struct ramfs_node *dnp, struct ramfs_node 
*np)
     }
     ramfs_free_node(np);
 
+    set_times_to_now(&(dnp->rn_mtime));
+
     mutex_unlock(&ramfs_lock);
     return 0;
 }
@@ -141,6 +173,9 @@ ramfs_rename_node(struct ramfs_node *np, char *name)
     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);
@@ -154,6 +189,7 @@ ramfs_rename_node(struct ramfs_node *np, char *name)
         np->rn_name = tmp;
     }
     np->rn_namelen = len;
+    set_times_to_now(&(np->rn_ctime));
     return 0;
 }
 
@@ -214,6 +250,10 @@ 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;
 
@@ -221,12 +261,19 @@ ramfs_mkdir(struct vnode *dvp, char *name, mode_t mode)
     if (np == NULL)
         return ENOMEM;
     np->rn_size = 0;
+
+    set_times_to_now(&(((ramfs_node *) dvp->v_data)->rn_ctime),
+                     &(((ramfs_node *) dvp->v_data)->rn_mtime));
+
     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;
@@ -234,6 +281,9 @@ ramfs_symlink(struct vnode *dvp, char *name, char *link)
     size_t len = strlen(link);
     np->rn_buf = strndup(link, len);
     np->rn_bufsize = np->rn_size = len;
+
+    set_times_to_now(&(((ramfs_node *) dvp->v_data)->rn_ctime),
+                     &(((ramfs_node *) dvp->v_data)->rn_mtime));
     return 0;
 }
 
@@ -258,6 +308,8 @@ ramfs_readlink(struct vnode *vp, struct uio *uio)
         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);
 }
 
@@ -308,6 +360,7 @@ ramfs_truncate(struct vnode *vp, off_t length)
     }
     np->rn_size = length;
     vp->v_size = length;
+    set_times_to_now(&(np->rn_mtime));
     return 0;
 }
 
@@ -319,6 +372,10 @@ 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;
@@ -356,6 +413,8 @@ ramfs_read(struct vnode *vp, struct file *fp, struct uio 
*uio, int ioflag)
     else
         len = uio->uio_resid;
 
+    set_times_to_now(&(np->rn_atime));
+
     return uiomove(np->rn_buf + uio->uio_offset, len, uio);
 }
 
@@ -373,6 +432,9 @@ ramfs_write(struct vnode *vp, struct uio *uio, int ioflag)
     if (uio->uio_offset < 0) {
         return EINVAL;
     }
+    if (uio->uio_offset >= LONG_MAX) {
+        return EFBIG;
+    }
     if (uio->uio_resid == 0) {
         return 0;
     }
@@ -399,6 +461,8 @@ ramfs_write(struct vnode *vp, struct uio *uio, int ioflag)
         np->rn_size = end_pos;
         vp->v_size = end_pos;
     }
+
+    set_times_to_now(&(np->rn_mtime));
     return uiomove(np->rn_buf + uio->uio_offset, uio->uio_resid, uio);
 }
 
@@ -450,8 +514,11 @@ ramfs_readdir(struct vnode *vp, struct file *fp, struct 
dirent *dir)
     struct ramfs_node *np, *dnp;
     int i;
 
+    DPRINTF(("readdir %s \n", ((ramfs_node *) vp->v_data)->rn_name));
     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));
@@ -502,6 +569,39 @@ 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;
 }
 
@@ -510,7 +610,6 @@ ramfs_getattr(struct vnode *vnode, struct vattr *attr)
 #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_setattr   ((vnop_setattr_t)vop_eperm)
 #define ramfs_inactive  ((vnop_inactive_t)vop_nullop)
 #define ramfs_link      ((vnop_link_t)vop_eperm)
 #define ramfs_fallocate ((vnop_fallocate_t)vop_nullop)
-- 
2.7.4

-- 
You received this message because you are subscribed to the Google Groups "OSv 
Development" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to osv-dev+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to