Skip to content

Commit

Permalink
Custom devoptab wrappers (part 4).
Browse files Browse the repository at this point in the history
Improve dirnext() calls in both PFS and HFS devoptab wrappers to make them also return bogus "." and ".." directory entries.

The "st_ino" field is now also being filled for all file entries.

Other changes include:

* libs: update libusbhsfs.
  • Loading branch information
DarkMatterCore committed Dec 21, 2023
1 parent e6caff3 commit 091747d
Show file tree
Hide file tree
Showing 3 changed files with 71 additions and 25 deletions.
47 changes: 35 additions & 12 deletions source/devoptab/hfs_dev.c
Original file line number Diff line number Diff line change
Expand Up @@ -35,12 +35,14 @@
/* Type definitions. */

typedef struct {
u32 index; ///< Hash FS entry index.
HashFileSystemEntry *hfs_entry; ///< Hash FS entry metadata.
const char *name; ///< Entry name.
u64 offset; ///< Current offset within Hash FS entry data.
} HashFileSystemFileState;

typedef struct {
u8 state; ///< 0: "." entry; 1: ".." entry; 2: actual Hash FS entry.
u32 index; ///< Current Hash FS entry index.
} HashFileSystemDirectoryState;

Expand All @@ -60,7 +62,7 @@ static int hfsdev_statvfs(struct _reent *r, const char *path, struct statv

static const char *hfsdev_get_truncated_path(struct _reent *r, const char *path);

static void hfsdev_fill_stat(struct stat *st, const HashFileSystemEntry *hfs_entry, time_t mount_time);
static void hfsdev_fill_stat(struct stat *st, u32 index, const HashFileSystemEntry *hfs_entry, time_t mount_time);

/* Global variables. */

Expand Down Expand Up @@ -122,8 +124,9 @@ static int hfsdev_open(struct _reent *r, void *fd, const char *path, int flags,
/* Reset file descriptor. */
memset(file, 0, sizeof(HashFileSystemFileState));

/* Get Hash FS entry. */
if (!(file->hfs_entry = hfsGetEntryByName(fs_ctx, path)) || !(file->name = hfsGetEntryName(fs_ctx, file->hfs_entry))) DEVOPTAB_SET_ERROR(ENOENT);
/* Get information about the requested Partition FS entry. */
if (!hfsGetEntryIndexByName(fs_ctx, path, &(file->index)) || !(file->hfs_entry = hfsGetEntryByIndex(fs_ctx, file->index)) || \
!(file->name = hfsGetEntryNameByIndex(fs_ctx, file->index))) DEVOPTAB_SET_ERROR(ENOENT);

end:
DEVOPTAB_DEINIT_VARS;
Expand Down Expand Up @@ -221,7 +224,7 @@ static int hfsdev_fstat(struct _reent *r, void *fd, struct stat *st)
LOG_MSG_DEBUG("Getting file stats for \"%s:/%s\".", dev_ctx->name, file->name);

/* Fill stat info. */
hfsdev_fill_stat(st, file->hfs_entry, dev_ctx->mount_time);
hfsdev_fill_stat(st, file->index, file->hfs_entry, dev_ctx->mount_time);

end:
DEVOPTAB_DEINIT_VARS;
Expand All @@ -230,6 +233,7 @@ static int hfsdev_fstat(struct _reent *r, void *fd, struct stat *st)

static int hfsdev_stat(struct _reent *r, const char *file, struct stat *st)
{
u32 index = 0;
HashFileSystemEntry *hfs_entry = NULL;

HFS_DEV_INIT_VARS;
Expand All @@ -243,11 +247,11 @@ static int hfsdev_stat(struct _reent *r, const char *file, struct stat *st)

LOG_MSG_DEBUG("Getting file stats for \"%s:/%s\".", dev_ctx->name, file);

/* Get Hash FS entry. */
if (!(hfs_entry = hfsGetEntryByName(fs_ctx, file))) DEVOPTAB_SET_ERROR_AND_EXIT(EINVAL);
/* Get information about the requested Partition FS entry. */
if (!hfsGetEntryIndexByName(fs_ctx, file, &index) || !(hfs_entry = hfsGetEntryByIndex(fs_ctx, index))) DEVOPTAB_SET_ERROR(ENOENT);

/* Fill stat info. */
hfsdev_fill_stat(st, hfs_entry, dev_ctx->mount_time);
hfsdev_fill_stat(st, index, hfs_entry, dev_ctx->mount_time);

end:
DEVOPTAB_DEINIT_VARS;
Expand All @@ -263,7 +267,7 @@ static DIR_ITER *hfsdev_diropen(struct _reent *r, DIR_ITER *dirState, const char
/* Get truncated path. */
/* We can only work with the FS root here, so we won't accept anything else. */
if (!(path = hfsdev_get_truncated_path(r, path))) DEVOPTAB_EXIT;
if (*path) DEVOPTAB_SET_ERROR_AND_EXIT(EINVAL);
if (*path) DEVOPTAB_SET_ERROR_AND_EXIT(ENOENT);

LOG_MSG_DEBUG("Opening directory \"%s:/\".", dev_ctx->name);

Expand All @@ -285,6 +289,7 @@ static int hfsdev_dirreset(struct _reent *r, DIR_ITER *dirState)
LOG_MSG_DEBUG("Resetting directory state for \"%s:/\".", dev_ctx->name);

/* Reset directory state. */
dir->state = 0;
dir->index = 0;

end:
Expand All @@ -303,7 +308,24 @@ static int hfsdev_dirnext(struct _reent *r, DIR_ITER *dirState, char *filename,
/* Sanity check. */
if (!filename || !filestat) DEVOPTAB_SET_ERROR_AND_EXIT(EINVAL);

LOG_MSG_DEBUG("Getting info for next directory entry in \"%s:/\" (index %u).", dev_ctx->name, dir->index);
LOG_MSG_DEBUG("Getting info for next directory entry in \"%s:/\" (state %u, index %u).", dev_ctx->name, dir->state, dir->index);

if (dir->state < 2)
{
/* Fill bogus directory entry. */
memset(filestat, 0, sizeof(struct stat));

filestat->st_nlink = 1;
filestat->st_mode = (S_IFDIR | S_IRUSR | S_IRGRP | S_IROTH);
filestat->st_atime = filestat->st_mtime = filestat->st_ctime = dev_ctx->mount_time;

strcpy(filename, dir->state == 0 ? "." : "..");

/* Update state. */
dir->state++;

DEVOPTAB_EXIT;
}

/* Check if we haven't reached EOD. */
if (dir->index >= hfsGetEntryCount(fs_ctx)) DEVOPTAB_SET_ERROR_AND_EXIT(ENOENT);
Expand All @@ -315,7 +337,7 @@ static int hfsdev_dirnext(struct _reent *r, DIR_ITER *dirState, char *filename,
strcpy(filename, fname);

/* Fill stat info. */
hfsdev_fill_stat(filestat, hfs_entry, dev_ctx->mount_time);
hfsdev_fill_stat(filestat, dir->index, hfs_entry, dev_ctx->mount_time);

/* Adjust index. */
dir->index++;
Expand Down Expand Up @@ -428,15 +450,16 @@ static const char *hfsdev_get_truncated_path(struct _reent *r, const char *path)
DEVOPTAB_RETURN_PTR(path);
}

static void hfsdev_fill_stat(struct stat *st, const HashFileSystemEntry *hfs_entry, time_t mount_time)
static void hfsdev_fill_stat(struct stat *st, u32 index, const HashFileSystemEntry *hfs_entry, time_t mount_time)
{
/* Clear stat struct. */
memset(st, 0, sizeof(struct stat));

/* Fill stat struct. */
/* We're always dealing with a file entry. */
st->st_ino = index;
st->st_mode = (S_IFREG | S_IRUSR | S_IRGRP | S_IROTH);
st->st_nlink = 1;
st->st_size = (off_t)hfs_entry->size;
st->st_mode = (S_IFREG | S_IRUSR | S_IRGRP | S_IROTH);
st->st_atime = st->st_mtime = st->st_ctime = mount_time;
}
47 changes: 35 additions & 12 deletions source/devoptab/pfs_dev.c
Original file line number Diff line number Diff line change
Expand Up @@ -35,12 +35,14 @@
/* Type definitions. */

typedef struct {
u32 index; ///< Partition FS entry index.
PartitionFileSystemEntry *pfs_entry; ///< Partition FS entry metadata.
const char *name; ///< Entry name.
u64 offset; ///< Current offset within Partition FS entry data.
} PartitionFileSystemFileState;

typedef struct {
u8 state; ///< 0: "." entry; 1: ".." entry; 2: actual Partition FS entry.
u32 index; ///< Current Partition FS entry index.
} PartitionFileSystemDirectoryState;

Expand All @@ -60,7 +62,7 @@ static int pfsdev_statvfs(struct _reent *r, const char *path, struct statv

static const char *pfsdev_get_truncated_path(struct _reent *r, const char *path);

static void pfsdev_fill_stat(struct stat *st, const PartitionFileSystemEntry *pfs_entry, time_t mount_time);
static void pfsdev_fill_stat(struct stat *st, u32 index, const PartitionFileSystemEntry *pfs_entry, time_t mount_time);

/* Global variables. */

Expand Down Expand Up @@ -122,8 +124,9 @@ static int pfsdev_open(struct _reent *r, void *fd, const char *path, int flags,
/* Reset file descriptor. */
memset(file, 0, sizeof(PartitionFileSystemFileState));

/* Get Partition FS entry. */
if (!(file->pfs_entry = pfsGetEntryByName(fs_ctx, path)) || !(file->name = pfsGetEntryName(fs_ctx, file->pfs_entry))) DEVOPTAB_SET_ERROR(ENOENT);
/* Get information about the requested Partition FS entry. */
if (!pfsGetEntryIndexByName(fs_ctx, path, &(file->index)) || !(file->pfs_entry = pfsGetEntryByIndex(fs_ctx, file->index)) || \
!(file->name = pfsGetEntryNameByIndex(fs_ctx, file->index))) DEVOPTAB_SET_ERROR(ENOENT);

end:
DEVOPTAB_DEINIT_VARS;
Expand Down Expand Up @@ -221,7 +224,7 @@ static int pfsdev_fstat(struct _reent *r, void *fd, struct stat *st)
LOG_MSG_DEBUG("Getting file stats for \"%s:/%s\".", dev_ctx->name, file->name);

/* Fill stat info. */
pfsdev_fill_stat(st, file->pfs_entry, dev_ctx->mount_time);
pfsdev_fill_stat(st, file->index, file->pfs_entry, dev_ctx->mount_time);

end:
DEVOPTAB_DEINIT_VARS;
Expand All @@ -230,6 +233,7 @@ static int pfsdev_fstat(struct _reent *r, void *fd, struct stat *st)

static int pfsdev_stat(struct _reent *r, const char *file, struct stat *st)
{
u32 index = 0;
PartitionFileSystemEntry *pfs_entry = NULL;

PFS_DEV_INIT_VARS;
Expand All @@ -243,11 +247,11 @@ static int pfsdev_stat(struct _reent *r, const char *file, struct stat *st)

LOG_MSG_DEBUG("Getting file stats for \"%s:/%s\".", dev_ctx->name, file);

/* Get Partition FS entry. */
if (!(pfs_entry = pfsGetEntryByName(fs_ctx, file))) DEVOPTAB_SET_ERROR_AND_EXIT(EINVAL);
/* Get information about the requested Partition FS entry. */
if (!pfsGetEntryIndexByName(fs_ctx, file, &index) || !(pfs_entry = pfsGetEntryByIndex(fs_ctx, index))) DEVOPTAB_SET_ERROR(ENOENT);

/* Fill stat info. */
pfsdev_fill_stat(st, pfs_entry, dev_ctx->mount_time);
pfsdev_fill_stat(st, index, pfs_entry, dev_ctx->mount_time);

end:
DEVOPTAB_DEINIT_VARS;
Expand All @@ -263,7 +267,7 @@ static DIR_ITER *pfsdev_diropen(struct _reent *r, DIR_ITER *dirState, const char
/* Get truncated path. */
/* We can only work with the FS root here, so we won't accept anything else. */
if (!(path = pfsdev_get_truncated_path(r, path))) DEVOPTAB_EXIT;
if (*path) DEVOPTAB_SET_ERROR_AND_EXIT(EINVAL);
if (*path) DEVOPTAB_SET_ERROR_AND_EXIT(ENOENT);

LOG_MSG_DEBUG("Opening directory \"%s:/\".", dev_ctx->name);

Expand All @@ -285,6 +289,7 @@ static int pfsdev_dirreset(struct _reent *r, DIR_ITER *dirState)
LOG_MSG_DEBUG("Resetting directory state for \"%s:/\".", dev_ctx->name);

/* Reset directory state. */
dir->state = 0;
dir->index = 0;

end:
Expand All @@ -303,7 +308,24 @@ static int pfsdev_dirnext(struct _reent *r, DIR_ITER *dirState, char *filename,
/* Sanity check. */
if (!filename || !filestat) DEVOPTAB_SET_ERROR_AND_EXIT(EINVAL);

LOG_MSG_DEBUG("Getting info for next directory entry in \"%s:/\" (index %u).", dev_ctx->name, dir->index);
LOG_MSG_DEBUG("Getting info for next directory entry in \"%s:/\" (state %u, index %u).", dev_ctx->name, dir->state, dir->index);

if (dir->state < 2)
{
/* Fill bogus directory entry. */
memset(filestat, 0, sizeof(struct stat));

filestat->st_nlink = 1;
filestat->st_mode = (S_IFDIR | S_IRUSR | S_IRGRP | S_IROTH);
filestat->st_atime = filestat->st_mtime = filestat->st_ctime = dev_ctx->mount_time;

strcpy(filename, dir->state == 0 ? "." : "..");

/* Update state. */
dir->state++;

DEVOPTAB_EXIT;
}

/* Check if we haven't reached EOD. */
if (dir->index >= pfsGetEntryCount(fs_ctx)) DEVOPTAB_SET_ERROR_AND_EXIT(ENOENT);
Expand All @@ -315,7 +337,7 @@ static int pfsdev_dirnext(struct _reent *r, DIR_ITER *dirState, char *filename,
strcpy(filename, fname);

/* Fill stat info. */
pfsdev_fill_stat(filestat, pfs_entry, dev_ctx->mount_time);
pfsdev_fill_stat(filestat, dir->index, pfs_entry, dev_ctx->mount_time);

/* Adjust index. */
dir->index++;
Expand Down Expand Up @@ -428,15 +450,16 @@ static const char *pfsdev_get_truncated_path(struct _reent *r, const char *path)
DEVOPTAB_RETURN_PTR(path);
}

static void pfsdev_fill_stat(struct stat *st, const PartitionFileSystemEntry *pfs_entry, time_t mount_time)
static void pfsdev_fill_stat(struct stat *st, u32 index, const PartitionFileSystemEntry *pfs_entry, time_t mount_time)
{
/* Clear stat struct. */
memset(st, 0, sizeof(struct stat));

/* Fill stat struct. */
/* We're always dealing with a file entry. */
st->st_ino = index;
st->st_mode = (S_IFREG | S_IRUSR | S_IRGRP | S_IROTH);
st->st_nlink = 1;
st->st_size = (off_t)pfs_entry->size;
st->st_mode = (S_IFREG | S_IRUSR | S_IRGRP | S_IROTH);
st->st_atime = st->st_mtime = st->st_ctime = mount_time;
}

0 comments on commit 091747d

Please sign in to comment.