Add readdir batching to sdmc
This commit is contained in:
parent
41ea040420
commit
4393593e48
@ -4,14 +4,21 @@
|
|||||||
*/
|
*/
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
|
||||||
#include <3ds/types.h>
|
#include <3ds/types.h>
|
||||||
#include <3ds/services/fs.h>
|
#include <3ds/services/fs.h>
|
||||||
|
|
||||||
|
#define SDMC_DIRITER_MAGIC 0x73646D63 /* "sdmc" */
|
||||||
|
|
||||||
/*! Open directory struct */
|
/*! Open directory struct */
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
Handle fd; /*! CTRU handle */
|
u32 magic; /*! "sdmc" */
|
||||||
FS_DirectoryEntry entry_data; /*! Temporary storage for reading entries */
|
Handle fd; /*! CTRU handle */
|
||||||
|
ssize_t index; /*! Current entry index */
|
||||||
|
size_t size; /*! Current batch size */
|
||||||
|
FS_DirectoryEntry entry_data[32]; /*! Temporary storage for reading entries */
|
||||||
} sdmc_dir_t;
|
} sdmc_dir_t;
|
||||||
|
|
||||||
/// Initializes the SDMC driver.
|
/// Initializes the SDMC driver.
|
||||||
|
@ -939,8 +939,10 @@ sdmc_diropen(struct _reent *r,
|
|||||||
rc = FSUSER_OpenDirectory(&fd, sdmcArchive, fs_path);
|
rc = FSUSER_OpenDirectory(&fd, sdmcArchive, fs_path);
|
||||||
if(R_SUCCEEDED(rc))
|
if(R_SUCCEEDED(rc))
|
||||||
{
|
{
|
||||||
|
dir->magic = SDMC_DIRITER_MAGIC;
|
||||||
dir->fd = fd;
|
dir->fd = fd;
|
||||||
memset(&dir->entry_data, 0, sizeof(dir->entry_data));
|
memset(&dir->entry_data, 0, sizeof(dir->entry_data));
|
||||||
|
dir->index = -1;
|
||||||
return dirState;
|
return dirState;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -980,35 +982,58 @@ sdmc_dirnext(struct _reent *r,
|
|||||||
char *filename,
|
char *filename,
|
||||||
struct stat *filestat)
|
struct stat *filestat)
|
||||||
{
|
{
|
||||||
Result rc;
|
Result rc;
|
||||||
u32 entries;
|
u32 entries;
|
||||||
ssize_t units;
|
ssize_t units;
|
||||||
|
FS_DirectoryEntry *entry;
|
||||||
|
|
||||||
/* get pointer to our data */
|
/* get pointer to our data */
|
||||||
sdmc_dir_t *dir = (sdmc_dir_t*)(dirState->dirStruct);
|
sdmc_dir_t *dir = (sdmc_dir_t*)(dirState->dirStruct);
|
||||||
|
|
||||||
/* fetch the next entry */
|
static const size_t max_entries = sizeof(dir->entry_data) / sizeof(dir->entry_data[0]);
|
||||||
memset(&dir->entry_data, 0, sizeof(dir->entry_data));
|
|
||||||
rc = FSDIR_Read(dir->fd, &entries, 1, &dir->entry_data);
|
/* check if it's in the batch already */
|
||||||
|
if(++dir->index < dir->size)
|
||||||
|
{
|
||||||
|
rc = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* reset batch info */
|
||||||
|
dir->index = -1;
|
||||||
|
dir->size = 0;
|
||||||
|
|
||||||
|
/* fetch the next batch */
|
||||||
|
memset(dir->entry_data, 0, sizeof(dir->entry_data));
|
||||||
|
rc = FSDIR_Read(dir->fd, &entries, max_entries, dir->entry_data);
|
||||||
|
if(R_SUCCEEDED(rc))
|
||||||
|
{
|
||||||
|
if(entries == 0)
|
||||||
|
{
|
||||||
|
/* there are no more entries; ENOENT signals end-of-directory */
|
||||||
|
r->_errno = ENOENT;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
dir->index = 0;
|
||||||
|
dir->size = entries;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if(R_SUCCEEDED(rc))
|
if(R_SUCCEEDED(rc))
|
||||||
{
|
{
|
||||||
if(entries == 0)
|
entry = &dir->entry_data[dir->index];
|
||||||
{
|
|
||||||
/* there are no more entries; ENOENT signals end-of-directory */
|
|
||||||
r->_errno = ENOENT;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* fill in the stat info */
|
/* fill in the stat info */
|
||||||
filestat->st_ino = 0;
|
filestat->st_ino = 0;
|
||||||
if(dir->entry_data.attributes & FS_ATTRIBUTE_DIRECTORY)
|
if(entry->attributes & FS_ATTRIBUTE_DIRECTORY)
|
||||||
filestat->st_mode = S_IFDIR;
|
filestat->st_mode = S_IFDIR;
|
||||||
else
|
else
|
||||||
filestat->st_mode = S_IFREG;
|
filestat->st_mode = S_IFREG;
|
||||||
|
|
||||||
/* convert name from UTF-16 to UTF-8 */
|
/* convert name from UTF-16 to UTF-8 */
|
||||||
memset(filename, 0, NAME_MAX);
|
memset(filename, 0, NAME_MAX);
|
||||||
units = utf16_to_utf8((uint8_t*)filename, dir->entry_data.name, NAME_MAX);
|
units = utf16_to_utf8((uint8_t*)filename, entry->name, NAME_MAX);
|
||||||
if(units < 0)
|
if(units < 0)
|
||||||
{
|
{
|
||||||
r->_errno = EILSEQ;
|
r->_errno = EILSEQ;
|
||||||
|
Loading…
Reference in New Issue
Block a user