[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