diff options
author | Mathias Agopian <mathias@google.com> | 2013-05-06 20:20:50 -0700 |
---|---|---|
committer | Mathias Agopian <mathias@google.com> | 2013-05-07 18:28:11 -0700 |
commit | 002e1e58dfe19dd3e49a59c6827cbf51573941a2 (patch) | |
tree | 6dc444d7f05aa0512e3c97344d86ee0264daf869 /libs | |
parent | b4f1a027cbadd4cd07341f60f859ae34643b68ae (diff) | |
download | frameworks_native-002e1e58dfe19dd3e49a59c6827cbf51573941a2.zip frameworks_native-002e1e58dfe19dd3e49a59c6827cbf51573941a2.tar.gz frameworks_native-002e1e58dfe19dd3e49a59c6827cbf51573941a2.tar.bz2 |
libutils clean-up
Change-Id: I6ff4cfc736751de2912c697f954e45e275f2d386
Diffstat (limited to 'libs')
-rw-r--r-- | libs/binder/Android.mk | 5 | ||||
-rw-r--r-- | libs/binder/BufferedTextOutput.cpp (renamed from libs/utils/BufferedTextOutput.cpp) | 6 | ||||
-rw-r--r-- | libs/binder/Debug.cpp (renamed from libs/utils/Debug.cpp) | 16 | ||||
-rw-r--r-- | libs/binder/IPCThreadState.cpp | 3 | ||||
-rw-r--r-- | libs/binder/Parcel.cpp | 5 | ||||
-rw-r--r-- | libs/binder/Static.cpp | 54 | ||||
-rw-r--r-- | libs/binder/TextOutput.cpp (renamed from libs/utils/TextOutput.cpp) | 4 | ||||
-rw-r--r-- | libs/utils/Android.mk | 21 | ||||
-rw-r--r-- | libs/utils/RefBase.cpp | 16 | ||||
-rw-r--r-- | libs/utils/Static.cpp | 56 | ||||
-rw-r--r-- | libs/utils/String16.cpp | 9 | ||||
-rw-r--r-- | libs/utils/String8.cpp | 11 | ||||
-rw-r--r-- | libs/utils/StringArray.cpp | 113 | ||||
-rw-r--r-- | libs/utils/SystemClock.cpp | 54 | ||||
-rw-r--r-- | libs/utils/Timers.cpp | 62 | ||||
-rw-r--r-- | libs/utils/WorkQueue.cpp | 171 | ||||
-rw-r--r-- | libs/utils/ZipFileCRO.cpp | 54 | ||||
-rw-r--r-- | libs/utils/ZipFileRO.cpp | 931 | ||||
-rw-r--r-- | libs/utils/ZipUtils.cpp | 345 | ||||
-rw-r--r-- | libs/utils/misc.cpp | 51 | ||||
-rw-r--r-- | libs/utils/tests/Android.mk | 3 | ||||
-rw-r--r-- | libs/utils/tests/ZipFileRO_test.cpp | 64 |
22 files changed, 79 insertions, 1975 deletions
diff --git a/libs/binder/Android.mk b/libs/binder/Android.mk index 994d3db..4c8820e 100644 --- a/libs/binder/Android.mk +++ b/libs/binder/Android.mk @@ -17,6 +17,8 @@ sources := \ AppOpsManager.cpp \ Binder.cpp \ BpBinder.cpp \ + BufferedTextOutput.cpp \ + Debug.cpp \ IAppOpsCallback.cpp \ IAppOpsService.cpp \ IInterface.cpp \ @@ -30,7 +32,8 @@ sources := \ Parcel.cpp \ PermissionCache.cpp \ ProcessState.cpp \ - Static.cpp + Static.cpp \ + TextOutput.cpp \ LOCAL_PATH:= $(call my-dir) diff --git a/libs/utils/BufferedTextOutput.cpp b/libs/binder/BufferedTextOutput.cpp index 989662e..2d493c1 100644 --- a/libs/utils/BufferedTextOutput.cpp +++ b/libs/binder/BufferedTextOutput.cpp @@ -14,16 +14,16 @@ * limitations under the License. */ -#include <utils/BufferedTextOutput.h> +#include <binder/BufferedTextOutput.h> +#include <binder/Debug.h> #include <utils/Atomic.h> -#include <utils/Debug.h> #include <utils/Log.h> #include <utils/RefBase.h> #include <utils/Vector.h> #include <cutils/threads.h> -#include <private/utils/Static.h> +#include <private/binder/Static.h> #include <stdio.h> #include <stdlib.h> diff --git a/libs/utils/Debug.cpp b/libs/binder/Debug.cpp index e8ac983..a8b6e83 100644 --- a/libs/utils/Debug.cpp +++ b/libs/binder/Debug.cpp @@ -14,7 +14,7 @@ * limitations under the License. */ -#include <utils/Debug.h> +#include <binder/Debug.h> #include <utils/misc.h> @@ -70,20 +70,6 @@ static char* appendhexnum(uint32_t val, char* out) return out; } -static inline char makeupperhexdigit(uint32_t val) -{ - return "0123456789ABCDEF"[val&0xF]; -} - -static char* appendupperhexnum(uint32_t val, char* out) -{ - for( int32_t i=28; i>=0; i-=4 ) { - *out++ = makeupperhexdigit( val>>i ); - } - *out = 0; - return out; -} - static char* appendcharornum(char c, char* out, bool skipzero = true) { if (skipzero && c == 0) return out; diff --git a/libs/binder/IPCThreadState.cpp b/libs/binder/IPCThreadState.cpp index 6e83faa..2780d9a 100644 --- a/libs/binder/IPCThreadState.cpp +++ b/libs/binder/IPCThreadState.cpp @@ -20,10 +20,11 @@ #include <binder/Binder.h> #include <binder/BpBinder.h> +#include <binder/TextOutput.h> + #include <cutils/sched_policy.h> #include <utils/Debug.h> #include <utils/Log.h> -#include <utils/TextOutput.h> #include <utils/threads.h> #include <private/binder/binder_module.h> diff --git a/libs/binder/Parcel.cpp b/libs/binder/Parcel.cpp index 8f7f7e7..aa19d17 100644 --- a/libs/binder/Parcel.cpp +++ b/libs/binder/Parcel.cpp @@ -22,12 +22,13 @@ #include <binder/IPCThreadState.h> #include <binder/Binder.h> #include <binder/BpBinder.h> -#include <utils/Debug.h> #include <binder/ProcessState.h> +#include <binder/TextOutput.h> + +#include <utils/Debug.h> #include <utils/Log.h> #include <utils/String8.h> #include <utils/String16.h> -#include <utils/TextOutput.h> #include <utils/misc.h> #include <utils/Flattenable.h> #include <cutils/ashmem.h> diff --git a/libs/binder/Static.cpp b/libs/binder/Static.cpp index 12b0308..2062692 100644 --- a/libs/binder/Static.cpp +++ b/libs/binder/Static.cpp @@ -19,30 +19,76 @@ #include <private/binder/Static.h> +#include <binder/BufferedTextOutput.h> #include <binder/IPCThreadState.h> #include <utils/Log.h> namespace android { +// ------------ Text output streams + +Vector<int32_t> gTextBuffers; + +class LogTextOutput : public BufferedTextOutput +{ +public: + LogTextOutput() : BufferedTextOutput(MULTITHREADED) { } + virtual ~LogTextOutput() { }; + +protected: + virtual status_t writeLines(const struct iovec& vec, size_t N) + { + //android_writevLog(&vec, N); <-- this is now a no-op + if (N != 1) ALOGI("WARNING: writeLines N=%zu\n", N); + ALOGI("%.*s", (int)vec.iov_len, (const char*) vec.iov_base); + return NO_ERROR; + } +}; + +class FdTextOutput : public BufferedTextOutput +{ +public: + FdTextOutput(int fd) : BufferedTextOutput(MULTITHREADED), mFD(fd) { } + virtual ~FdTextOutput() { }; + +protected: + virtual status_t writeLines(const struct iovec& vec, size_t N) + { + writev(mFD, &vec, N); + return NO_ERROR; + } + +private: + int mFD; +}; + +static LogTextOutput gLogTextOutput; +static FdTextOutput gStdoutTextOutput(STDOUT_FILENO); +static FdTextOutput gStderrTextOutput(STDERR_FILENO); + +TextOutput& alog(gLogTextOutput); +TextOutput& aout(gStdoutTextOutput); +TextOutput& aerr(gStderrTextOutput); + // ------------ ProcessState.cpp Mutex gProcessMutex; sp<ProcessState> gProcess; -class LibUtilsIPCtStatics +class LibBinderIPCtStatics { public: - LibUtilsIPCtStatics() + LibBinderIPCtStatics() { } - ~LibUtilsIPCtStatics() + ~LibBinderIPCtStatics() { IPCThreadState::shutdown(); } }; -static LibUtilsIPCtStatics gIPCStatics; +static LibBinderIPCtStatics gIPCStatics; // ------------ ServiceManager.cpp diff --git a/libs/utils/TextOutput.cpp b/libs/binder/TextOutput.cpp index e04823d..9637334 100644 --- a/libs/utils/TextOutput.cpp +++ b/libs/binder/TextOutput.cpp @@ -14,9 +14,9 @@ * limitations under the License. */ -#include <utils/TextOutput.h> +#include <binder/TextOutput.h> -#include <utils/Debug.h> +#include <binder/Debug.h> #include <stdio.h> #include <stdlib.h> diff --git a/libs/utils/Android.mk b/libs/utils/Android.mk index ce25605..42e1c7e 100644 --- a/libs/utils/Android.mk +++ b/libs/utils/Android.mk @@ -20,9 +20,7 @@ LOCAL_PATH:= $(call my-dir) commonSources:= \ BasicHashtable.cpp \ BlobCache.cpp \ - BufferedTextOutput.cpp \ CallStack.cpp \ - Debug.cpp \ FileMap.cpp \ Flattenable.cpp \ JenkinsHash.cpp \ @@ -36,18 +34,12 @@ commonSources:= \ StopWatch.cpp \ String8.cpp \ String16.cpp \ - StringArray.cpp \ SystemClock.cpp \ - TextOutput.cpp \ Threads.cpp \ Timers.cpp \ Tokenizer.cpp \ Unicode.cpp \ VectorImpl.cpp \ - WorkQueue.cpp \ - ZipFileCRO.cpp \ - ZipFileRO.cpp \ - ZipUtils.cpp \ misc.cpp host_commonCflags := -DLIBUTILS_NATIVE=1 $(TOOL_CFLAGS) @@ -74,9 +66,6 @@ ifeq ($(HOST_OS), linux) LOCAL_SRC_FILES += Looper.cpp endif LOCAL_MODULE:= libutils -LOCAL_STATIC_LIBRARIES := libz -LOCAL_C_INCLUDES := \ - external/zlib LOCAL_CFLAGS += $(host_commonCflags) LOCAL_LDLIBS += $(host_commonLdlibs) include $(BUILD_HOST_STATIC_LIBRARY) @@ -90,9 +79,6 @@ ifeq ($(HOST_OS), linux) LOCAL_SRC_FILES += Looper.cpp endif LOCAL_MODULE:= lib64utils -LOCAL_STATIC_LIBRARIES := libz -LOCAL_C_INCLUDES := \ - external/zlib LOCAL_CFLAGS += $(host_commonCflags) -m64 LOCAL_LDLIBS += $(host_commonLdlibs) include $(BUILD_HOST_STATIC_LIBRARY) @@ -124,8 +110,7 @@ LOCAL_C_INCLUDES += \ LOCAL_LDLIBS += -lpthread LOCAL_STATIC_LIBRARIES := \ - libcutils \ - libz + libcutils LOCAL_SHARED_LIBRARIES := \ libcorkscrew \ @@ -144,8 +129,8 @@ LOCAL_SHARED_LIBRARIES := \ liblog \ libcutils \ libdl \ - libcorkscrew \ - libz + libcorkscrew + include $(BUILD_SHARED_LIBRARY) # Include subdirectory makefiles diff --git a/libs/utils/RefBase.cpp b/libs/utils/RefBase.cpp index e538f68..f398a82 100644 --- a/libs/utils/RefBase.cpp +++ b/libs/utils/RefBase.cpp @@ -23,7 +23,6 @@ #include <utils/CallStack.h> #include <utils/Log.h> #include <utils/threads.h> -#include <utils/TextOutput.h> #include <stdlib.h> #include <stdio.h> @@ -648,19 +647,4 @@ void RefBase::renameRefId(RefBase* ref, ref->mRefs->renameWeakRefId(old_id, new_id); } -// --------------------------------------------------------------------------- - -TextOutput& printStrongPointer(TextOutput& to, const void* val) -{ - to << "sp<>(" << val << ")"; - return to; -} - -TextOutput& printWeakPointer(TextOutput& to, const void* val) -{ - to << "wp<>(" << val << ")"; - return to; -} - - }; // namespace android diff --git a/libs/utils/Static.cpp b/libs/utils/Static.cpp index 624e917..3ed07a1 100644 --- a/libs/utils/Static.cpp +++ b/libs/utils/Static.cpp @@ -17,12 +17,15 @@ // All static variables go here, to control initialization and // destruction order in the library. -#include <private/utils/Static.h> +namespace android { -#include <utils/BufferedTextOutput.h> -#include <utils/Log.h> +// For String8.cpp +extern void initialize_string8(); +extern void terminate_string8(); -namespace android { +// For String16.cpp +extern void initialize_string16(); +extern void terminate_string16(); class LibUtilsFirstStatics { @@ -43,49 +46,4 @@ public: static LibUtilsFirstStatics gFirstStatics; int gDarwinCantLoadAllObjects = 1; -// ------------ Text output streams - -Vector<int32_t> gTextBuffers; - -class LogTextOutput : public BufferedTextOutput -{ -public: - LogTextOutput() : BufferedTextOutput(MULTITHREADED) { } - virtual ~LogTextOutput() { }; - -protected: - virtual status_t writeLines(const struct iovec& vec, size_t N) - { - //android_writevLog(&vec, N); <-- this is now a no-op - if (N != 1) ALOGI("WARNING: writeLines N=%zu\n", N); - ALOGI("%.*s", (int)vec.iov_len, (const char*) vec.iov_base); - return NO_ERROR; - } -}; - -class FdTextOutput : public BufferedTextOutput -{ -public: - FdTextOutput(int fd) : BufferedTextOutput(MULTITHREADED), mFD(fd) { } - virtual ~FdTextOutput() { }; - -protected: - virtual status_t writeLines(const struct iovec& vec, size_t N) - { - writev(mFD, &vec, N); - return NO_ERROR; - } - -private: - int mFD; -}; - -static LogTextOutput gLogTextOutput; -static FdTextOutput gStdoutTextOutput(STDOUT_FILENO); -static FdTextOutput gStderrTextOutput(STDERR_FILENO); - -TextOutput& alog(gLogTextOutput); -TextOutput& aout(gStdoutTextOutput); -TextOutput& aerr(gStderrTextOutput); - } // namespace android diff --git a/libs/utils/String16.cpp b/libs/utils/String16.cpp index 94e072f..c856ceb 100644 --- a/libs/utils/String16.cpp +++ b/libs/utils/String16.cpp @@ -20,11 +20,8 @@ #include <utils/Log.h> #include <utils/Unicode.h> #include <utils/String8.h> -#include <utils/TextOutput.h> #include <utils/threads.h> -#include <private/utils/Static.h> - #include <memory.h> #include <stdio.h> #include <ctype.h> @@ -409,10 +406,4 @@ status_t String16::remove(size_t len, size_t begin) return NO_MEMORY; } -TextOutput& operator<<(TextOutput& to, const String16& val) -{ - to << String8(val).string(); - return to; -} - }; // namespace android diff --git a/libs/utils/String8.cpp b/libs/utils/String8.cpp index 75daee9..413928a 100644 --- a/libs/utils/String8.cpp +++ b/libs/utils/String8.cpp @@ -20,11 +20,8 @@ #include <utils/Unicode.h> #include <utils/SharedBuffer.h> #include <utils/String16.h> -#include <utils/TextOutput.h> #include <utils/threads.h> -#include <private/utils/Static.h> - #include <ctype.h> /* @@ -46,6 +43,8 @@ static char* gEmptyString = NULL; extern int gDarwinCantLoadAllObjects; int gDarwinIsReallyAnnoying; +void initialize_string8(); + static inline char* getEmptyString() { if (!gEmptyStringBuf) initialize_string8(); @@ -454,12 +453,6 @@ void String8::getUtf32(char32_t* dst) const utf8_to_utf32(mString, length(), dst); } -TextOutput& operator<<(TextOutput& to, const String8& val) -{ - to << val.string(); - return to; -} - // --------------------------------------------------------------------------- // Path functions diff --git a/libs/utils/StringArray.cpp b/libs/utils/StringArray.cpp deleted file mode 100644 index aa42d68..0000000 --- a/libs/utils/StringArray.cpp +++ /dev/null @@ -1,113 +0,0 @@ -/* - * Copyright (C) 2009 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -// -// Sortable array of strings. STL-ish, but STL-free. -// - -#include <stdlib.h> -#include <string.h> - -#include <utils/StringArray.h> - -namespace android { - -// -// An expanding array of strings. Add, get, sort, delete. -// -StringArray::StringArray() - : mMax(0), mCurrent(0), mArray(NULL) -{ -} - -StringArray:: ~StringArray() { - for (int i = 0; i < mCurrent; i++) - delete[] mArray[i]; - delete[] mArray; -} - -// -// Add a string. A copy of the string is made. -// -bool StringArray::push_back(const char* str) { - if (mCurrent >= mMax) { - char** tmp; - - if (mMax == 0) - mMax = 16; // initial storage - else - mMax *= 2; - - tmp = new char*[mMax]; - if (tmp == NULL) - return false; - - memcpy(tmp, mArray, mCurrent * sizeof(char*)); - delete[] mArray; - mArray = tmp; - } - - int len = strlen(str); - mArray[mCurrent] = new char[len+1]; - memcpy(mArray[mCurrent], str, len+1); - mCurrent++; - - return true; -} - -// -// Delete an entry. -// -void StringArray::erase(int idx) { - if (idx < 0 || idx >= mCurrent) - return; - delete[] mArray[idx]; - if (idx < mCurrent-1) { - memmove(&mArray[idx], &mArray[idx+1], - (mCurrent-1 - idx) * sizeof(char*)); - } - mCurrent--; -} - -// -// Sort the array. -// -void StringArray::sort(int (*compare)(const void*, const void*)) { - qsort(mArray, mCurrent, sizeof(char*), compare); -} - -// -// Pass this to the sort routine to do an ascending alphabetical sort. -// -int StringArray::cmpAscendingAlpha(const void* pstr1, const void* pstr2) { - return strcmp(*(const char**)pstr1, *(const char**)pstr2); -} - -// -// Set entry N to specified string. -// [should use operator[] here] -// -void StringArray::setEntry(int idx, const char* str) { - if (idx < 0 || idx >= mCurrent) - return; - delete[] mArray[idx]; - int len = strlen(str); - mArray[idx] = new char[len+1]; - memcpy(mArray[idx], str, len+1); -} - - -}; // namespace android diff --git a/libs/utils/SystemClock.cpp b/libs/utils/SystemClock.cpp index ec2d82e..4b74889 100644 --- a/libs/utils/SystemClock.cpp +++ b/libs/utils/SystemClock.cpp @@ -36,63 +36,11 @@ #include <utils/Timers.h> #define LOG_TAG "SystemClock" -#include "utils/Log.h" +#include <utils/Log.h> namespace android { /* - * Set the current time. This only works when running as root. - */ -int setCurrentTimeMillis(int64_t millis) -{ -#if WIN32 - // not implemented - return -1; -#else - struct timeval tv; -#ifdef HAVE_ANDROID_OS - struct timespec ts; - int fd; - int res; -#endif - int ret = 0; - - if (millis <= 0 || millis / 1000LL >= INT_MAX) { - return -1; - } - - tv.tv_sec = (time_t) (millis / 1000LL); - tv.tv_usec = (suseconds_t) ((millis % 1000LL) * 1000LL); - - ALOGD("Setting time of day to sec=%d\n", (int) tv.tv_sec); - -#ifdef HAVE_ANDROID_OS - fd = open("/dev/alarm", O_RDWR); - if(fd < 0) { - ALOGW("Unable to open alarm driver: %s\n", strerror(errno)); - return -1; - } - ts.tv_sec = tv.tv_sec; - ts.tv_nsec = tv.tv_usec * 1000; - res = ioctl(fd, ANDROID_ALARM_SET_RTC, &ts); - if(res < 0) { - ALOGW("Unable to set rtc to %ld: %s\n", tv.tv_sec, strerror(errno)); - ret = -1; - } - close(fd); -#else - if (settimeofday(&tv, NULL) != 0) { - ALOGW("Unable to set clock to %d.%d: %s\n", - (int) tv.tv_sec, (int) tv.tv_usec, strerror(errno)); - ret = -1; - } -#endif - - return ret; -#endif // WIN32 -} - -/* * native public static long uptimeMillis(); */ int64_t uptimeMillis() diff --git a/libs/utils/Timers.cpp b/libs/utils/Timers.cpp index d4f8516..5293cd2 100644 --- a/libs/utils/Timers.cpp +++ b/libs/utils/Timers.cpp @@ -70,65 +70,3 @@ int toMillisecondTimeoutDelay(nsecs_t referenceTime, nsecs_t timeoutTime) } return timeoutDelayMillis; } - - -/* - * =========================================================================== - * DurationTimer - * =========================================================================== - */ - -using namespace android; - -// Start the timer. -void DurationTimer::start(void) -{ - gettimeofday(&mStartWhen, NULL); -} - -// Stop the timer. -void DurationTimer::stop(void) -{ - gettimeofday(&mStopWhen, NULL); -} - -// Get the duration in microseconds. -long long DurationTimer::durationUsecs(void) const -{ - return (long) subtractTimevals(&mStopWhen, &mStartWhen); -} - -// Subtract two timevals. Returns the difference (ptv1-ptv2) in -// microseconds. -/*static*/ long long DurationTimer::subtractTimevals(const struct timeval* ptv1, - const struct timeval* ptv2) -{ - long long stop = ((long long) ptv1->tv_sec) * 1000000LL + - ((long long) ptv1->tv_usec); - long long start = ((long long) ptv2->tv_sec) * 1000000LL + - ((long long) ptv2->tv_usec); - return stop - start; -} - -// Add the specified amount of time to the timeval. -/*static*/ void DurationTimer::addToTimeval(struct timeval* ptv, long usec) -{ - if (usec < 0) { - ALOG(LOG_WARN, "", "Negative values not supported in addToTimeval\n"); - return; - } - - // normalize tv_usec if necessary - if (ptv->tv_usec >= 1000000) { - ptv->tv_sec += ptv->tv_usec / 1000000; - ptv->tv_usec %= 1000000; - } - - ptv->tv_usec += usec % 1000000; - if (ptv->tv_usec >= 1000000) { - ptv->tv_usec -= 1000000; - ptv->tv_sec++; - } - ptv->tv_sec += usec / 1000000; -} - diff --git a/libs/utils/WorkQueue.cpp b/libs/utils/WorkQueue.cpp deleted file mode 100644 index 3bb99a1..0000000 --- a/libs/utils/WorkQueue.cpp +++ /dev/null @@ -1,171 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -// #define LOG_NDEBUG 0 -#define LOG_TAG "WorkQueue" - -#include <utils/Log.h> -#include <utils/WorkQueue.h> - -namespace android { - -// --- WorkQueue --- - -WorkQueue::WorkQueue(size_t maxThreads, bool canCallJava) : - mMaxThreads(maxThreads), mCanCallJava(canCallJava), - mCanceled(false), mFinished(false), mIdleThreads(0) { -} - -WorkQueue::~WorkQueue() { - if (!cancel()) { - finish(); - } -} - -status_t WorkQueue::schedule(WorkUnit* workUnit, size_t backlog) { - AutoMutex _l(mLock); - - if (mFinished || mCanceled) { - return INVALID_OPERATION; - } - - if (mWorkThreads.size() < mMaxThreads - && mIdleThreads < mWorkUnits.size() + 1) { - sp<WorkThread> workThread = new WorkThread(this, mCanCallJava); - status_t status = workThread->run("WorkQueue::WorkThread"); - if (status) { - return status; - } - mWorkThreads.add(workThread); - mIdleThreads += 1; - } else if (backlog) { - while (mWorkUnits.size() >= mMaxThreads * backlog) { - mWorkDequeuedCondition.wait(mLock); - if (mFinished || mCanceled) { - return INVALID_OPERATION; - } - } - } - - mWorkUnits.add(workUnit); - mWorkChangedCondition.broadcast(); - return OK; -} - -status_t WorkQueue::cancel() { - AutoMutex _l(mLock); - - return cancelLocked(); -} - -status_t WorkQueue::cancelLocked() { - if (mFinished) { - return INVALID_OPERATION; - } - - if (!mCanceled) { - mCanceled = true; - - size_t count = mWorkUnits.size(); - for (size_t i = 0; i < count; i++) { - delete mWorkUnits.itemAt(i); - } - mWorkUnits.clear(); - mWorkChangedCondition.broadcast(); - mWorkDequeuedCondition.broadcast(); - } - return OK; -} - -status_t WorkQueue::finish() { - { // acquire lock - AutoMutex _l(mLock); - - if (mFinished) { - return INVALID_OPERATION; - } - - mFinished = true; - mWorkChangedCondition.broadcast(); - } // release lock - - // It is not possible for the list of work threads to change once the mFinished - // flag has been set, so we can access mWorkThreads outside of the lock here. - size_t count = mWorkThreads.size(); - for (size_t i = 0; i < count; i++) { - mWorkThreads.itemAt(i)->join(); - } - mWorkThreads.clear(); - return OK; -} - -bool WorkQueue::threadLoop() { - WorkUnit* workUnit; - { // acquire lock - AutoMutex _l(mLock); - - for (;;) { - if (mCanceled) { - return false; - } - - if (!mWorkUnits.isEmpty()) { - workUnit = mWorkUnits.itemAt(0); - mWorkUnits.removeAt(0); - mIdleThreads -= 1; - mWorkDequeuedCondition.broadcast(); - break; - } - - if (mFinished) { - return false; - } - - mWorkChangedCondition.wait(mLock); - } - } // release lock - - bool shouldContinue = workUnit->run(); - delete workUnit; - - { // acquire lock - AutoMutex _l(mLock); - - mIdleThreads += 1; - - if (!shouldContinue) { - cancelLocked(); - return false; - } - } // release lock - - return true; -} - -// --- WorkQueue::WorkThread --- - -WorkQueue::WorkThread::WorkThread(WorkQueue* workQueue, bool canCallJava) : - Thread(canCallJava), mWorkQueue(workQueue) { -} - -WorkQueue::WorkThread::~WorkThread() { -} - -bool WorkQueue::WorkThread::threadLoop() { - return mWorkQueue->threadLoop(); -} - -}; // namespace android diff --git a/libs/utils/ZipFileCRO.cpp b/libs/utils/ZipFileCRO.cpp deleted file mode 100644 index 55dfd9f..0000000 --- a/libs/utils/ZipFileCRO.cpp +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright (C) 2008 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include <utils/ZipFileCRO.h> -#include <utils/ZipFileRO.h> - -using namespace android; - -ZipFileCRO ZipFileXRO_open(const char* path) { - ZipFileRO* zip = new ZipFileRO(); - if (zip->open(path) == NO_ERROR) { - return (ZipFileCRO)zip; - } - return NULL; -} - -void ZipFileCRO_destroy(ZipFileCRO zipToken) { - ZipFileRO* zip = (ZipFileRO*)zipToken; - delete zip; -} - -ZipEntryCRO ZipFileCRO_findEntryByName(ZipFileCRO zipToken, - const char* fileName) { - ZipFileRO* zip = (ZipFileRO*)zipToken; - return (ZipEntryCRO)zip->findEntryByName(fileName); -} - -bool ZipFileCRO_getEntryInfo(ZipFileCRO zipToken, ZipEntryRO entryToken, - int* pMethod, size_t* pUncompLen, - size_t* pCompLen, off64_t* pOffset, long* pModWhen, long* pCrc32) { - ZipFileRO* zip = (ZipFileRO*)zipToken; - ZipEntryRO entry = (ZipEntryRO)entryToken; - return zip->getEntryInfo(entry, pMethod, pUncompLen, pCompLen, pOffset, - pModWhen, pCrc32); -} - -bool ZipFileCRO_uncompressEntry(ZipFileCRO zipToken, ZipEntryRO entryToken, int fd) { - ZipFileRO* zip = (ZipFileRO*)zipToken; - ZipEntryRO entry = (ZipEntryRO)entryToken; - return zip->uncompressEntry(entry, fd); -} diff --git a/libs/utils/ZipFileRO.cpp b/libs/utils/ZipFileRO.cpp deleted file mode 100644 index a1bfedb..0000000 --- a/libs/utils/ZipFileRO.cpp +++ /dev/null @@ -1,931 +0,0 @@ -/* - * Copyright (C) 2007 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -// -// Read-only access to Zip archives, with minimal heap allocation. -// -#define LOG_TAG "zipro" -//#define LOG_NDEBUG 0 -#include <utils/Log.h> -#include <utils/Compat.h> -#include <utils/ZipFileRO.h> -#include <utils/misc.h> -#include <utils/threads.h> - -#include <zlib.h> - -#include <string.h> -#include <fcntl.h> -#include <errno.h> -#include <assert.h> -#include <unistd.h> - -/* - * We must open binary files using open(path, ... | O_BINARY) under Windows. - * Otherwise strange read errors will happen. - */ -#ifndef O_BINARY -# define O_BINARY 0 -#endif - -using namespace android; - -/* - * Zip file constants. - */ -#define kEOCDSignature 0x06054b50 -#define kEOCDLen 22 -#define kEOCDNumEntries 8 // offset to #of entries in file -#define kEOCDSize 12 // size of the central directory -#define kEOCDFileOffset 16 // offset to central directory - -#define kMaxCommentLen 65535 // longest possible in ushort -#define kMaxEOCDSearch (kMaxCommentLen + kEOCDLen) - -#define kLFHSignature 0x04034b50 -#define kLFHLen 30 // excluding variable-len fields -#define kLFHNameLen 26 // offset to filename length -#define kLFHExtraLen 28 // offset to extra length - -#define kCDESignature 0x02014b50 -#define kCDELen 46 // excluding variable-len fields -#define kCDEMethod 10 // offset to compression method -#define kCDEModWhen 12 // offset to modification timestamp -#define kCDECRC 16 // offset to entry CRC -#define kCDECompLen 20 // offset to compressed length -#define kCDEUncompLen 24 // offset to uncompressed length -#define kCDENameLen 28 // offset to filename length -#define kCDEExtraLen 30 // offset to extra length -#define kCDECommentLen 32 // offset to comment length -#define kCDELocalOffset 42 // offset to local hdr - -/* - * The values we return for ZipEntryRO use 0 as an invalid value, so we - * want to adjust the hash table index by a fixed amount. Using a large - * value helps insure that people don't mix & match arguments, e.g. to - * findEntryByIndex(). - */ -#define kZipEntryAdj 10000 - -ZipFileRO::~ZipFileRO() { - free(mHashTable); - if (mDirectoryMap) - mDirectoryMap->release(); - if (mFd >= 0) - TEMP_FAILURE_RETRY(close(mFd)); - if (mFileName) - free(mFileName); -} - -/* - * Convert a ZipEntryRO to a hash table index, verifying that it's in a - * valid range. - */ -int ZipFileRO::entryToIndex(const ZipEntryRO entry) const -{ - long ent = ((intptr_t) entry) - kZipEntryAdj; - if (ent < 0 || ent >= mHashTableSize || mHashTable[ent].name == NULL) { - ALOGW("Invalid ZipEntryRO %p (%ld)\n", entry, ent); - return -1; - } - return ent; -} - - -/* - * Open the specified file read-only. We memory-map the entire thing and - * close the file before returning. - */ -status_t ZipFileRO::open(const char* zipFileName) -{ - int fd = -1; - - assert(mDirectoryMap == NULL); - - /* - * Open and map the specified file. - */ - fd = TEMP_FAILURE_RETRY(::open(zipFileName, O_RDONLY | O_BINARY)); - if (fd < 0) { - ALOGW("Unable to open zip '%s': %s\n", zipFileName, strerror(errno)); - return NAME_NOT_FOUND; - } - - mFileLength = lseek64(fd, 0, SEEK_END); - if (mFileLength < kEOCDLen) { - TEMP_FAILURE_RETRY(close(fd)); - return UNKNOWN_ERROR; - } - - if (mFileName != NULL) { - free(mFileName); - } - mFileName = strdup(zipFileName); - - mFd = fd; - - /* - * Find the Central Directory and store its size and number of entries. - */ - if (!mapCentralDirectory()) { - goto bail; - } - - /* - * Verify Central Directory and create data structures for fast access. - */ - if (!parseZipArchive()) { - goto bail; - } - - return OK; - -bail: - free(mFileName); - mFileName = NULL; - TEMP_FAILURE_RETRY(close(fd)); - return UNKNOWN_ERROR; -} - -/* - * Parse the Zip archive, verifying its contents and initializing internal - * data structures. - */ -bool ZipFileRO::mapCentralDirectory(void) -{ - ssize_t readAmount = kMaxEOCDSearch; - if (readAmount > (ssize_t) mFileLength) - readAmount = mFileLength; - - unsigned char* scanBuf = (unsigned char*) malloc(readAmount); - if (scanBuf == NULL) { - ALOGW("couldn't allocate scanBuf: %s", strerror(errno)); - free(scanBuf); - return false; - } - - /* - * Make sure this is a Zip archive. - */ - if (lseek64(mFd, 0, SEEK_SET) != 0) { - ALOGW("seek to start failed: %s", strerror(errno)); - free(scanBuf); - return false; - } - - ssize_t actual = TEMP_FAILURE_RETRY(read(mFd, scanBuf, sizeof(int32_t))); - if (actual != (ssize_t) sizeof(int32_t)) { - ALOGI("couldn't read first signature from zip archive: %s", strerror(errno)); - free(scanBuf); - return false; - } - - { - unsigned int header = get4LE(scanBuf); - if (header == kEOCDSignature) { - ALOGI("Found Zip archive, but it looks empty\n"); - free(scanBuf); - return false; - } else if (header != kLFHSignature) { - ALOGV("Not a Zip archive (found 0x%08x)\n", header); - free(scanBuf); - return false; - } - } - - /* - * Perform the traditional EOCD snipe hunt. - * - * We're searching for the End of Central Directory magic number, - * which appears at the start of the EOCD block. It's followed by - * 18 bytes of EOCD stuff and up to 64KB of archive comment. We - * need to read the last part of the file into a buffer, dig through - * it to find the magic number, parse some values out, and use those - * to determine the extent of the CD. - * - * We start by pulling in the last part of the file. - */ - off64_t searchStart = mFileLength - readAmount; - - if (lseek64(mFd, searchStart, SEEK_SET) != searchStart) { - ALOGW("seek %ld failed: %s\n", (long) searchStart, strerror(errno)); - free(scanBuf); - return false; - } - actual = TEMP_FAILURE_RETRY(read(mFd, scanBuf, readAmount)); - if (actual != (ssize_t) readAmount) { - ALOGW("Zip: read " ZD ", expected " ZD ". Failed: %s\n", - (ZD_TYPE) actual, (ZD_TYPE) readAmount, strerror(errno)); - free(scanBuf); - return false; - } - - /* - * Scan backward for the EOCD magic. In an archive without a trailing - * comment, we'll find it on the first try. (We may want to consider - * doing an initial minimal read; if we don't find it, retry with a - * second read as above.) - */ - int i; - for (i = readAmount - kEOCDLen; i >= 0; i--) { - if (scanBuf[i] == 0x50 && get4LE(&scanBuf[i]) == kEOCDSignature) { - ALOGV("+++ Found EOCD at buf+%d\n", i); - break; - } - } - if (i < 0) { - ALOGD("Zip: EOCD not found, %s is not zip\n", mFileName); - free(scanBuf); - return false; - } - - off64_t eocdOffset = searchStart + i; - const unsigned char* eocdPtr = scanBuf + i; - - assert(eocdOffset < mFileLength); - - /* - * Grab the CD offset and size, and the number of entries in the - * archive. After that, we can release our EOCD hunt buffer. - */ - unsigned int numEntries = get2LE(eocdPtr + kEOCDNumEntries); - unsigned int dirSize = get4LE(eocdPtr + kEOCDSize); - unsigned int dirOffset = get4LE(eocdPtr + kEOCDFileOffset); - free(scanBuf); - - // Verify that they look reasonable. - if ((long long) dirOffset + (long long) dirSize > (long long) eocdOffset) { - ALOGW("bad offsets (dir %ld, size %u, eocd %ld)\n", - (long) dirOffset, dirSize, (long) eocdOffset); - return false; - } - if (numEntries == 0) { - ALOGW("empty archive?\n"); - return false; - } - - ALOGV("+++ numEntries=%d dirSize=%d dirOffset=%d\n", - numEntries, dirSize, dirOffset); - - mDirectoryMap = new FileMap(); - if (mDirectoryMap == NULL) { - ALOGW("Unable to create directory map: %s", strerror(errno)); - return false; - } - - if (!mDirectoryMap->create(mFileName, mFd, dirOffset, dirSize, true)) { - ALOGW("Unable to map '%s' (" ZD " to " ZD "): %s\n", mFileName, - (ZD_TYPE) dirOffset, (ZD_TYPE) (dirOffset + dirSize), strerror(errno)); - return false; - } - - mNumEntries = numEntries; - mDirectoryOffset = dirOffset; - - return true; -} - - -/* - * Round up to the next highest power of 2. - * - * Found on http://graphics.stanford.edu/~seander/bithacks.html. - */ -static unsigned int roundUpPower2(unsigned int val) -{ - val--; - val |= val >> 1; - val |= val >> 2; - val |= val >> 4; - val |= val >> 8; - val |= val >> 16; - val++; - - return val; -} - -bool ZipFileRO::parseZipArchive(void) -{ - bool result = false; - const unsigned char* cdPtr = (const unsigned char*) mDirectoryMap->getDataPtr(); - size_t cdLength = mDirectoryMap->getDataLength(); - int numEntries = mNumEntries; - - /* - * Create hash table. We have a minimum 75% load factor, possibly as - * low as 50% after we round off to a power of 2. - */ - mHashTableSize = roundUpPower2(1 + (numEntries * 4) / 3); - mHashTable = (HashEntry*) calloc(mHashTableSize, sizeof(HashEntry)); - - /* - * Walk through the central directory, adding entries to the hash - * table. - */ - const unsigned char* ptr = cdPtr; - for (int i = 0; i < numEntries; i++) { - if (get4LE(ptr) != kCDESignature) { - ALOGW("Missed a central dir sig (at %d)\n", i); - goto bail; - } - if (ptr + kCDELen > cdPtr + cdLength) { - ALOGW("Ran off the end (at %d)\n", i); - goto bail; - } - - long localHdrOffset = (long) get4LE(ptr + kCDELocalOffset); - if (localHdrOffset >= mDirectoryOffset) { - ALOGW("bad LFH offset %ld at entry %d\n", localHdrOffset, i); - goto bail; - } - - unsigned int fileNameLen, extraLen, commentLen, hash; - - fileNameLen = get2LE(ptr + kCDENameLen); - extraLen = get2LE(ptr + kCDEExtraLen); - commentLen = get2LE(ptr + kCDECommentLen); - - /* add the CDE filename to the hash table */ - hash = computeHash((const char*)ptr + kCDELen, fileNameLen); - addToHash((const char*)ptr + kCDELen, fileNameLen, hash); - - ptr += kCDELen + fileNameLen + extraLen + commentLen; - if ((size_t)(ptr - cdPtr) > cdLength) { - ALOGW("bad CD advance (%d vs " ZD ") at entry %d\n", - (int) (ptr - cdPtr), (ZD_TYPE) cdLength, i); - goto bail; - } - } - ALOGV("+++ zip good scan %d entries\n", numEntries); - result = true; - -bail: - return result; -} - -/* - * Simple string hash function for non-null-terminated strings. - */ -/*static*/ unsigned int ZipFileRO::computeHash(const char* str, int len) -{ - unsigned int hash = 0; - - while (len--) - hash = hash * 31 + *str++; - - return hash; -} - -/* - * Add a new entry to the hash table. - */ -void ZipFileRO::addToHash(const char* str, int strLen, unsigned int hash) -{ - int ent = hash & (mHashTableSize-1); - - /* - * We over-allocate the table, so we're guaranteed to find an empty slot. - */ - while (mHashTable[ent].name != NULL) - ent = (ent + 1) & (mHashTableSize-1); - - mHashTable[ent].name = str; - mHashTable[ent].nameLen = strLen; -} - -/* - * Find a matching entry. - * - * Returns NULL if not found. - */ -ZipEntryRO ZipFileRO::findEntryByName(const char* fileName) const -{ - /* - * If the ZipFileRO instance is not initialized, the entry number will - * end up being garbage since mHashTableSize is -1. - */ - if (mHashTableSize <= 0) { - return NULL; - } - - int nameLen = strlen(fileName); - unsigned int hash = computeHash(fileName, nameLen); - int ent = hash & (mHashTableSize-1); - - while (mHashTable[ent].name != NULL) { - if (mHashTable[ent].nameLen == nameLen && - memcmp(mHashTable[ent].name, fileName, nameLen) == 0) - { - /* match */ - return (ZipEntryRO)(long)(ent + kZipEntryAdj); - } - - ent = (ent + 1) & (mHashTableSize-1); - } - - return NULL; -} - -/* - * Find the Nth entry. - * - * This currently involves walking through the sparse hash table, counting - * non-empty entries. If we need to speed this up we can either allocate - * a parallel lookup table or (perhaps better) provide an iterator interface. - */ -ZipEntryRO ZipFileRO::findEntryByIndex(int idx) const -{ - if (idx < 0 || idx >= mNumEntries) { - ALOGW("Invalid index %d\n", idx); - return NULL; - } - - for (int ent = 0; ent < mHashTableSize; ent++) { - if (mHashTable[ent].name != NULL) { - if (idx-- == 0) - return (ZipEntryRO) (intptr_t)(ent + kZipEntryAdj); - } - } - - return NULL; -} - -/* - * Get the useful fields from the zip entry. - * - * Returns "false" if the offsets to the fields or the contents of the fields - * appear to be bogus. - */ -bool ZipFileRO::getEntryInfo(ZipEntryRO entry, int* pMethod, size_t* pUncompLen, - size_t* pCompLen, off64_t* pOffset, long* pModWhen, long* pCrc32) const -{ - bool ret = false; - - const int ent = entryToIndex(entry); - if (ent < 0) - return false; - - HashEntry hashEntry = mHashTable[ent]; - - /* - * Recover the start of the central directory entry from the filename - * pointer. The filename is the first entry past the fixed-size data, - * so we can just subtract back from that. - */ - const unsigned char* ptr = (const unsigned char*) hashEntry.name; - off64_t cdOffset = mDirectoryOffset; - - ptr -= kCDELen; - - int method = get2LE(ptr + kCDEMethod); - if (pMethod != NULL) - *pMethod = method; - - if (pModWhen != NULL) - *pModWhen = get4LE(ptr + kCDEModWhen); - if (pCrc32 != NULL) - *pCrc32 = get4LE(ptr + kCDECRC); - - size_t compLen = get4LE(ptr + kCDECompLen); - if (pCompLen != NULL) - *pCompLen = compLen; - size_t uncompLen = get4LE(ptr + kCDEUncompLen); - if (pUncompLen != NULL) - *pUncompLen = uncompLen; - - /* - * If requested, determine the offset of the start of the data. All we - * have is the offset to the Local File Header, which is variable size, - * so we have to read the contents of the struct to figure out where - * the actual data starts. - * - * We also need to make sure that the lengths are not so large that - * somebody trying to map the compressed or uncompressed data runs - * off the end of the mapped region. - * - * Note we don't verify compLen/uncompLen if they don't request the - * dataOffset, because dataOffset is expensive to determine. However, - * if they don't have the file offset, they're not likely to be doing - * anything with the contents. - */ - if (pOffset != NULL) { - long localHdrOffset = get4LE(ptr + kCDELocalOffset); - if (localHdrOffset + kLFHLen >= cdOffset) { - ALOGE("ERROR: bad local hdr offset in zip\n"); - return false; - } - - unsigned char lfhBuf[kLFHLen]; - -#ifdef HAVE_PREAD - /* - * This file descriptor might be from zygote's preloaded assets, - * so we need to do an pread64() instead of a lseek64() + read() to - * guarantee atomicity across the processes with the shared file - * descriptors. - */ - ssize_t actual = - TEMP_FAILURE_RETRY(pread64(mFd, lfhBuf, sizeof(lfhBuf), localHdrOffset)); - - if (actual != sizeof(lfhBuf)) { - ALOGW("failed reading lfh from offset %ld\n", localHdrOffset); - return false; - } - - if (get4LE(lfhBuf) != kLFHSignature) { - ALOGW("didn't find signature at start of lfh; wanted: offset=%ld data=0x%08x; " - "got: data=0x%08lx\n", - localHdrOffset, kLFHSignature, get4LE(lfhBuf)); - return false; - } -#else /* HAVE_PREAD */ - /* - * For hosts don't have pread64() we cannot guarantee atomic reads from - * an offset in a file. Android should never run on those platforms. - * File descriptors inherited from a fork() share file offsets and - * there would be nothing to protect from two different processes - * calling lseek64() concurrently. - */ - - { - AutoMutex _l(mFdLock); - - if (lseek64(mFd, localHdrOffset, SEEK_SET) != localHdrOffset) { - ALOGW("failed seeking to lfh at offset %ld\n", localHdrOffset); - return false; - } - - ssize_t actual = - TEMP_FAILURE_RETRY(read(mFd, lfhBuf, sizeof(lfhBuf))); - if (actual != sizeof(lfhBuf)) { - ALOGW("failed reading lfh from offset %ld\n", localHdrOffset); - return false; - } - - if (get4LE(lfhBuf) != kLFHSignature) { - off64_t actualOffset = lseek64(mFd, 0, SEEK_CUR); - ALOGW("didn't find signature at start of lfh; wanted: offset=%ld data=0x%08x; " - "got: offset=" ZD " data=0x%08lx\n", - localHdrOffset, kLFHSignature, (ZD_TYPE) actualOffset, get4LE(lfhBuf)); - return false; - } - } -#endif /* HAVE_PREAD */ - - off64_t dataOffset = localHdrOffset + kLFHLen - + get2LE(lfhBuf + kLFHNameLen) + get2LE(lfhBuf + kLFHExtraLen); - if (dataOffset >= cdOffset) { - ALOGW("bad data offset %ld in zip\n", (long) dataOffset); - return false; - } - - /* check lengths */ - if ((off64_t)(dataOffset + compLen) > cdOffset) { - ALOGW("bad compressed length in zip (%ld + " ZD " > %ld)\n", - (long) dataOffset, (ZD_TYPE) compLen, (long) cdOffset); - return false; - } - - if (method == kCompressStored && - (off64_t)(dataOffset + uncompLen) > cdOffset) - { - ALOGE("ERROR: bad uncompressed length in zip (%ld + " ZD " > %ld)\n", - (long) dataOffset, (ZD_TYPE) uncompLen, (long) cdOffset); - return false; - } - - *pOffset = dataOffset; - } - - return true; -} - -/* - * Copy the entry's filename to the buffer. - */ -int ZipFileRO::getEntryFileName(ZipEntryRO entry, char* buffer, int bufLen) - const -{ - int ent = entryToIndex(entry); - if (ent < 0) - return -1; - - int nameLen = mHashTable[ent].nameLen; - if (bufLen < nameLen+1) - return nameLen+1; - - memcpy(buffer, mHashTable[ent].name, nameLen); - buffer[nameLen] = '\0'; - return 0; -} - -/* - * Create a new FileMap object that spans the data in "entry". - */ -FileMap* ZipFileRO::createEntryFileMap(ZipEntryRO entry) const -{ - /* - * TODO: the efficient way to do this is to modify FileMap to allow - * sub-regions of a file to be mapped. A reference-counting scheme - * can manage the base memory mapping. For now, we just create a brand - * new mapping off of the Zip archive file descriptor. - */ - - FileMap* newMap; - size_t compLen; - off64_t offset; - - if (!getEntryInfo(entry, NULL, NULL, &compLen, &offset, NULL, NULL)) - return NULL; - - newMap = new FileMap(); - if (!newMap->create(mFileName, mFd, offset, compLen, true)) { - newMap->release(); - return NULL; - } - - return newMap; -} - -/* - * Uncompress an entry, in its entirety, into the provided output buffer. - * - * This doesn't verify the data's CRC, which might be useful for - * uncompressed data. The caller should be able to manage it. - */ -bool ZipFileRO::uncompressEntry(ZipEntryRO entry, void* buffer) const -{ - const size_t kSequentialMin = 32768; - bool result = false; - int ent = entryToIndex(entry); - if (ent < 0) - return -1; - - int method; - size_t uncompLen, compLen; - off64_t offset; - const unsigned char* ptr; - - getEntryInfo(entry, &method, &uncompLen, &compLen, &offset, NULL, NULL); - - FileMap* file = createEntryFileMap(entry); - if (file == NULL) { - goto bail; - } - - ptr = (const unsigned char*) file->getDataPtr(); - - /* - * Experiment with madvise hint. When we want to uncompress a file, - * we pull some stuff out of the central dir entry and then hit a - * bunch of compressed or uncompressed data sequentially. The CDE - * visit will cause a limited amount of read-ahead because it's at - * the end of the file. We could end up doing lots of extra disk - * access if the file we're prying open is small. Bottom line is we - * probably don't want to turn MADV_SEQUENTIAL on and leave it on. - * - * So, if the compressed size of the file is above a certain minimum - * size, temporarily boost the read-ahead in the hope that the extra - * pair of system calls are negated by a reduction in page faults. - */ - if (compLen > kSequentialMin) - file->advise(FileMap::SEQUENTIAL); - - if (method == kCompressStored) { - memcpy(buffer, ptr, uncompLen); - } else { - if (!inflateBuffer(buffer, ptr, uncompLen, compLen)) - goto unmap; - } - - if (compLen > kSequentialMin) - file->advise(FileMap::NORMAL); - - result = true; - -unmap: - file->release(); -bail: - return result; -} - -/* - * Uncompress an entry, in its entirety, to an open file descriptor. - * - * This doesn't verify the data's CRC, but probably should. - */ -bool ZipFileRO::uncompressEntry(ZipEntryRO entry, int fd) const -{ - bool result = false; - int ent = entryToIndex(entry); - if (ent < 0) - return -1; - - int method; - size_t uncompLen, compLen; - off64_t offset; - const unsigned char* ptr; - - getEntryInfo(entry, &method, &uncompLen, &compLen, &offset, NULL, NULL); - - FileMap* file = createEntryFileMap(entry); - if (file == NULL) { - goto bail; - } - - ptr = (const unsigned char*) file->getDataPtr(); - - if (method == kCompressStored) { - ssize_t actual = TEMP_FAILURE_RETRY(write(fd, ptr, uncompLen)); - if (actual < 0) { - ALOGE("Write failed: %s\n", strerror(errno)); - goto unmap; - } else if ((size_t) actual != uncompLen) { - ALOGE("Partial write during uncompress (" ZD " of " ZD ")\n", - (ZD_TYPE) actual, (ZD_TYPE) uncompLen); - goto unmap; - } else { - ALOGI("+++ successful write\n"); - } - } else { - if (!inflateBuffer(fd, ptr, uncompLen, compLen)) - goto unmap; - } - - result = true; - -unmap: - file->release(); -bail: - return result; -} - -/* - * Uncompress "deflate" data from one buffer to another. - */ -/*static*/ bool ZipFileRO::inflateBuffer(void* outBuf, const void* inBuf, - size_t uncompLen, size_t compLen) -{ - bool result = false; - z_stream zstream; - int zerr; - - /* - * Initialize the zlib stream struct. - */ - memset(&zstream, 0, sizeof(zstream)); - zstream.zalloc = Z_NULL; - zstream.zfree = Z_NULL; - zstream.opaque = Z_NULL; - zstream.next_in = (Bytef*)inBuf; - zstream.avail_in = compLen; - zstream.next_out = (Bytef*) outBuf; - zstream.avail_out = uncompLen; - zstream.data_type = Z_UNKNOWN; - - /* - * Use the undocumented "negative window bits" feature to tell zlib - * that there's no zlib header waiting for it. - */ - zerr = inflateInit2(&zstream, -MAX_WBITS); - if (zerr != Z_OK) { - if (zerr == Z_VERSION_ERROR) { - ALOGE("Installed zlib is not compatible with linked version (%s)\n", - ZLIB_VERSION); - } else { - ALOGE("Call to inflateInit2 failed (zerr=%d)\n", zerr); - } - goto bail; - } - - /* - * Expand data. - */ - zerr = inflate(&zstream, Z_FINISH); - if (zerr != Z_STREAM_END) { - ALOGW("Zip inflate failed, zerr=%d (nIn=%p aIn=%u nOut=%p aOut=%u)\n", - zerr, zstream.next_in, zstream.avail_in, - zstream.next_out, zstream.avail_out); - goto z_bail; - } - - /* paranoia */ - if (zstream.total_out != uncompLen) { - ALOGW("Size mismatch on inflated file (%ld vs " ZD ")\n", - zstream.total_out, (ZD_TYPE) uncompLen); - goto z_bail; - } - - result = true; - -z_bail: - inflateEnd(&zstream); /* free up any allocated structures */ - -bail: - return result; -} - -/* - * Uncompress "deflate" data from one buffer to an open file descriptor. - */ -/*static*/ bool ZipFileRO::inflateBuffer(int fd, const void* inBuf, - size_t uncompLen, size_t compLen) -{ - bool result = false; - const size_t kWriteBufSize = 32768; - unsigned char writeBuf[kWriteBufSize]; - z_stream zstream; - int zerr; - - /* - * Initialize the zlib stream struct. - */ - memset(&zstream, 0, sizeof(zstream)); - zstream.zalloc = Z_NULL; - zstream.zfree = Z_NULL; - zstream.opaque = Z_NULL; - zstream.next_in = (Bytef*)inBuf; - zstream.avail_in = compLen; - zstream.next_out = (Bytef*) writeBuf; - zstream.avail_out = sizeof(writeBuf); - zstream.data_type = Z_UNKNOWN; - - /* - * Use the undocumented "negative window bits" feature to tell zlib - * that there's no zlib header waiting for it. - */ - zerr = inflateInit2(&zstream, -MAX_WBITS); - if (zerr != Z_OK) { - if (zerr == Z_VERSION_ERROR) { - ALOGE("Installed zlib is not compatible with linked version (%s)\n", - ZLIB_VERSION); - } else { - ALOGE("Call to inflateInit2 failed (zerr=%d)\n", zerr); - } - goto bail; - } - - /* - * Loop while we have more to do. - */ - do { - /* - * Expand data. - */ - zerr = inflate(&zstream, Z_NO_FLUSH); - if (zerr != Z_OK && zerr != Z_STREAM_END) { - ALOGW("zlib inflate: zerr=%d (nIn=%p aIn=%u nOut=%p aOut=%u)\n", - zerr, zstream.next_in, zstream.avail_in, - zstream.next_out, zstream.avail_out); - goto z_bail; - } - - /* write when we're full or when we're done */ - if (zstream.avail_out == 0 || - (zerr == Z_STREAM_END && zstream.avail_out != sizeof(writeBuf))) - { - long writeSize = zstream.next_out - writeBuf; - int cc = TEMP_FAILURE_RETRY(write(fd, writeBuf, writeSize)); - if (cc < 0) { - ALOGW("write failed in inflate: %s", strerror(errno)); - goto z_bail; - } else if (cc != (int) writeSize) { - ALOGW("write failed in inflate (%d vs %ld)", cc, writeSize); - goto z_bail; - } - - zstream.next_out = writeBuf; - zstream.avail_out = sizeof(writeBuf); - } - } while (zerr == Z_OK); - - assert(zerr == Z_STREAM_END); /* other errors should've been caught */ - - /* paranoia */ - if (zstream.total_out != uncompLen) { - ALOGW("Size mismatch on inflated file (%ld vs " ZD ")\n", - zstream.total_out, (ZD_TYPE) uncompLen); - goto z_bail; - } - - result = true; - -z_bail: - inflateEnd(&zstream); /* free up any allocated structures */ - -bail: - return result; -} diff --git a/libs/utils/ZipUtils.cpp b/libs/utils/ZipUtils.cpp deleted file mode 100644 index a43bbb0..0000000 --- a/libs/utils/ZipUtils.cpp +++ /dev/null @@ -1,345 +0,0 @@ -/* - * Copyright (C) 2007 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -// -// Misc zip/gzip utility functions. -// - -#define LOG_TAG "ziputil" - -#include <utils/Log.h> -#include <utils/Compat.h> -#include <utils/ZipUtils.h> -#include <utils/ZipFileRO.h> - -#include <stdlib.h> -#include <string.h> -#include <assert.h> - -#include <zlib.h> - -using namespace android; - -/* - * Utility function that expands zip/gzip "deflate" compressed data - * into a buffer. - * - * "fd" is an open file positioned at the start of the "deflate" data - * "buf" must hold at least "uncompressedLen" bytes. - */ -/*static*/ bool ZipUtils::inflateToBuffer(int fd, void* buf, - long uncompressedLen, long compressedLen) -{ - bool result = false; - const unsigned long kReadBufSize = 32768; - unsigned char* readBuf = NULL; - z_stream zstream; - int zerr; - unsigned long compRemaining; - - assert(uncompressedLen >= 0); - assert(compressedLen >= 0); - - readBuf = new unsigned char[kReadBufSize]; - if (readBuf == NULL) - goto bail; - compRemaining = compressedLen; - - /* - * Initialize the zlib stream. - */ - memset(&zstream, 0, sizeof(zstream)); - zstream.zalloc = Z_NULL; - zstream.zfree = Z_NULL; - zstream.opaque = Z_NULL; - zstream.next_in = NULL; - zstream.avail_in = 0; - zstream.next_out = (Bytef*) buf; - zstream.avail_out = uncompressedLen; - zstream.data_type = Z_UNKNOWN; - - /* - * Use the undocumented "negative window bits" feature to tell zlib - * that there's no zlib header waiting for it. - */ - zerr = inflateInit2(&zstream, -MAX_WBITS); - if (zerr != Z_OK) { - if (zerr == Z_VERSION_ERROR) { - ALOGE("Installed zlib is not compatible with linked version (%s)\n", - ZLIB_VERSION); - } else { - ALOGE("Call to inflateInit2 failed (zerr=%d)\n", zerr); - } - goto bail; - } - - /* - * Loop while we have data. - */ - do { - unsigned long getSize; - - /* read as much as we can */ - if (zstream.avail_in == 0) { - getSize = (compRemaining > kReadBufSize) ? - kReadBufSize : compRemaining; - ALOGV("+++ reading %ld bytes (%ld left)\n", - getSize, compRemaining); - - int cc = TEMP_FAILURE_RETRY(read(fd, readBuf, getSize)); - if (cc < 0) { - ALOGW("inflate read failed: %s", strerror(errno)); - } else if (cc != (int) getSize) { - ALOGW("inflate read failed (%d vs %ld)", cc, getSize); - goto z_bail; - } - - compRemaining -= getSize; - - zstream.next_in = readBuf; - zstream.avail_in = getSize; - } - - /* uncompress the data */ - zerr = inflate(&zstream, Z_NO_FLUSH); - if (zerr != Z_OK && zerr != Z_STREAM_END) { - ALOGD("zlib inflate call failed (zerr=%d)\n", zerr); - goto z_bail; - } - - /* output buffer holds all, so no need to write the output */ - } while (zerr == Z_OK); - - assert(zerr == Z_STREAM_END); /* other errors should've been caught */ - - if ((long) zstream.total_out != uncompressedLen) { - ALOGW("Size mismatch on inflated file (%ld vs %ld)\n", - zstream.total_out, uncompressedLen); - goto z_bail; - } - - // success! - result = true; - -z_bail: - inflateEnd(&zstream); /* free up any allocated structures */ - -bail: - delete[] readBuf; - return result; -} - -/* - * Utility function that expands zip/gzip "deflate" compressed data - * into a buffer. - * - * (This is a clone of the previous function, but it takes a FILE* instead - * of an fd. We could pass fileno(fd) to the above, but we can run into - * trouble when "fp" has a different notion of what fd's file position is.) - * - * "fp" is an open file positioned at the start of the "deflate" data - * "buf" must hold at least "uncompressedLen" bytes. - */ -/*static*/ bool ZipUtils::inflateToBuffer(FILE* fp, void* buf, - long uncompressedLen, long compressedLen) -{ - bool result = false; - const unsigned long kReadBufSize = 32768; - unsigned char* readBuf = NULL; - z_stream zstream; - int zerr; - unsigned long compRemaining; - - assert(uncompressedLen >= 0); - assert(compressedLen >= 0); - - readBuf = new unsigned char[kReadBufSize]; - if (readBuf == NULL) - goto bail; - compRemaining = compressedLen; - - /* - * Initialize the zlib stream. - */ - memset(&zstream, 0, sizeof(zstream)); - zstream.zalloc = Z_NULL; - zstream.zfree = Z_NULL; - zstream.opaque = Z_NULL; - zstream.next_in = NULL; - zstream.avail_in = 0; - zstream.next_out = (Bytef*) buf; - zstream.avail_out = uncompressedLen; - zstream.data_type = Z_UNKNOWN; - - /* - * Use the undocumented "negative window bits" feature to tell zlib - * that there's no zlib header waiting for it. - */ - zerr = inflateInit2(&zstream, -MAX_WBITS); - if (zerr != Z_OK) { - if (zerr == Z_VERSION_ERROR) { - ALOGE("Installed zlib is not compatible with linked version (%s)\n", - ZLIB_VERSION); - } else { - ALOGE("Call to inflateInit2 failed (zerr=%d)\n", zerr); - } - goto bail; - } - - /* - * Loop while we have data. - */ - do { - unsigned long getSize; - - /* read as much as we can */ - if (zstream.avail_in == 0) { - getSize = (compRemaining > kReadBufSize) ? - kReadBufSize : compRemaining; - ALOGV("+++ reading %ld bytes (%ld left)\n", - getSize, compRemaining); - - int cc = fread(readBuf, 1, getSize, fp); - if (cc != (int) getSize) { - ALOGD("inflate read failed (%d vs %ld)\n", - cc, getSize); - goto z_bail; - } - - compRemaining -= getSize; - - zstream.next_in = readBuf; - zstream.avail_in = getSize; - } - - /* uncompress the data */ - zerr = inflate(&zstream, Z_NO_FLUSH); - if (zerr != Z_OK && zerr != Z_STREAM_END) { - ALOGD("zlib inflate call failed (zerr=%d)\n", zerr); - goto z_bail; - } - - /* output buffer holds all, so no need to write the output */ - } while (zerr == Z_OK); - - assert(zerr == Z_STREAM_END); /* other errors should've been caught */ - - if ((long) zstream.total_out != uncompressedLen) { - ALOGW("Size mismatch on inflated file (%ld vs %ld)\n", - zstream.total_out, uncompressedLen); - goto z_bail; - } - - // success! - result = true; - -z_bail: - inflateEnd(&zstream); /* free up any allocated structures */ - -bail: - delete[] readBuf; - return result; -} - -/* - * Look at the contents of a gzip archive. We want to know where the - * data starts, and how long it will be after it is uncompressed. - * - * We expect to find the CRC and length as the last 8 bytes on the file. - * This is a pretty reasonable thing to expect for locally-compressed - * files, but there's a small chance that some extra padding got thrown - * on (the man page talks about compressed data written to tape). We - * don't currently deal with that here. If "gzip -l" whines, we're going - * to fail too. - * - * On exit, "fp" is pointing at the start of the compressed data. - */ -/*static*/ bool ZipUtils::examineGzip(FILE* fp, int* pCompressionMethod, - long* pUncompressedLen, long* pCompressedLen, unsigned long* pCRC32) -{ - enum { // flags - FTEXT = 0x01, - FHCRC = 0x02, - FEXTRA = 0x04, - FNAME = 0x08, - FCOMMENT = 0x10, - }; - int ic; - int method, flags; - int i; - - ic = getc(fp); - if (ic != 0x1f || getc(fp) != 0x8b) - return false; // not gzip - method = getc(fp); - flags = getc(fp); - - /* quick sanity checks */ - if (method == EOF || flags == EOF) - return false; - if (method != ZipFileRO::kCompressDeflated) - return false; - - /* skip over 4 bytes of mod time, 1 byte XFL, 1 byte OS */ - for (i = 0; i < 6; i++) - (void) getc(fp); - /* consume "extra" field, if present */ - if ((flags & FEXTRA) != 0) { - int len; - - len = getc(fp); - len |= getc(fp) << 8; - while (len-- && getc(fp) != EOF) - ; - } - /* consume filename, if present */ - if ((flags & FNAME) != 0) { - do { - ic = getc(fp); - } while (ic != 0 && ic != EOF); - } - /* consume comment, if present */ - if ((flags & FCOMMENT) != 0) { - do { - ic = getc(fp); - } while (ic != 0 && ic != EOF); - } - /* consume 16-bit header CRC, if present */ - if ((flags & FHCRC) != 0) { - (void) getc(fp); - (void) getc(fp); - } - - if (feof(fp) || ferror(fp)) - return false; - - /* seek to the end; CRC and length are in the last 8 bytes */ - long curPosn = ftell(fp); - unsigned char buf[8]; - fseek(fp, -8, SEEK_END); - *pCompressedLen = ftell(fp) - curPosn; - - if (fread(buf, 1, 8, fp) != 8) - return false; - /* seek back to start of compressed data */ - fseek(fp, curPosn, SEEK_SET); - - *pCompressionMethod = method; - *pCRC32 = ZipFileRO::get4LE(&buf[0]); - *pUncompressedLen = ZipFileRO::get4LE(&buf[4]); - - return true; -} diff --git a/libs/utils/misc.cpp b/libs/utils/misc.cpp index 445a23a..58eb499 100644 --- a/libs/utils/misc.cpp +++ b/libs/utils/misc.cpp @@ -25,7 +25,6 @@ #include <sys/stat.h> #include <string.h> #include <errno.h> -#include <assert.h> #include <stdio.h> #if defined(HAVE_PTHREADS) @@ -38,56 +37,6 @@ using namespace android; namespace android { -/* - * Get a file's type. - */ -FileType getFileType(const char* fileName) -{ - struct stat sb; - - if (stat(fileName, &sb) < 0) { - if (errno == ENOENT || errno == ENOTDIR) - return kFileTypeNonexistent; - else { - fprintf(stderr, "getFileType got errno=%d on '%s'\n", - errno, fileName); - return kFileTypeUnknown; - } - } else { - if (S_ISREG(sb.st_mode)) - return kFileTypeRegular; - else if (S_ISDIR(sb.st_mode)) - return kFileTypeDirectory; - else if (S_ISCHR(sb.st_mode)) - return kFileTypeCharDev; - else if (S_ISBLK(sb.st_mode)) - return kFileTypeBlockDev; - else if (S_ISFIFO(sb.st_mode)) - return kFileTypeFifo; -#ifdef HAVE_SYMLINKS - else if (S_ISLNK(sb.st_mode)) - return kFileTypeSymlink; - else if (S_ISSOCK(sb.st_mode)) - return kFileTypeSocket; -#endif - else - return kFileTypeUnknown; - } -} - -/* - * Get a file's modification date. - */ -time_t getFileModDate(const char* fileName) -{ - struct stat sb; - - if (stat(fileName, &sb) < 0) - return (time_t) -1; - - return sb.st_mtime; -} - struct sysprop_change_callback_info { sysprop_change_callback callback; int priority; diff --git a/libs/utils/tests/Android.mk b/libs/utils/tests/Android.mk index a2ca9c8..a6d9cbe 100644 --- a/libs/utils/tests/Android.mk +++ b/libs/utils/tests/Android.mk @@ -10,8 +10,7 @@ test_src_files := \ LruCache_test.cpp \ String8_test.cpp \ Unicode_test.cpp \ - Vector_test.cpp \ - ZipFileRO_test.cpp + Vector_test.cpp shared_libraries := \ libz \ diff --git a/libs/utils/tests/ZipFileRO_test.cpp b/libs/utils/tests/ZipFileRO_test.cpp deleted file mode 100644 index 7a1d0bd..0000000 --- a/libs/utils/tests/ZipFileRO_test.cpp +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#define LOG_TAG "ZipFileRO_test" -#include <utils/Log.h> -#include <utils/ZipFileRO.h> - -#include <gtest/gtest.h> - -#include <fcntl.h> -#include <string.h> - -namespace android { - -class ZipFileROTest : public testing::Test { -protected: - virtual void SetUp() { - } - - virtual void TearDown() { - } -}; - -TEST_F(ZipFileROTest, ZipTimeConvertSuccess) { - struct tm t; - - // 2011-06-29 14:40:40 - long when = 0x3EDD7514; - - ZipFileRO::zipTimeToTimespec(when, &t); - - EXPECT_EQ(2011, t.tm_year + 1900) - << "Year was improperly converted."; - - EXPECT_EQ(6, t.tm_mon) - << "Month was improperly converted."; - - EXPECT_EQ(29, t.tm_mday) - << "Day was improperly converted."; - - EXPECT_EQ(14, t.tm_hour) - << "Hour was improperly converted."; - - EXPECT_EQ(40, t.tm_min) - << "Minute was improperly converted."; - - EXPECT_EQ(40, t.tm_sec) - << "Second was improperly converted."; -} - -} |