]> Chaos Git - corbenik/ctrulib.git/commitdiff
Add sdmcWriteSafe
authorMichael Theall <pigman46@gmail.com>
Tue, 12 Jan 2016 22:22:30 +0000 (16:22 -0600)
committerMichael Theall <pigman46@gmail.com>
Tue, 12 Jan 2016 22:22:30 +0000 (16:22 -0600)
libctru/include/3ds/sdmc.h
libctru/source/sdmc_dev.c

index d86acde10aebcdc7a54e0d669f095c1984574f3c..2b17e5340c18ec69c7d1c6861f863183633e86e0 100644 (file)
@@ -9,5 +9,8 @@
 /// Initializes the SDMC driver.
 Result sdmcInit(void);
 
+/// Enable/disable copy in sdmc_write
+void sdmcWriteSafe(bool enable);
+
 /// Exits the SDMC driver.
 Result sdmcExit(void);
index 5836270cbbbfcbb69734a44bebdeb5ae319a1864..45de57f71ad89a81759701b66d3478bc6bfb5c0e 100644 (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_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_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 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);
@@ -72,7 +73,7 @@ sdmc_devoptab =
   .structSize   = sizeof(sdmc_file_t),
   .open_r       = sdmc_open,
   .close_r      = sdmc_close,
-  .write_r      = sdmc_write,
+  .write_r      = sdmc_write_safe,
   .read_r       = sdmc_read,
   .seek_r       = sdmc_seek,
   .fstat_r      = sdmc_fstat,
@@ -280,6 +281,21 @@ Result sdmcInit(void)
   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 */
 Result sdmcExit(void)
 {
@@ -442,6 +458,64 @@ sdmc_write(struct _reent *r,
            int           fd,
            const char    *ptr,
            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;
   u32         bytes, bytesWritten = 0;
@@ -459,7 +533,7 @@ sdmc_write(struct _reent *r,
 
   /* check if this is synchronous or not */
   if(file->flags & O_SYNC)
-    sync = FS_WRITE_FLUSH;
+    sync = FS_WRITE_FLUSH | FS_WRITE_UPDATE_TIME;
 
   if(file->flags & O_APPEND)
   {