Browse Source

Fixed filesystem operations on Android

Full paths are used as-is, relative paths are prepended with SDL_GetAndroidInternalStoragePath(), and operations fall back to the asset system as appropriate.

This is consistent with the behavior of opening files on Android.
Sam Lantinga 2 weeks ago
parent
commit
26dd4e3abb
2 changed files with 96 additions and 11 deletions
  1. 95 7
      src/filesystem/posix/SDL_sysfsops.c
  2. 1 4
      test/testautomation_surface.c

+ 95 - 7
src/filesystem/posix/SDL_sysfsops.c

@@ -41,6 +41,21 @@
 
 bool SDL_SYS_EnumerateDirectory(const char *path, SDL_EnumerateDirectoryCallback cb, void *userdata)
 {
+#ifdef SDL_PLATFORM_ANDROID
+    if (*path != '/') {
+        char *apath = NULL;
+        SDL_asprintf(&apath, "%s/%s", SDL_GetAndroidInternalStoragePath(), path);
+        if (!apath) {
+            return false;
+        }
+        const bool retval = SDL_SYS_EnumerateDirectory(apath, cb, userdata);
+        SDL_free(apath);
+        if (retval) {
+            return true;
+        }
+    }
+#endif
+
     char *pathwithsep = NULL;
     int pathwithseplen = SDL_asprintf(&pathwithsep, "%s/", path);
     if ((pathwithseplen == -1) || (!pathwithsep)) {
@@ -88,7 +103,23 @@ bool SDL_SYS_EnumerateDirectory(const char *path, SDL_EnumerateDirectoryCallback
 
 bool SDL_SYS_RemovePath(const char *path)
 {
-    int rc = remove(path);
+    int rc;
+
+#ifdef SDL_PLATFORM_ANDROID
+    if (*path == '/') {
+        rc = remove(path);
+    } else {
+        char *apath = NULL;
+        SDL_asprintf(&apath, "%s/%s", SDL_GetAndroidInternalStoragePath(), path);
+        if (!apath) {
+            return false;
+        }
+        rc = remove(apath);
+        SDL_free(apath);
+    }
+#else
+    rc = remove(path);
+#endif
     if (rc < 0) {
         if (errno == ENOENT) {
             // It's already gone, this is a success
@@ -101,7 +132,33 @@ bool SDL_SYS_RemovePath(const char *path)
 
 bool SDL_SYS_RenamePath(const char *oldpath, const char *newpath)
 {
-    if (rename(oldpath, newpath) < 0) {
+    int rc;
+
+#ifdef SDL_PLATFORM_ANDROID
+    char *aoldpath = NULL;
+    char *anewpath = NULL;
+    if (*oldpath != '/') {
+        SDL_asprintf(&aoldpath, "%s/%s", SDL_GetAndroidInternalStoragePath(), oldpath);
+        if (!aoldpath) {
+            return false;
+        }
+        oldpath = aoldpath;
+    }
+    if (*newpath != '/') {
+        SDL_asprintf(&anewpath, "%s/%s", SDL_GetAndroidInternalStoragePath(), newpath);
+        if (!anewpath) {
+            SDL_free(aoldpath);
+            return false;
+        }
+        newpath = anewpath;
+    }
+    rc = rename(oldpath, newpath);
+    SDL_free(aoldpath);
+    SDL_free(anewpath);
+#else
+    rc = rename(oldpath, newpath);
+#endif
+    if (rc < 0) {
         return SDL_SetError("Can't rename path: %s", strerror(errno));
     }
     return true;
@@ -164,7 +221,23 @@ done:
 
 bool SDL_SYS_CreateDirectory(const char *path)
 {
-    const int rc = mkdir(path, 0770);
+    int rc;
+
+#ifdef SDL_PLATFORM_ANDROID
+    if (*path == '/') {
+        rc = mkdir(path, 0770);
+    } else {
+        char *apath = NULL;
+        SDL_asprintf(&apath, "%s/%s", SDL_GetAndroidInternalStoragePath(), path);
+        if (!apath) {
+            return false;
+        }
+        rc = mkdir(apath, 0770);
+        SDL_free(apath);
+    }
+#else
+    rc = mkdir(path, 0770);
+#endif
     if (rc < 0) {
         const int origerrno = errno;
         if (origerrno == EEXIST) {
@@ -181,13 +254,28 @@ bool SDL_SYS_CreateDirectory(const char *path)
 bool SDL_SYS_GetPathInfo(const char *path, SDL_PathInfo *info)
 {
     struct stat statbuf;
-    const int rc = stat(path, &statbuf);
+    int rc;
+
+#ifdef SDL_PLATFORM_ANDROID
+    if (*path == '/') {
+        rc = stat(path, &statbuf);
+    } else {
+        char *apath = NULL;
+        SDL_asprintf(&apath, "%s/%s", SDL_GetAndroidInternalStoragePath(), path);
+        if (!apath) {
+            return false;
+        }
+        rc = stat(apath, &statbuf);
+        SDL_free(apath);
+    }
     if (rc < 0) {
-        #ifdef SDL_PLATFORM_ANDROID  // Maybe it's an asset...?
         return Android_JNI_GetAssetPathInfo(path, info);
-        #else
+    }
+#else
+    rc = stat(path, &statbuf);
+#endif
+    if (rc < 0) {
         return SDL_SetError("Can't stat: %s", strerror(errno));
-        #endif
     } else if (S_ISREG(statbuf.st_mode)) {
         info->type = SDL_PATHTYPE_FILE;
         info->size = (Uint64) statbuf.st_size;

+ 1 - 4
test/testautomation_surface.c

@@ -305,10 +305,7 @@ static void testBlitBlendMode(int mode)
 /* Helper to check that a file exists */
 static void AssertFileExist(const char *filename)
 {
-    struct stat st;
-    int ret = stat(filename, &st);
-
-    SDLTest_AssertCheck(ret == 0, "Verify file '%s' exists", filename);
+    SDLTest_AssertCheck(SDL_GetPathInfo(filename, NULL), "Verify file '%s' exists", filename);
 }
 
 /* Test case functions */