[Libreoffice-commits] .: 4 commits - README.Android sal/android sal/osl solenv/inc

Tor Lillqvist tml at kemper.freedesktop.org
Tue Jan 3 14:19:42 PST 2012


 README.Android                    |   27 ++++----
 sal/android/lo-bootstrap.c        |  121 +++++++++++++++++++++++++++++++-------
 sal/osl/unx/file.cxx              |    2 
 sal/osl/unx/file_misc.cxx         |  104 +++++++++++++++++++++++++-------
 sal/osl/unx/uunxapi.cxx           |   32 +++++++++-
 solenv/inc/unxandr/lo-bootstrap.h |    2 
 6 files changed, 229 insertions(+), 59 deletions(-)

New commits:
commit 90b141496018201ee9df721b382cd2b177a3a92f
Author: Tor Lillqvist <tlillqvist at suse.com>
Date:   Wed Jan 4 00:03:18 2012 +0200

    Use the lo_apk_* functions for files under /assets

diff --git a/sal/osl/unx/file_misc.cxx b/sal/osl/unx/file_misc.cxx
index e1da32a..7c84086 100644
--- a/sal/osl/unx/file_misc.cxx
+++ b/sal/osl/unx/file_misc.cxx
@@ -53,6 +53,10 @@
 
 #include <algorithm>
 
+#ifdef ANDROID
+#include <lo-bootstrap.h>
+#endif
+
 /************************************************************************
  *   ToDo
  *
@@ -70,6 +74,15 @@ typedef struct
 {
     rtl_uString* ustrPath;           /* holds native directory path */
     DIR*         pDirStruct;
+#ifdef ANDROID
+    enum Kind
+    {
+        KIND_DIRENT = 1,
+        KIND_ASSETS = 2
+    };
+    int eKind;
+    lo_apk_dir*  pApkDirStruct;
+#endif
 } oslDirectoryImpl;
 
 DirectoryItem_Impl::DirectoryItem_Impl(
@@ -169,33 +182,64 @@ oslFileError SAL_CALL osl_openDirectory(rtl_uString* ustrDirectoryURL, oslDirect
 #endif /* MACOSX */
      )
     {
-        /* open directory */
-        DIR *pdir = opendir( path );
-
-        if( pdir )
+#ifdef ANDROID
+        if( strncmp( path, "/assets/", sizeof( "/assets/" ) - 1) == 0 )
         {
-            /* create and initialize impl structure */
-            oslDirectoryImpl* pDirImpl = (oslDirectoryImpl*) rtl_allocateMemory( sizeof(oslDirectoryImpl) );
-
-            if( pDirImpl )
-            {
-                pDirImpl->pDirStruct = pdir;
-                pDirImpl->ustrPath = ustrSystemPath;
+            lo_apk_dir *pdir = lo_apk_opendir( path );
 
-                *pDirectory = (oslDirectory) pDirImpl;
-                return osl_File_E_None;
-            }
-            else
+            if( pdir )
             {
-                errno = ENOMEM;
-                closedir( pdir );
+                oslDirectoryImpl* pDirImpl = (oslDirectoryImpl*) rtl_allocateMemory( sizeof(oslDirectoryImpl) );
+
+                if( pDirImpl )
+                    {
+                        pDirImpl->eKind = oslDirectoryImpl::KIND_ASSETS;
+                        pDirImpl->pApkDirStruct = pdir;
+                        pDirImpl->ustrPath = ustrSystemPath;
+
+                        *pDirectory = (oslDirectory) pDirImpl;
+                        return osl_File_E_None;
+                    }
+                else
+                    {
+                        errno = ENOMEM;
+                        lo_apk_closedir( pdir );
+                    }
             }
         }
         else
+#endif
         {
+            /* open directory */
+            DIR *pdir = opendir( path );
+
+            if( pdir )
+            {
+                /* create and initialize impl structure */
+                oslDirectoryImpl* pDirImpl = (oslDirectoryImpl*) rtl_allocateMemory( sizeof(oslDirectoryImpl) );
+
+                if( pDirImpl )
+                {
+                    pDirImpl->pDirStruct = pdir;
+                    pDirImpl->ustrPath = ustrSystemPath;
+#ifdef ANDROID
+                    pDirImpl->eKind = oslDirectoryImpl::KIND_DIRENT;
+#endif
+                    *pDirectory = (oslDirectory) pDirImpl;
+                    return osl_File_E_None;
+                }
+                else
+                {
+                    errno = ENOMEM;
+                    closedir( pdir );
+                }
+            }
+            else
+            {
 #ifdef DEBUG_OSL_FILE
-            perror ("osl_openDirectory"); fprintf (stderr, path);
+                perror ("osl_openDirectory"); fprintf (stderr, path);
 #endif
+            }
         }
     }
 
@@ -218,10 +262,17 @@ oslFileError SAL_CALL osl_closeDirectory( oslDirectory Directory )
     if( NULL == pDirImpl )
         return osl_File_E_INVAL;
 
-    /* close directory */
-    if( closedir( pDirImpl->pDirStruct ) )
+#ifdef ANDROID
+    if( pDirImpl->eKind == oslDirectoryImpl::KIND_ASSETS )
+    {
+        if (lo_apk_closedir( pDirImpl->pApkDirStruct ))
+            err = osl_File_E_IO;
+    }
+    else
+#endif
     {
-        err = oslTranslateFileError(OSL_FET_ERROR, errno);
+        if( closedir( pDirImpl->pDirStruct ) )
+            err = oslTranslateFileError(OSL_FET_ERROR, errno);
     }
 
     /* cleanup members */
@@ -272,7 +323,16 @@ oslFileError SAL_CALL osl_getNextDirectoryItem(oslDirectory Directory, oslDirect
     if ((NULL == Directory) || (NULL == pItem))
         return osl_File_E_INVAL;
 
-    pEntry = osl_readdir_impl_(pDirImpl->pDirStruct, sal_True);
+#ifdef ANDROID
+    if( pDirImpl->eKind == oslDirectoryImpl::KIND_ASSETS )
+    {
+        pEntry = lo_apk_readdir(pDirImpl->pApkDirStruct);
+    }
+    else
+#endif
+    {
+        pEntry = osl_readdir_impl_(pDirImpl->pDirStruct, sal_True);
+    }
 
     if (NULL == pEntry)
         return osl_File_E_NOENT;
diff --git a/sal/osl/unx/uunxapi.cxx b/sal/osl/unx/uunxapi.cxx
index ee3cdeb..3c2067b 100644
--- a/sal/osl/unx/uunxapi.cxx
+++ b/sal/osl/unx/uunxapi.cxx
@@ -47,6 +47,10 @@
  #include <osl/thread.h>
  #endif
 
+ #ifdef ANDROID
+ #include <lo-bootstrap.h>
+ #endif
+
  //###########################
  inline rtl::OString OUStringToOString(const rtl_uString* s)
  {
@@ -80,7 +84,24 @@
  int access_u(const rtl_uString* pustrPath, int mode)
  {
 #ifndef MACOSX // not MACOSX
-    return access(OUStringToOString(pustrPath).getStr(), mode);
+    const char *path = OUStringToOString(pustrPath).getStr();
+#ifdef ANDROID
+    if (strncmp(path, "/assets", sizeof("/assets")-1) == 0 &&
+        (path[sizeof("/assets")-1] == '\0' ||
+         path[sizeof("/assets")-1] == '/'))
+    {
+        struct stat stat;
+        if (lo_apk_lstat(path, &stat) == -1)
+            return -1;
+        if (mode & W_OK)
+        {
+            errno = EACCES;
+            return -1;
+        }
+        return 0;
+    }
+#endif
+    return access(path, mode);
 #else
     return access(macxp_resolveAliasAndConvert(pustrPath).getStr(), mode);
 #endif
@@ -114,7 +135,14 @@
   int lstat_u(const rtl_uString* pustrPath, struct stat* buf)
  {
 #ifndef MACOSX  // not MACOSX
-    return lstat(OUStringToOString(pustrPath).getStr(), buf);
+    const char *path = OUStringToOString(pustrPath).getStr();
+#ifdef ANDROID
+    if (strncmp(path, "/assets", sizeof("/assets")-1) == 0 &&
+        (path[sizeof("/assets")-1] == '\0' ||
+         path[sizeof("/assets")-1] == '/'))
+        return lo_apk_lstat(path, buf);
+#endif
+    return lstat(path, buf);
 #else
     return lstat(macxp_resolveAliasAndConvert(pustrPath).getStr(), buf);
 #endif
commit 2717fe35ae7fd35b787b53d291919449d307ea01
Author: Tor Lillqvist <tlillqvist at suse.com>
Date:   Tue Jan 3 23:58:19 2012 +0200

    Use sizeof(s)-1 instead of strlen(s) on string literals

diff --git a/sal/osl/unx/file.cxx b/sal/osl/unx/file.cxx
index 458554e..bb31902 100644
--- a/sal/osl/unx/file.cxx
+++ b/sal/osl/unx/file.cxx
@@ -914,7 +914,7 @@ SAL_CALL osl_openFile( rtl_uString* ustrFileURL, oslFileHandle* pHandle, sal_uIn
      * we should mmap it from the .apk file
      */
     if (!(uFlags & osl_File_OpenFlag_Write) &&
-        strncmp (buffer, "/assets/", strlen ("/assets/")) == 0)
+        strncmp (buffer, "/assets/", sizeof ("/assets/") - 1) == 0)
     {
         void *address;
         size_t size;
commit 7cc28bae3a8aded334f40bf3a5593b5f6067fdd8
Author: Tor Lillqvist <tlillqvist at suse.com>
Date:   Tue Jan 3 16:33:10 2012 +0200

    Fixes for the lo-bootstrap apk element code
    
    Fix some off-by-one style errors, add a new lo_apk_lstat() function,
    and (temporarily) add some debugging logging.

diff --git a/sal/android/lo-bootstrap.c b/sal/android/lo-bootstrap.c
index 07c1687..7fc171b 100644
--- a/sal/android/lo-bootstrap.c
+++ b/sal/android/lo-bootstrap.c
@@ -903,13 +903,17 @@ new_dir(const char *folder_path,
     lo_apk_dir *result;
 
     result = malloc(sizeof(*result));
-    if (result == NULL)
+    if (result == NULL) {
+        LOGE("lo_apk_opendir: Out of memory");
         return NULL;
+    }
 
     result->folder_path = strdup(folder_path);
     result->current_entry = start_entry;
     result->remaining_entries = remaining_entries;
 
+    LOGI("new_dir(%s,%p,%d) = %p", folder_path, start_entry, remaining_entries, result);
+
     return result;
 }
 
@@ -918,38 +922,43 @@ __attribute__ ((visibility("default")))
 lo_apk_dir *
 lo_apk_opendir(const char *dirname)
 {
+    const char *dn = dirname;
     int count = cdir_entries;
     struct cdir_entry *entry = cdir_start;
-    size_t name_size = strlen(dirname);
+    size_t name_size;
 
-    if (*dirname == '/') {
-        dirname++;
-        if (!dirname[0])
+    if (*dn == '/') {
+        dn++;
+        if (!dn[0])
             return new_dir("", cdir_start, count);
     }
 
+    name_size = strlen(dn);
     while (count--) {
         if (letoh16(entry->filename_size) >= name_size &&
-            !memcmp(entry->data, dirname, name_size) &&
+            !memcmp(entry->data, dn, name_size) &&
             entry->data[name_size] == '/')
             break;
         entry = (struct cdir_entry *)((char *)entry + cdir_entry_size(entry));
     }
     if (count >= 0)
-        return new_dir(dirname, entry, count+1);
+        return new_dir(dn, entry, count+1);
+
+    LOGI("lo_apk_opendir(%s) = NULL", dirname);
 
     return NULL;
 }
 
 static int
-path_component_length(const char *path)
+path_component_length(const char *path,
+                      const char *path_end)
 {
-    const char *slash = strchr(path, '/');
-
-    if (slash)
-        return slash - path;
+    const char *p = path;
+    while (p < path_end &&
+           *p != '/')
+        p++;
 
-    return strlen(path);
+    return p - path;
 }
 
 __attribute__ ((visibility("default")))
@@ -959,33 +968,39 @@ lo_apk_readdir(lo_apk_dir *dirp)
     static struct dirent result;
     size_t folder_size = strlen(dirp->folder_path);
 
-    while (dirp->remaining_entries > 0) {
-        const char *folder_end = dirp->current_entry->data + folder_size;
+    while (dirp->remaining_entries-- > 0) {
+        struct cdir_entry *entry = dirp->current_entry;
+        const char *folder_end = entry->data + folder_size;
         int entry_len;
 
-        if (letoh16(dirp->current_entry->filename_size) > folder_size &&
-            !memcmp(dirp->current_entry->data, dirp->folder_path, folder_size) &&
+        dirp->current_entry = (struct cdir_entry *)((char *)entry + cdir_entry_size(entry));
+
+        if (letoh16(entry->filename_size) > folder_size &&
+            !memcmp(entry->data, dirp->folder_path, folder_size) &&
             *folder_end == '/' &&
-            (entry_len = path_component_length(folder_end + 1)) < 256) {
+            (entry_len = path_component_length(folder_end + 1, entry->data + entry->filename_size)) < 256) {
 
             /* Fake an unique inode number; might be used? */
-            result.d_ino = cdir_entries - dirp->remaining_entries + 2;
+            result.d_ino = cdir_entries - dirp->remaining_entries + 1;
 
             result.d_off = 0;
             result.d_reclen = 0;
 
-            if (folder_end[entry_len] == '/')
+            if (folder_end[1 + entry_len] == '/')
                 result.d_type = DT_DIR;
             else
                 result.d_type = DT_REG;
 
             memcpy(result.d_name, folder_end + 1, entry_len);
             result.d_name[entry_len] = '\0';
+
+            LOGI("lo_apk_readdir(%p) = %s:%s", dirp, result.d_type == DT_DIR ? "DIR" : "REG", result.d_name);
             return &result;
         }
-        dirp->remaining_entries--;
     }
 
+    LOGI("lo_apk_readdir(%p) = NULL", dirp);
+
     return NULL;
 }
 
@@ -996,9 +1011,73 @@ lo_apk_closedir(lo_apk_dir *dirp)
     free(dirp->folder_path);
     free(dirp);
 
+    LOGI("lo_apk_closedir(%p)", dirp);
+
     return 0;
 }
 
+static int
+new_stat(const char *path,
+         struct stat *statp,
+         struct cdir_entry *entry,
+         int mode,
+         int fake_ino)
+{
+    memset(statp, 0, sizeof(*statp));
+    statp->st_mode = mode | S_IRUSR | S_IRGRP | S_IROTH;
+    statp->st_nlink = 1;
+    if (entry != NULL)
+        statp->st_size = entry->uncompressed_size;
+    else
+        statp->st_size = 0;
+    statp->st_blksize = 512;
+    if (statp->st_size == 0)
+        statp->st_blocks = 0;
+    else
+        statp->st_blocks = (statp->st_size - 1) / statp->st_blksize + 1;
+    /* Leave timestamps at zero for now? */
+    statp->st_ino = fake_ino;
+
+    LOGI("lo_apk_lstat(%s) = { st_mode=%o, st_size=%lld, st_ino=%lld }", path, statp->st_mode, statp->st_size, statp->st_ino);
+
+    return 0;
+}
+
+__attribute__ ((visibility("default")))
+int
+lo_apk_lstat(const char *path,
+             struct stat *statp)
+{
+    const char *pn = path;
+    int count = cdir_entries;
+    struct cdir_entry *entry = cdir_start;
+    size_t name_size;
+
+    if (*pn == '/') {
+        pn++;
+        if (!pn[0])
+            return new_stat(path, statp, NULL, S_IFDIR, 1);
+    }
+
+    name_size = strlen(pn);
+    while (count--) {
+        if (letoh16(entry->filename_size) >= name_size &&
+            !memcmp(entry->data, pn, name_size) &&
+            (letoh16(entry->filename_size) == name_size || entry->data[name_size] == '/'))
+            break;
+        entry = (struct cdir_entry *)((char *)entry + cdir_entry_size(entry));
+    }
+    if (count >= 0) {
+        if (letoh16(entry->filename_size) == name_size)
+            return new_stat(path, statp, entry, S_IFREG, cdir_entries - count + 1);
+        else
+            return new_stat(path, statp, entry, S_IFDIR, cdir_entries - count + 1);
+    }
+
+    errno = ENOENT;
+    return -1;
+}
+
 __attribute__ ((visibility("default")))
 int
 lo_dlcall_argc_argv(void *function,
diff --git a/solenv/inc/unxandr/lo-bootstrap.h b/solenv/inc/unxandr/lo-bootstrap.h
index 71a8d13..48b1a5c 100644
--- a/solenv/inc/unxandr/lo-bootstrap.h
+++ b/solenv/inc/unxandr/lo-bootstrap.h
@@ -58,6 +58,8 @@ struct dirent *lo_apk_readdir(lo_apk_dir *dirp);
 
 int lo_apk_closedir(lo_apk_dir *dirp);
 
+int lo_apk_lstat(const char *path, struct stat *statp);
+
 int lo_dlcall_argc_argv(void *function,
                         int argc,
                         const char **argv);
commit 05d0bdbb940eb43d8fd70aa782daa9172c7f32ce
Author: Tor Lillqvist <tlillqvist at suse.com>
Date:   Tue Jan 3 15:27:41 2012 +0200

    Minor edits

diff --git a/README.Android b/README.Android
index 076dff2..e58c811 100644
--- a/README.Android
+++ b/README.Android
@@ -7,15 +7,16 @@ files, so that they run in a sandboxed environment like that of
 whatever eventual end-user Android apps there will be that use LO
 code.
 
-Sure, we could quite easily build unit tests as plain Android
-executables, push them to the device or emulator with adb and run them
-from adb shell, but that would not be a good test as the environment
-would be completely different. They would run as root, and not
-sandboxed. We have no intent to require LibreOffice code to be used
-only on "rooted" devices etc.
+Sure, we could quite easily build unit tests as plain Linux
+executables (built against the Android libraries, of course, not
+GNU/Linux ones), push them to the device or emulator with adb and run
+them from adb shell, but that would not be a good test as the
+environment such processs run in is completely different from that in
+which real end-user apps with GUI etc run. We have no intent to
+require LibreOffice code to be used only on "rooted" devices etc.
 
 All Android apps are basically Java programs. They run "in" a Dalvik
-virtual machine. Yes, you can also have apps where your code is only
+virtual machine. Yes, you can also have apps where *your* code is only
 native code, written in a compiled language like C or C++. But also
 also such apps are actually started by system-provided Java
 bootstrapping code (NativeActivity) running in a Dalvik VM.
@@ -30,13 +31,13 @@ out how to manually construct an .apk that is properly signed so that
 it will run in the emulator. (I don't have any Android device...) I
 only know how to let the SDK Ant tooling do it...
 
-A LO Android app would work would something like this:
+At this stage, the plan is that a LO Android app will work would
+something like this:
 
-We have a top Java bootstrapping class
-org.libreoffice.android.Bootstrap that loads a small helper native
-library liblo-bootstrap.so that implements JNI wrappers for dlopen(),
-dlsym(), and ELF header scanning coresponding to looking for DT_NEEDED
-entries with readelf.
+We have a Java class org.libreoffice.android.Bootstrap that that loads
+a small helper native library liblo-bootstrap.so that implements JNI
+wrappers for dlopen(), dlsym(), and ELF header scanning coresponding
+to looking for DT_NEEDED entries with readelf.
 
 The Java code then loads the actual native library that corresponds to
 the LibreOffice-related "program" we want to run. For unit tests, a


More information about the Libreoffice-commits mailing list