Compare commits

...

5 Commits

9 changed files with 199 additions and 62 deletions

View File

@ -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, IoctlStat *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 = IOCTLSTAT_FILE;
statbuf->size = info.size;
} else if (info.type == LFS_TYPE_DIR) {
statbuf->type = IOCTLSTAT_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);
@ -148,6 +160,52 @@ struct VfsObj *littlefs_open(struct VfsMountPoint *vmp, const char *path, uint32
return vobj;
}
int32_t littlefs_fetchdirent(struct VfsMountPoint *vmp, const char *path, IoctlDirent *direntbuf, size_t idx) {
size_t i = 0;
struct lfs_info statinfo;
int ok;
spinlock_acquire(&vmp->spinlock);
ok = lfs_stat(&vmp->fs.littlefs.instance, path, &statinfo);
if (ok < 0) {
spinlock_release(&vmp->spinlock);
return E_BADIO;
}
if (statinfo.type != LFS_TYPE_DIR) {
spinlock_release(&vmp->spinlock);
return E_BADIO;
}
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 entinfo;
while (lfs_dir_read(&vmp->fs.littlefs.instance, &dir, &entinfo) > 0) {
if (i == idx) {
if (entinfo.type == LFS_TYPE_REG) {
direntbuf->stat.type = IOCTLSTAT_FILE;
direntbuf->stat.size = entinfo.size;
} else if (entinfo.type == LFS_TYPE_DIR) {
direntbuf->stat.type = IOCTLSTAT_DIR;
}
hal_memcpy(direntbuf->name, entinfo.name, sizeof(direntbuf->name));
break;
}
i++;
}
lfs_dir_close(&vmp->fs.littlefs.instance, &dir);
spinlock_release(&vmp->spinlock);
}
int portlfs_read(const struct lfs_config *c, lfs_block_t block, lfs_off_t off, void *buffer, lfs_size_t size) {
VfsMountPoint *vmp = c->context;
vmp->backingsd->read(vmp->backingsd, buffer, size, block * LITTLEFS_BLOCK_SIZE + off);
@ -170,3 +228,4 @@ int portlfs_sync(const struct lfs_config *c) {
(void)c;
return 0;
}

View File

@ -4,11 +4,11 @@
#include <stdint.h>
#include <stdbool.h>
#include "fs/littlefs/lfs.h"
#include "sysdefs/ioctl.h"
#define LITTLEFS_BLOCK_SIZE 4096
struct VfsMountPoint;
struct VfsStat;
struct VfsObj;
typedef struct {
@ -17,6 +17,8 @@ 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, IoctlStat *statbuf);
int32_t littlefs_fetchdirent(struct VfsMountPoint *vmp, const char *path, IoctlDirent *direntbuf, size_t idx);
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);

View File

@ -14,6 +14,7 @@
#include "bootinfo/bootinfo.h"
#include "ipc/pipe/pipe.h"
#include "sysdefs/processctl.h"
#include "sysdefs/ioctl.h"
#define PROC_REAPER_FREQ 30
@ -74,22 +75,20 @@ ElfAuxval proc_load_elf_segs(Proc *proc, uint8_t *data) {
}
Proc *proc_spawnuser(char *mountpoint, char *path) {
IoctlStat stat;
if (vfs_stat(mountpoint, path, &stat) != E_OK) {
return NULL;
}
if (stat.type != IOCTLSTAT_FILE) {
return NULL;
}
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);
return NULL;
}
if (stat.type != VFS_TYPE_FILE) {
vfs_close(vobj);
return NULL;
}
uint8_t *data = dlmalloc(stat.size);
if (data == NULL) {
vfs_close(vobj);

View File

@ -134,33 +134,48 @@ int32_t SYSCALL5(sys_ioctl, ioh1, cmd1, arg1, arg2, arg3) {
ret = vobj->read(vobj, buffer, len, off);
} break;
case IOCTL_STAT: {
if (ioh >= PROC_VFSHANDLES_MAX) {
const char *opath = (const char *)arg2;
if (opath == NULL) {
ret = E_INVALIDARGUMENT;
goto done;
}
spinlock_acquire(&PROCS.spinlock);
Proc *proc = PROCS.current;
spinlock_release(&PROCS.spinlock);
VfsObj *vobj = proc->vobjs[ioh];
if (vobj == NULL) {
ret = E_INVALIDARGUMENT;
goto done;
}
VfsStat stat1;
ret = vobj->stat(vobj, &stat1);
IoctlStat *iostat = (IoctlStat *)arg1;
if (iostat == NULL) {
ret = E_INVALIDARGUMENT;
goto done;
}
iostat->size = stat1.size;
iostat->type = stat1.type;
char mp[IOCTL_MP_MAX];
char path[IOCTL_PATH_MAX];
path_parse(opath, mp, path);
ret = vfs_stat(mp, path, iostat);
} break;
case IOCTL_FETCHDIRENT: {
const char *opath = (const char *)arg1;
if (opath == NULL) {
ret = E_INVALIDARGUMENT;
goto done;
}
IoctlDirent *direntbuf = (IoctlDirent *)arg2;
if (direntbuf == NULL) {
ret = E_INVALIDARGUMENT;
goto done;
}
size_t idx = (size_t)arg3;
char mp[IOCTL_MP_MAX];
char path[IOCTL_PATH_MAX];
path_parse(opath, mp, path);
ret = vfs_fetchdirent(mp, path, direntbuf, idx);
} break;
default: {
ret = E_INVALIDARGUMENT;

View File

@ -46,6 +46,36 @@ void vfs_init_littlefs(VfsMountPoint *mp, bool format) {
mp->cleanup = &littlefs_cleanup;
mp->open = &littlefs_open;
mp->stat = &littlefs_stat;
mp->fetchdirent = &littlefs_fetchdirent;
}
int32_t vfs_stat(char *mountpoint, const char *path, IoctlStat *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_fetchdirent(char *mountpoint, const char *path, IoctlDirent *direntbuf, size_t idx) {
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->fetchdirent(mp, path, direntbuf, idx);
}
int32_t vfs_mount(char *mountpoint, int32_t fstype, StoreDev *backingsd, bool format) {

View File

@ -7,6 +7,7 @@
#include "spinlock/spinlock.h"
#include "fs/portlfs/portlfs.h"
#include "storedev/storedev.h"
#include "sysdefs/ioctl.h"
#define VFS_MOUNTPOINT_LABEL_MAX 128
#define VFS_MOUNTPOINTS_MAX 30
@ -19,11 +20,6 @@ static const char *vfs_strings[] = {
"Little FS",
};
enum {
VFS_TYPE_DIR = 0,
VFS_TYPE_FILE = 1,
};
enum {
VFS_FLAG_READ = 1<<0,
VFS_FLAG_WRITE = 1<<1,
@ -32,11 +28,6 @@ enum {
#define VFS_PATH_MAX 1024
typedef struct VfsStat {
size_t size;
int32_t type;
} VfsStat;
typedef struct VfsObj {
SpinLock spinlock;
void *extra;
@ -45,7 +36,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 +48,8 @@ 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, IoctlStat *statbuf);
int32_t (*fetchdirent)(struct VfsMountPoint *vmp, const char *path, IoctlDirent *direntbuf, size_t idx);
union {
LittleFs littlefs;
@ -77,5 +69,7 @@ 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, IoctlStat *stat);
int32_t vfs_fetchdirent(char *mountpoint, const char *path, IoctlDirent *direntbuf, size_t idx);
#endif // VFS_VFS_H_

View File

@ -12,6 +12,7 @@ enum {
IOCTL_READ = 2,
IOCTL_STAT = 3,
IOCTL_WRITE = 4,
IOCTL_FETCHDIRENT = 5,
};
enum {
@ -30,6 +31,11 @@ typedef struct IoctlStat {
int32_t type;
} IoctlStat;
typedef struct IoctlDirent {
IoctlStat stat;
char name[0x100];
} IoctlDirent;
typedef int32_t IOH;
#endif // SHARE_SYSDEFS_IOCTL_H_

View File

@ -10,26 +10,58 @@ 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, 0, 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) {
IoctlDirent *dirents = (IoctlDirent *)umalloc(statbuf.size * sizeof(*dirents));
for (size_t i = 0; i < statbuf.size; i++) {
ioctl(IOCTL_NOHANDLE, IOCTL_FETCHDIRENT, (uint64_t)path, (uint64_t)&dirents[i], i);
IoctlDirent *dirent = &dirents[i];
if (dirent->stat.type == IOCTLSTAT_FILE) {
char *membuf = umalloc(20);
uprintf("%-30s %-15s %-1s\n",
dirent->name,
human_size(dirent->stat.size, membuf, 20),
"F"
);
ufree(membuf);
} else if (dirent->stat.type == IOCTLSTAT_DIR) {
uprintf("%-30s %-15s %-1s\n",
dirent->name,
"-",
"D"
);
}
}
ufree(dirents);
}
}

View File

@ -68,7 +68,7 @@ void do_file(char *filepath) {
IoctlStat statbuf; ZERO(&statbuf);
ioctl(ioh, IOCTL_STAT, (uint64_t)&statbuf, 0, 0);
ioctl(ioh, IOCTL_STAT, (uint64_t)&statbuf, (uint64_t)filepath, 0);
if (statbuf.type != IOCTLSTAT_FILE) {
LOG(LOG_ERR, "%s is not a file (%d)\n", filepath, statbuf.type);
return;