summaryrefslogtreecommitdiff
path: root/sal/android
diff options
context:
space:
mode:
authorTor Lillqvist <tlillqvist@suse.com>2012-01-03 16:33:10 +0200
committerTor Lillqvist <tlillqvist@suse.com>2012-01-04 00:15:26 +0200
commit7cc28bae3a8aded334f40bf3a5593b5f6067fdd8 (patch)
tree2b1acacfc985f0858fc1472326b9e37436a9f3ed /sal/android
parent05d0bdbb940eb43d8fd70aa782daa9172c7f32ce (diff)
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.
Diffstat (limited to 'sal/android')
-rw-r--r--sal/android/lo-bootstrap.c121
1 files changed, 100 insertions, 21 deletions
diff --git a/sal/android/lo-bootstrap.c b/sal/android/lo-bootstrap.c
index 07c168701f69..7fc171ba90ae 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,