Add sdmcWriteSafe

This commit is contained in:
Michael Theall 2016-01-12 16:22:30 -06:00
parent 15897d0eab
commit c5674b3126
2 changed files with 79 additions and 2 deletions

View File

@ -9,5 +9,8 @@
/// Initializes the SDMC driver. /// Initializes the SDMC driver.
Result sdmcInit(void); Result sdmcInit(void);
/// Enable/disable copy in sdmc_write
void sdmcWriteSafe(bool enable);
/// Exits the SDMC driver. /// Exits the SDMC driver.
Result sdmcExit(void); Result sdmcExit(void);

View File

@ -27,6 +27,7 @@ static int sdmc_translate_error(Result error);
static int sdmc_open(struct _reent *r, void *fileStruct, const char *path, int flags, int mode); static int sdmc_open(struct _reent *r, void *fileStruct, const char *path, int flags, int mode);
static int sdmc_close(struct _reent *r, int fd); static int sdmc_close(struct _reent *r, int fd);
static ssize_t sdmc_write(struct _reent *r, int fd, const char *ptr, size_t len); static ssize_t sdmc_write(struct _reent *r, int fd, const char *ptr, size_t len);
static ssize_t sdmc_write_safe(struct _reent *r, int fd, const char *ptr, size_t len);
static ssize_t sdmc_read(struct _reent *r, int fd, char *ptr, size_t len); static ssize_t sdmc_read(struct _reent *r, int fd, char *ptr, size_t len);
static off_t sdmc_seek(struct _reent *r, int fd, off_t pos, int dir); static off_t sdmc_seek(struct _reent *r, int fd, off_t pos, int dir);
static int sdmc_fstat(struct _reent *r, int fd, struct stat *st); static int sdmc_fstat(struct _reent *r, int fd, struct stat *st);
@ -72,7 +73,7 @@ sdmc_devoptab =
.structSize = sizeof(sdmc_file_t), .structSize = sizeof(sdmc_file_t),
.open_r = sdmc_open, .open_r = sdmc_open,
.close_r = sdmc_close, .close_r = sdmc_close,
.write_r = sdmc_write, .write_r = sdmc_write_safe,
.read_r = sdmc_read, .read_r = sdmc_read,
.seek_r = sdmc_seek, .seek_r = sdmc_seek,
.fstat_r = sdmc_fstat, .fstat_r = sdmc_fstat,
@ -280,6 +281,21 @@ Result sdmcInit(void)
return rc; return rc;
} }
/*! Enable/disable safe sdmc_write
*
* Safe sdmc_write is enabled by default. If it is disabled, you will be
* unable to write from read-only buffers.
*
* @param[in] enable Whether to enable
*/
void sdmcWriteSafe(bool enable)
{
if(enable)
sdmc_devoptab.write_r = sdmc_write_safe;
else
sdmc_devoptab.write_r = sdmc_write;
}
/*! Clean up SDMC device */ /*! Clean up SDMC device */
Result sdmcExit(void) Result sdmcExit(void)
{ {
@ -442,6 +458,64 @@ sdmc_write(struct _reent *r,
int fd, int fd,
const char *ptr, const char *ptr,
size_t len) size_t len)
{
Result rc;
u32 bytes;
u32 sync = 0;
/* get pointer to our data */
sdmc_file_t *file = (sdmc_file_t*)fd;
/* check that the file was opened with write access */
if((file->flags & O_ACCMODE) == O_RDONLY)
{
r->_errno = EBADF;
return -1;
}
/* check if this is synchronous or not */
if(file->flags & O_SYNC)
sync = FS_WRITE_FLUSH | FS_WRITE_UPDATE_TIME;
if(file->flags & O_APPEND)
{
/* append means write from the end of the file */
rc = FSFILE_GetSize(file->fd, &file->offset);
if(R_FAILED(rc))
{
r->_errno = sdmc_translate_error(rc);
return -1;
}
}
rc = FSFILE_Write(file->fd, &bytes, file->offset,
(u32*)ptr, len, sync);
if(R_FAILED(rc))
{
r->_errno = sdmc_translate_error(rc);
return -1;
}
file->offset += bytes;
return bytes;
}
/*! Write to an open file
*
* @param[in,out] r newlib reentrancy struct
* @param[in,out] fd Pointer to sdmc_file_t
* @param[in] ptr Pointer to data to write
* @param[in] len Length of data to write
*
* @returns number of bytes written
* @returns -1 for error
*/
static ssize_t
sdmc_write_safe(struct _reent *r,
int fd,
const char *ptr,
size_t len)
{ {
Result rc; Result rc;
u32 bytes, bytesWritten = 0; u32 bytes, bytesWritten = 0;
@ -459,7 +533,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 = FS_WRITE_FLUSH; sync = FS_WRITE_FLUSH | FS_WRITE_UPDATE_TIME;
if(file->flags & O_APPEND) if(file->flags & O_APPEND)
{ {