diff options
author | Jean-Baptiste Queru <jbq@google.com> | 2011-12-13 07:58:58 -0800 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2011-12-13 07:58:58 -0800 |
commit | 01fc7b248553eea6dfee8c56819c4855a69504c1 (patch) | |
tree | c5924ff0c50dfaf18d6bb0b71d32a5e9de97f6e6 | |
parent | 7330ec21c1ce30fb67681236e8cd1a84f00ca0b7 (diff) | |
parent | 5792ce79cc79cd0eef9fadd6351521b128b4e85c (diff) | |
download | system_core-01fc7b248553eea6dfee8c56819c4855a69504c1.zip system_core-01fc7b248553eea6dfee8c56819c4855a69504c1.tar.gz system_core-01fc7b248553eea6dfee8c56819c4855a69504c1.tar.bz2 |
Merge "run-as: use mmap to read package list file"
-rw-r--r-- | run-as/package.c | 91 |
1 files changed, 59 insertions, 32 deletions
diff --git a/run-as/package.c b/run-as/package.c index ca08436..8f11646 100644 --- a/run-as/package.c +++ b/run-as/package.c @@ -18,6 +18,7 @@ #include <fcntl.h> #include <unistd.h> #include <sys/stat.h> +#include <sys/mman.h> #include <private/android_filesystem_config.h> #include "package.h" @@ -43,9 +44,6 @@ /* The file containing the list of installed packages on the system */ #define PACKAGES_LIST_FILE "/data/system/packages.list" -/* This should be large enough to hold the content of the package database file */ -#define PACKAGES_LIST_BUFFER_SIZE 65536 - /* Copy 'srclen' string bytes from 'src' into buffer 'dst' of size 'dstlen' * This function always zero-terminate the destination buffer unless * 'dstlen' is 0, even in case of overflow. @@ -67,40 +65,63 @@ string_copy(char* dst, size_t dstlen, const char* src, size_t srclen) *dst = '\0'; /* zero-terminate result */ } -/* Read up to 'buffsize' bytes into 'buff' from the file - * named 'filename'. Return byte length on success, or -1 - * on error. +/* Open 'filename' and map it into our address-space. + * Returns buffer address, or NULL on error + * On exit, *filesize will be set to the file's size, or 0 on error */ -static int -read_file(const char* filename, char* buff, size_t buffsize) +static void* +map_file(const char* filename, size_t* filesize) { - int fd, len, old_errno; + int fd, ret, old_errno; + struct stat st; + size_t length = 0; + void* address = NULL; - /* check the input buffer size */ - if (buffsize >= INT_MAX) { - errno = EINVAL; - return -1; - } + *filesize = 0; /* open the file for reading */ - do { - fd = open(filename, O_RDONLY); - } while (fd < 0 && errno == EINTR); - + fd = TEMP_FAILURE_RETRY(open(filename, O_RDONLY)); if (fd < 0) - return -1; + return NULL; - /* read the content */ - do { - len = read(fd, buff, buffsize); - } while (len < 0 && errno == EINTR); + /* get its size */ + ret = TEMP_FAILURE_RETRY(fstat(fd, &st)); + if (ret < 0) + goto EXIT; + + /* Ensure that the size is not ridiculously large */ + length = (size_t)st.st_size; + if ((off_t)length != st.st_size) { + errno = ENOMEM; + goto EXIT; + } + + /* Memory-map the file now */ + address = TEMP_FAILURE_RETRY(mmap(NULL, length, PROT_READ, MAP_PRIVATE, fd, 0)); + if (address == MAP_FAILED) { + address = NULL; + goto EXIT; + } + /* We're good, return size */ + *filesize = length; + +EXIT: /* close the file, preserve old errno for better diagnostics */ old_errno = errno; close(fd); errno = old_errno; - return len; + return address; +} + +/* unmap the file, but preserve errno */ +static void +unmap_file(void* address, size_t size) +{ + int old_errno = errno; + TEMP_FAILURE_RETRY(munmap(address, size)); + errno = old_errno; } /* Check that a given directory: @@ -371,18 +392,18 @@ BAD: int get_package_info(const char* pkgName, PackageInfo *info) { - static char buffer[PACKAGES_LIST_BUFFER_SIZE]; - int buffer_len; + char* buffer; + size_t buffer_len; const char* p; const char* buffer_end; - int result; + int result = -1; info->uid = 0; info->isDebuggable = 0; info->dataDir[0] = '\0'; - buffer_len = read_file(PACKAGES_LIST_FILE, buffer, sizeof buffer); - if (buffer_len < 0) + buffer = map_file(PACKAGES_LIST_FILE, &buffer_len); + if (buffer == NULL) return -1; p = buffer; @@ -455,7 +476,8 @@ get_package_info(const char* pkgName, PackageInfo *info) string_copy(info->dataDir, sizeof info->dataDir, p, q - p); /* Ignore the rest */ - return 0; + result = 0; + goto EXIT; NEXT_LINE: p = next; @@ -463,9 +485,14 @@ get_package_info(const char* pkgName, PackageInfo *info) /* the package is unknown */ errno = ENOENT; - return -1; + result = -1; + goto EXIT; BAD_FORMAT: errno = EINVAL; - return -1; + result = -1; + +EXIT: + unmap_file(buffer, buffer_len); + return result; } |