Merge 93847b0817
into b5723c9209
This commit is contained in:
commit
8616855f4c
@ -5,6 +5,8 @@
|
|||||||
#include <sys/iosupport.h>
|
#include <sys/iosupport.h>
|
||||||
#include <sys/param.h>
|
#include <sys/param.h>
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <dirent.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <3ds.h>
|
#include <3ds.h>
|
||||||
|
|
||||||
@ -39,12 +41,25 @@ static int sdmc_fchmod(struct _reent *r, int fd, mode_t mode);
|
|||||||
|
|
||||||
/*! @cond INTERNAL */
|
/*! @cond INTERNAL */
|
||||||
|
|
||||||
|
#define SDMC_FILEBUFFSIZE 0x4000 /* Size of file data buffer */
|
||||||
|
#define SDMC_FILEBUFFMASK (-SDMC_FILEBUFFSIZE) /* For calculating the start of the buffer's current chunk */
|
||||||
|
#define SDMC_FILEOFFMASK (SDMC_FILEBUFFSIZE-1) /* For calculating the start offset within the buffer */
|
||||||
|
|
||||||
|
#define SDMC_BUFFINVALID 0xFFFFFFFF /* To indicate that a buffer has not actually been loaded yet */
|
||||||
|
|
||||||
/*! Open file struct */
|
/*! Open file struct */
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
Handle fd; /*! CTRU handle */
|
Handle fd; /*! CTRU handle */
|
||||||
int flags; /*! Flags used in open(2) */
|
int flags; /*! Flags used in open(2) */
|
||||||
u64 offset; /*! Current file offset */
|
u64 offset; /*! Current file offset */
|
||||||
|
|
||||||
|
u8 buffer[SDMC_FILEBUFFSIZE]; /* File data buffer for speed-of-access */
|
||||||
|
u64 boffset; /* File start offset of the current buffered chunk */
|
||||||
|
u32 bsize; /* Amount of valid data in the buffer before EOF */
|
||||||
|
|
||||||
|
u64 size; /* Size of the file in bytes*/
|
||||||
|
|
||||||
} sdmc_file_t;
|
} sdmc_file_t;
|
||||||
|
|
||||||
/*! Open directory struct */
|
/*! Open directory struct */
|
||||||
@ -251,6 +266,19 @@ sdmc_open(struct _reent *r,
|
|||||||
file->fd = fd;
|
file->fd = fd;
|
||||||
file->flags = (flags & (O_ACCMODE|O_APPEND|O_SYNC));
|
file->flags = (flags & (O_ACCMODE|O_APPEND|O_SYNC));
|
||||||
file->offset = 0;
|
file->offset = 0;
|
||||||
|
|
||||||
|
/* initialize buffer offset to buffer on first-read/write */
|
||||||
|
file->boffset = SDMC_BUFFINVALID;
|
||||||
|
file->bsize = 0;
|
||||||
|
|
||||||
|
/* record the file's size */
|
||||||
|
rc = FSFILE_GetSize(file->fd, &file->size);
|
||||||
|
if(rc != 0)
|
||||||
|
{
|
||||||
|
r->_errno = rc;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -272,9 +300,22 @@ sdmc_close(struct _reent *r,
|
|||||||
{
|
{
|
||||||
Result rc;
|
Result rc;
|
||||||
|
|
||||||
|
u32 bytes;
|
||||||
|
|
||||||
/* get pointer to our data */
|
/* get pointer to our data */
|
||||||
sdmc_file_t *file = (sdmc_file_t*)fd;
|
sdmc_file_t *file = (sdmc_file_t*)fd;
|
||||||
|
|
||||||
|
/* check if the file was opened with write access */
|
||||||
|
if((file->flags & O_ACCMODE) != O_RDONLY)
|
||||||
|
{
|
||||||
|
/* flush the current buffer */
|
||||||
|
if((rc = FSFILE_Write(file->fd, &bytes, file->boffset, file->buffer, file->bsize, FS_WRITE_FLUSH)) != 0)
|
||||||
|
{
|
||||||
|
r->_errno = rc;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
rc = FSFILE_Close(file->fd);
|
rc = FSFILE_Close(file->fd);
|
||||||
if(rc == 0)
|
if(rc == 0)
|
||||||
return 0;
|
return 0;
|
||||||
@ -304,6 +345,10 @@ sdmc_write(struct _reent *r,
|
|||||||
u32 sync = 0;
|
u32 sync = 0;
|
||||||
u64 offset;
|
u64 offset;
|
||||||
|
|
||||||
|
u32 start;
|
||||||
|
u32 curlen;
|
||||||
|
u32 total;
|
||||||
|
|
||||||
/* get pointer to our data */
|
/* get pointer to our data */
|
||||||
sdmc_file_t *file = (sdmc_file_t*)fd;
|
sdmc_file_t *file = (sdmc_file_t*)fd;
|
||||||
|
|
||||||
@ -316,7 +361,7 @@ sdmc_write(struct _reent *r,
|
|||||||
|
|
||||||
/* check if this is synchronous or not */
|
/* check if this is synchronous or not */
|
||||||
if(file->flags & O_SYNC)
|
if(file->flags & O_SYNC)
|
||||||
sync = 0x10001;
|
sync = FS_WRITE_FLUSH;
|
||||||
|
|
||||||
/* initialize offset */
|
/* initialize offset */
|
||||||
offset = file->offset;
|
offset = file->offset;
|
||||||
@ -331,23 +376,62 @@ sdmc_write(struct _reent *r,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* TODO: Copy to internal buffer and write in chunks.
|
/* initialize buffer start position, copy length, and total copied count */
|
||||||
* You cannot write from read-only memory.
|
start = offset & SDMC_FILEOFFMASK;
|
||||||
*/
|
curlen = SDMC_FILEBUFFSIZE-start;
|
||||||
|
total = 0;
|
||||||
|
|
||||||
/* write the data */
|
/* if the target location is not in the currently-buffered chunk, save the current buffer and load the target chunk */
|
||||||
rc = FSFILE_Write(file->fd, &bytes, offset, (u32*)ptr, (u32)len, sync);
|
if(file->boffset != (offset & SDMC_FILEBUFFMASK))
|
||||||
if(rc == 0)
|
|
||||||
{
|
{
|
||||||
/* update current file offset; if O_APPEND, this moves it to the
|
|
||||||
* new end-of-file
|
/* if there is a valid buffer */
|
||||||
*/
|
if(file->boffset != SDMC_BUFFINVALID)
|
||||||
file->offset = offset + bytes;
|
{
|
||||||
return (ssize_t)bytes;
|
buffernext:
|
||||||
|
|
||||||
|
/* flush the current buffer */
|
||||||
|
if((rc = FSFILE_Write(file->fd, &bytes, file->boffset, file->buffer, file->bsize, sync)) != 0)
|
||||||
|
{
|
||||||
|
r->_errno = rc;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* buffer the target chunk */
|
||||||
|
file->boffset = offset & SDMC_FILEBUFFMASK;
|
||||||
|
if((rc = FSFILE_Read(file->fd, &file->bsize, file->boffset, file->buffer, SDMC_FILEBUFFSIZE)) != 0)
|
||||||
|
{
|
||||||
|
r->_errno = rc;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// else
|
||||||
|
// bytes = file->boffset + start;
|
||||||
|
|
||||||
|
if(curlen > len)
|
||||||
|
curlen = len;
|
||||||
|
|
||||||
|
memcpy(file->buffer+start, ptr, curlen);
|
||||||
|
total += curlen;
|
||||||
|
offset += curlen;
|
||||||
|
if((offset - file->boffset) > file->bsize)
|
||||||
|
file->bsize = offset - file->boffset;
|
||||||
|
if((len -= curlen) > 0)
|
||||||
|
{
|
||||||
|
ptr += curlen;
|
||||||
|
start = 0;
|
||||||
|
if(len > SDMC_FILEBUFFSIZE)
|
||||||
|
curlen = SDMC_FILEBUFFSIZE;
|
||||||
|
else
|
||||||
|
curlen = len;
|
||||||
|
goto buffernext;
|
||||||
}
|
}
|
||||||
|
|
||||||
r->_errno = rc;
|
file->offset = offset;
|
||||||
return -1;
|
|
||||||
|
/* return the total number of bytes that were actually copied */
|
||||||
|
return (ssize_t)total;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! Read from an open file
|
/*! Read from an open file
|
||||||
@ -367,7 +451,11 @@ sdmc_read(struct _reent *r,
|
|||||||
size_t len)
|
size_t len)
|
||||||
{
|
{
|
||||||
Result rc;
|
Result rc;
|
||||||
u32 bytes;
|
// u32 bytes;
|
||||||
|
|
||||||
|
u32 start;
|
||||||
|
u32 curlen;
|
||||||
|
u32 total;
|
||||||
|
|
||||||
/* get pointer to our data */
|
/* get pointer to our data */
|
||||||
sdmc_file_t *file = (sdmc_file_t*)fd;
|
sdmc_file_t *file = (sdmc_file_t*)fd;
|
||||||
@ -379,17 +467,55 @@ sdmc_read(struct _reent *r,
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* read the data */
|
if((file->offset + len) > file->size)
|
||||||
rc = FSFILE_Read(file->fd, &bytes, file->offset, (u32*)ptr, (u32)len);
|
if((len = (file->size - file->offset)) <= 0)
|
||||||
if(rc == 0)
|
return(0);
|
||||||
|
|
||||||
|
/* initialize buffer start position, copy length, and total copied count */
|
||||||
|
start = file->offset & SDMC_FILEOFFMASK;
|
||||||
|
curlen = SDMC_FILEBUFFSIZE-start;
|
||||||
|
total = 0;
|
||||||
|
|
||||||
|
/* if the requested data does not reside in the currently-buffered chunk, load the buffer */
|
||||||
|
if(file->boffset != (file->offset & SDMC_FILEBUFFMASK))
|
||||||
{
|
{
|
||||||
/* update current file offset */
|
buffernext:
|
||||||
file->offset += bytes;
|
file->boffset = file->offset & SDMC_FILEBUFFMASK;
|
||||||
return (ssize_t)bytes;
|
/* read the data */
|
||||||
|
if((rc = FSFILE_Read(file->fd, &file->bsize, file->boffset, file->buffer, SDMC_FILEBUFFSIZE)) != 0)
|
||||||
|
{
|
||||||
|
r->_errno = rc;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// else
|
||||||
|
// bytes = file->boffset + start;
|
||||||
|
|
||||||
|
if(curlen > len)
|
||||||
|
curlen = len;
|
||||||
|
if(curlen > file->bsize)
|
||||||
|
curlen = file->bsize;
|
||||||
|
|
||||||
|
memcpy(ptr, file->buffer+start, curlen);
|
||||||
|
total += curlen;
|
||||||
|
file->offset += curlen;
|
||||||
|
if((len -= curlen) > 0)
|
||||||
|
{
|
||||||
|
if(curlen + start == SDMC_FILEBUFFSIZE)
|
||||||
|
{
|
||||||
|
ptr += curlen;
|
||||||
|
start = 0;
|
||||||
|
if(len > SDMC_FILEBUFFSIZE)
|
||||||
|
curlen = SDMC_FILEBUFFSIZE;
|
||||||
|
else
|
||||||
|
curlen = len;
|
||||||
|
goto buffernext;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
r->_errno = rc;
|
/* return the total number of bytes that were actually copied */
|
||||||
return -1;
|
return (ssize_t)total;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! Update an open file's current offset
|
/*! Update an open file's current offset
|
||||||
@ -855,9 +981,18 @@ sdmc_fsync(struct _reent *r,
|
|||||||
{
|
{
|
||||||
Result rc;
|
Result rc;
|
||||||
|
|
||||||
|
u32 bytes;
|
||||||
|
|
||||||
/* get pointer to our data */
|
/* get pointer to our data */
|
||||||
sdmc_file_t *file = (sdmc_file_t*)fd;
|
sdmc_file_t *file = (sdmc_file_t*)fd;
|
||||||
|
|
||||||
|
/* flush the current buffer */
|
||||||
|
if((rc = FSFILE_Write(file->fd, &bytes, file->boffset, file->buffer, file->bsize, FS_WRITE_FLUSH)) != 0)
|
||||||
|
{
|
||||||
|
r->_errno = rc;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
rc = FSFILE_Flush(file->fd);
|
rc = FSFILE_Flush(file->fd);
|
||||||
if(rc == 0)
|
if(rc == 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
Loading…
Reference in New Issue
Block a user