diff --git a/kernel/fs/portlfs/portlfs.c b/kernel/fs/portlfs/portlfs.c index f6f660b..d4d0da3 100644 --- a/kernel/fs/portlfs/portlfs.c +++ b/kernel/fs/portlfs/portlfs.c @@ -72,25 +72,38 @@ int32_t littlefs_vobj_write(struct VfsObj *vobj, const uint8_t *const buffer, si return E_OK; } -int32_t littlefs_vobj_stat(struct VfsObj *vobj, struct VfsStat *stat) { - struct lfs_info statbuf; +int32_t littlefs_stat(struct VfsMountPoint *vmp, const char *path, struct VfsStat *statbuf) { + struct lfs_info info; - spinlock_acquire(&vobj->spinlock); + spinlock_acquire(&vmp->spinlock); - int ok = lfs_stat(&vobj->vmp->fs.littlefs.instance, vobj->path, &statbuf); + int ok = lfs_stat(&vmp->fs.littlefs.instance, path, &info); if (ok < 0) { - spinlock_release(&vobj->spinlock); + spinlock_release(&vmp->spinlock); return E_BADIO; } - if (statbuf.type == LFS_TYPE_REG) { - stat->type = VFS_TYPE_FILE; - } else if (statbuf.type == LFS_TYPE_DIR) { - stat->type = VFS_TYPE_DIR; + if (info.type == LFS_TYPE_REG) { + statbuf->type = VFS_TYPE_FILE; + statbuf->size = info.size; + } else if (info.type == LFS_TYPE_DIR) { + statbuf->type = VFS_TYPE_DIR; + statbuf->size = 0; + // TODO: find a better way than this... !!! + lfs_dir_t dir; + ok = lfs_dir_open(&vmp->fs.littlefs.instance, &dir, path); + if (ok < 0) { + spinlock_release(&vmp->spinlock); + return E_BADIO; + } + struct lfs_info info2; + while (lfs_dir_read(&vmp->fs.littlefs.instance, &dir, &info2) > 0) { + statbuf->size++; + } + lfs_dir_close(&vmp->fs.littlefs.instance, &dir); } - stat->size = statbuf.size; - spinlock_release(&vobj->spinlock); + spinlock_release(&vmp->spinlock); return E_OK; } @@ -140,7 +153,6 @@ struct VfsObj *littlefs_open(struct VfsMountPoint *vmp, const char *path, uint32 vobj->vmp = vmp; vobj->cleanup = &littlefs_vobj_cleanup; vobj->read = &littlefs_vobj_read; - vobj->stat = &littlefs_vobj_stat; vobj->write = &littlefs_vobj_write; hal_strcpy(vobj->path, path); @@ -170,3 +182,4 @@ int portlfs_sync(const struct lfs_config *c) { (void)c; return 0; } + diff --git a/kernel/fs/portlfs/portlfs.h b/kernel/fs/portlfs/portlfs.h index 4a62360..bab3560 100644 --- a/kernel/fs/portlfs/portlfs.h +++ b/kernel/fs/portlfs/portlfs.h @@ -17,6 +17,7 @@ typedef struct { int32_t littlefs_cleanup(struct VfsMountPoint *vmp); struct VfsObj *littlefs_open(struct VfsMountPoint *vmp, const char *path, uint32_t flags); +int32_t littlefs_stat(struct VfsMountPoint *vmp, const char *path, struct VfsStat *statbuf); int portlfs_read(const struct lfs_config *c, lfs_block_t block, lfs_off_t off, void *buffer, lfs_size_t size); int portlfs_prog(const struct lfs_config *c, lfs_block_t block, lfs_off_t off, const void *buffer, lfs_size_t size); diff --git a/kernel/proc/proc.c b/kernel/proc/proc.c index c3a553d..8622820 100644 --- a/kernel/proc/proc.c +++ b/kernel/proc/proc.c @@ -74,19 +74,17 @@ ElfAuxval proc_load_elf_segs(Proc *proc, uint8_t *data) { } Proc *proc_spawnuser(char *mountpoint, char *path) { - VfsObj *vobj = vfs_open(mountpoint, path, VFS_FLAG_READ); - if (vobj == NULL) { - return NULL; - } - VfsStat stat; - if (vobj->stat(vobj, &stat) != E_OK) { - vfs_close(vobj); + if (vfs_stat(mountpoint, path, &stat) != E_OK) { return NULL; } if (stat.type != VFS_TYPE_FILE) { - vfs_close(vobj); + return NULL; + } + + VfsObj *vobj = vfs_open(mountpoint, path, VFS_FLAG_READ); + if (vobj == NULL) { return NULL; } diff --git a/kernel/syscall/ioctl.c b/kernel/syscall/ioctl.c index a7a68da..b47d6e1 100644 --- a/kernel/syscall/ioctl.c +++ b/kernel/syscall/ioctl.c @@ -140,26 +140,21 @@ int32_t SYSCALL5(sys_ioctl, ioh1, cmd1, arg1, arg2, arg3) { ret = E_INVALIDARGUMENT; goto done; } + + IoctlStat *iostat = (IoctlStat *)arg1; + if (iostat == NULL) { + ret = E_INVALIDARGUMENT; + goto done; + } char mp[IOCTL_MP_MAX]; char path[IOCTL_PATH_MAX]; path_parse(opath, mp, path); - VfsObj *vobj = vfs_open(mp, path, IOCTL_F_READ); - if (vobj == NULL) { - ret = E_NOENTRY; - goto done; - } - VfsStat stat1; - ret = vobj->stat(vobj, &stat1); - - vfs_close(vobj); - - IoctlStat *iostat = (IoctlStat *)arg1; - if (iostat == NULL) { - ret = E_INVALIDARGUMENT; + ret = vfs_stat(mp, path, &stat1); + if (ret != E_OK) { goto done; } diff --git a/kernel/vfs/vfs.c b/kernel/vfs/vfs.c index 8b4dc49..81aae66 100644 --- a/kernel/vfs/vfs.c +++ b/kernel/vfs/vfs.c @@ -46,6 +46,21 @@ void vfs_init_littlefs(VfsMountPoint *mp, bool format) { mp->cleanup = &littlefs_cleanup; mp->open = &littlefs_open; + mp->stat = &littlefs_stat; +} + +int32_t vfs_stat(char *mountpoint, const char *path, VfsStat *stat) { + VfsMountPoint *mp = NULL; + + spinlock_acquire(&VFS_TABLE.spinlock); + HSHTB_GET(&VFS_TABLE, mountpoints, mountpoint, label, mp); + spinlock_release(&VFS_TABLE.spinlock); + + if (mp == NULL) { + return E_NOENTRY; + } + + return mp->stat(mp, path, stat); } int32_t vfs_mount(char *mountpoint, int32_t fstype, StoreDev *backingsd, bool format) { diff --git a/kernel/vfs/vfs.h b/kernel/vfs/vfs.h index e43d1e4..55ab16a 100644 --- a/kernel/vfs/vfs.h +++ b/kernel/vfs/vfs.h @@ -45,7 +45,6 @@ typedef struct VfsObj { char path[VFS_PATH_MAX]; int32_t flags; int32_t (*read)(struct VfsObj *vobj, uint8_t *const buffer, size_t n, size_t off); - int32_t (*stat)(struct VfsObj *vobj, struct VfsStat *stat); int32_t (*write)(struct VfsObj *vobj, const uint8_t *const buffer, size_t n, size_t off); void (*cleanup)(struct VfsObj *vobj); } VfsObj; @@ -58,6 +57,7 @@ typedef struct VfsMountPoint { VfsObj *(*open)(struct VfsMountPoint *vmp, const char *path, uint32_t flags); int32_t (*cleanup)(struct VfsMountPoint *vmp); + int32_t (*stat)(struct VfsMountPoint *vmp, const char *path, struct VfsStat *statbuf); union { LittleFs littlefs; @@ -77,5 +77,6 @@ int32_t vfs_unmount(char *mountpoint); int32_t vfs_mount(char *mountpoint, int32_t fstype, StoreDev *backingsd, bool format); void vfs_close(VfsObj *vobj); VfsObj *vfs_open(char *mountpoint, const char *path, uint32_t flags); +int32_t vfs_stat(char *mountpoint, const char *path, VfsStat *stat); #endif // VFS_VFS_H_ diff --git a/user/fs/fetch.c b/user/fs/fetch.c index ea4c166..a7ab388 100644 --- a/user/fs/fetch.c +++ b/user/fs/fetch.c @@ -10,29 +10,33 @@ void fs_fetch(void) { char *path = *(args()+1); - IOH ioh = ioctl(IOCTL_NOHANDLE, IOCTL_OPENF, (uint64_t)path, IOCTL_F_READ, 0); - if (ioh < 0) { - uprintf("fs: could not open %s\n", path); + IoctlStat statbuf; ZERO(&statbuf); + if (ioctl(IOCTL_NOHANDLE, IOCTL_STAT, (uint64_t)&statbuf, (uint64_t)path, 0) != E_OK) { + uprintf("fs: could not stat %s\n", path); return; } - IoctlStat statbuf; ZERO(&statbuf); - - ioctl(ioh, IOCTL_STAT, (uint64_t)&statbuf, (uint64_t)path, 0); if (statbuf.type == IOCTLSTAT_FILE) { + IOH ioh = ioctl(IOCTL_NOHANDLE, IOCTL_OPENF, (uint64_t)path, IOCTL_F_READ, 0); + if (ioh < 0) { + uprintf("fs: could not open %s\n", path); + return; + } + uint8_t *buf = umalloc(statbuf.size+1); string_memset(buf, 0, statbuf.size+1); if (ioctl(ioh, IOCTL_READ, (uint64_t)buf, statbuf.size, 0) < 0) { uprintf("fs: coult not read %s\n", path); - ufree(buf); - ioctl(ioh, IOCTL_CLOSEF, 0, 0, 0); + goto donefile; return; } uprintf("%s", buf); + donefile: ufree(buf); + ioctl(ioh, IOCTL_CLOSEF, 0, 0, 0); + } else if (statbuf.type == IOCTLSTAT_DIR) { + uprintf("entries = %zu\n", statbuf.size); } - - ioctl(ioh, IOCTL_CLOSEF, 0, 0, 0); }