break dependency on utils/ZipEntry.h and utils/ZipFile.h, get rid of inet_address.h and Socket.h which were not used
This commit is contained in:
parent
25cf68b1f8
commit
7e83f043d9
@ -1,80 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2005 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.
|
||||
*/
|
||||
|
||||
//
|
||||
// Socket class. Modeled after Java classes.
|
||||
//
|
||||
#ifndef _RUNTIME_SOCKET_H
|
||||
#define _RUNTIME_SOCKET_H
|
||||
|
||||
#include <utils/inet_address.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
namespace android {
|
||||
|
||||
/*
|
||||
* Basic socket class, needed to abstract away the differences between
|
||||
* BSD sockets and WinSock. This establishes a streaming network
|
||||
* connection (TCP/IP) to somebody.
|
||||
*/
|
||||
class Socket {
|
||||
public:
|
||||
Socket(void);
|
||||
~Socket(void);
|
||||
|
||||
// Create a connection to somewhere.
|
||||
// Return 0 on success.
|
||||
int connect(const char* host, int port);
|
||||
int connect(const InetAddress* addr, int port);
|
||||
|
||||
|
||||
// Close the socket. Don't try to use this object again after
|
||||
// calling this. Returns false on failure.
|
||||
bool close(void);
|
||||
|
||||
// If we created the socket without an address, we can use these
|
||||
// to finish the connection. Returns 0 on success.
|
||||
int bind(const SocketAddress& bindPoint);
|
||||
int connect(const SocketAddress& endPoint);
|
||||
|
||||
// Here we deviate from the traditional object-oriented fanciness
|
||||
// and just provide read/write operators instead of getters for
|
||||
// objects that abstract a stream.
|
||||
//
|
||||
// Standard read/write semantics.
|
||||
int read(void* buf, ssize_t len) const;
|
||||
int write(const void* buf, ssize_t len) const;
|
||||
|
||||
// This must be called once, at program startup.
|
||||
static bool bootInit(void);
|
||||
static void finalShutdown(void);
|
||||
|
||||
private:
|
||||
// Internal function that establishes a connection.
|
||||
int doConnect(const InetSocketAddress& addr);
|
||||
|
||||
unsigned long mSock; // holds SOCKET or int
|
||||
|
||||
static bool mBootInitialized;
|
||||
};
|
||||
|
||||
|
||||
// debug -- unit tests
|
||||
void TestSockets(void);
|
||||
|
||||
}; // namespace android
|
||||
|
||||
#endif // _RUNTIME_SOCKET_H
|
@ -1,345 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2006 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.
|
||||
*/
|
||||
|
||||
//
|
||||
// Zip archive entries.
|
||||
//
|
||||
// The ZipEntry class is tightly meshed with the ZipFile class.
|
||||
//
|
||||
#ifndef __LIBS_ZIPENTRY_H
|
||||
#define __LIBS_ZIPENTRY_H
|
||||
|
||||
#include "Errors.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
namespace android {
|
||||
|
||||
class ZipFile;
|
||||
|
||||
/*
|
||||
* ZipEntry objects represent a single entry in a Zip archive.
|
||||
*
|
||||
* You can use one of these to get or set information about an entry, but
|
||||
* there are no functions here for accessing the data itself. (We could
|
||||
* tuck a pointer to the ZipFile in here for convenience, but that raises
|
||||
* the likelihood of using ZipEntry objects after discarding the ZipFile.)
|
||||
*
|
||||
* File information is stored in two places: next to the file data (the Local
|
||||
* File Header, and possibly a Data Descriptor), and at the end of the file
|
||||
* (the Central Directory Entry). The two must be kept in sync.
|
||||
*/
|
||||
class ZipEntry {
|
||||
public:
|
||||
friend class ZipFile;
|
||||
|
||||
ZipEntry(void)
|
||||
: mDeleted(false), mMarked(false)
|
||||
{}
|
||||
~ZipEntry(void) {}
|
||||
|
||||
/*
|
||||
* Returns "true" if the data is compressed.
|
||||
*/
|
||||
bool isCompressed(void) const {
|
||||
return mCDE.mCompressionMethod != kCompressStored;
|
||||
}
|
||||
int getCompressionMethod(void) const { return mCDE.mCompressionMethod; }
|
||||
|
||||
/*
|
||||
* Return the uncompressed length.
|
||||
*/
|
||||
off_t getUncompressedLen(void) const { return mCDE.mUncompressedSize; }
|
||||
|
||||
/*
|
||||
* Return the compressed length. For uncompressed data, this returns
|
||||
* the same thing as getUncompresesdLen().
|
||||
*/
|
||||
off_t getCompressedLen(void) const { return mCDE.mCompressedSize; }
|
||||
|
||||
/*
|
||||
* Return the absolute file offset of the start of the compressed or
|
||||
* uncompressed data.
|
||||
*/
|
||||
off_t getFileOffset(void) const {
|
||||
return mCDE.mLocalHeaderRelOffset +
|
||||
LocalFileHeader::kLFHLen +
|
||||
mLFH.mFileNameLength +
|
||||
mLFH.mExtraFieldLength;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return the data CRC.
|
||||
*/
|
||||
unsigned long getCRC32(void) const { return mCDE.mCRC32; }
|
||||
|
||||
/*
|
||||
* Return file modification time in UNIX seconds-since-epoch.
|
||||
*/
|
||||
time_t getModWhen(void) const;
|
||||
|
||||
/*
|
||||
* Return the archived file name.
|
||||
*/
|
||||
const char* getFileName(void) const { return (const char*) mCDE.mFileName; }
|
||||
|
||||
/*
|
||||
* Application-defined "mark". Can be useful when synchronizing the
|
||||
* contents of an archive with contents on disk.
|
||||
*/
|
||||
bool getMarked(void) const { return mMarked; }
|
||||
void setMarked(bool val) { mMarked = val; }
|
||||
|
||||
/*
|
||||
* Some basic functions for raw data manipulation. "LE" means
|
||||
* Little Endian.
|
||||
*/
|
||||
static inline unsigned short getShortLE(const unsigned char* buf) {
|
||||
return buf[0] | (buf[1] << 8);
|
||||
}
|
||||
static inline unsigned long getLongLE(const unsigned char* buf) {
|
||||
return buf[0] | (buf[1] << 8) | (buf[2] << 16) | (buf[3] << 24);
|
||||
}
|
||||
static inline void putShortLE(unsigned char* buf, short val) {
|
||||
buf[0] = (unsigned char) val;
|
||||
buf[1] = (unsigned char) (val >> 8);
|
||||
}
|
||||
static inline void putLongLE(unsigned char* buf, long val) {
|
||||
buf[0] = (unsigned char) val;
|
||||
buf[1] = (unsigned char) (val >> 8);
|
||||
buf[2] = (unsigned char) (val >> 16);
|
||||
buf[3] = (unsigned char) (val >> 24);
|
||||
}
|
||||
|
||||
/* defined for Zip archives */
|
||||
enum {
|
||||
kCompressStored = 0, // no compression
|
||||
// shrunk = 1,
|
||||
// reduced 1 = 2,
|
||||
// reduced 2 = 3,
|
||||
// reduced 3 = 4,
|
||||
// reduced 4 = 5,
|
||||
// imploded = 6,
|
||||
// tokenized = 7,
|
||||
kCompressDeflated = 8, // standard deflate
|
||||
// Deflate64 = 9,
|
||||
// lib imploded = 10,
|
||||
// reserved = 11,
|
||||
// bzip2 = 12,
|
||||
};
|
||||
|
||||
/*
|
||||
* Deletion flag. If set, the entry will be removed on the next
|
||||
* call to "flush".
|
||||
*/
|
||||
bool getDeleted(void) const { return mDeleted; }
|
||||
|
||||
protected:
|
||||
/*
|
||||
* Initialize the structure from the file, which is pointing at
|
||||
* our Central Directory entry.
|
||||
*/
|
||||
status_t initFromCDE(FILE* fp);
|
||||
|
||||
/*
|
||||
* Initialize the structure for a new file. We need the filename
|
||||
* and comment so that we can properly size the LFH area. The
|
||||
* filename is mandatory, the comment is optional.
|
||||
*/
|
||||
void initNew(const char* fileName, const char* comment);
|
||||
|
||||
/*
|
||||
* Initialize the structure with the contents of a ZipEntry from
|
||||
* another file.
|
||||
*/
|
||||
status_t initFromExternal(const ZipFile* pZipFile, const ZipEntry* pEntry);
|
||||
|
||||
/*
|
||||
* Add some pad bytes to the LFH. We do this by adding or resizing
|
||||
* the "extra" field.
|
||||
*/
|
||||
status_t addPadding(int padding);
|
||||
|
||||
/*
|
||||
* Set information about the data for this entry.
|
||||
*/
|
||||
void setDataInfo(long uncompLen, long compLen, unsigned long crc32,
|
||||
int compressionMethod);
|
||||
|
||||
/*
|
||||
* Set the modification date.
|
||||
*/
|
||||
void setModWhen(time_t when);
|
||||
|
||||
/*
|
||||
* Return the offset of the local file header.
|
||||
*/
|
||||
off_t getLFHOffset(void) const { return mCDE.mLocalHeaderRelOffset; }
|
||||
|
||||
/*
|
||||
* Set the offset of the local file header, relative to the start of
|
||||
* the current file.
|
||||
*/
|
||||
void setLFHOffset(off_t offset) {
|
||||
mCDE.mLocalHeaderRelOffset = (long) offset;
|
||||
}
|
||||
|
||||
/* mark for deletion; used by ZipFile::remove() */
|
||||
void setDeleted(void) { mDeleted = true; }
|
||||
|
||||
private:
|
||||
/* these are private and not defined */
|
||||
ZipEntry(const ZipEntry& src);
|
||||
ZipEntry& operator=(const ZipEntry& src);
|
||||
|
||||
/* returns "true" if the CDE and the LFH agree */
|
||||
bool compareHeaders(void) const;
|
||||
void copyCDEtoLFH(void);
|
||||
|
||||
bool mDeleted; // set if entry is pending deletion
|
||||
bool mMarked; // app-defined marker
|
||||
|
||||
/*
|
||||
* Every entry in the Zip archive starts off with one of these.
|
||||
*/
|
||||
class LocalFileHeader {
|
||||
public:
|
||||
LocalFileHeader(void) :
|
||||
mVersionToExtract(0),
|
||||
mGPBitFlag(0),
|
||||
mCompressionMethod(0),
|
||||
mLastModFileTime(0),
|
||||
mLastModFileDate(0),
|
||||
mCRC32(0),
|
||||
mCompressedSize(0),
|
||||
mUncompressedSize(0),
|
||||
mFileNameLength(0),
|
||||
mExtraFieldLength(0),
|
||||
mFileName(NULL),
|
||||
mExtraField(NULL)
|
||||
{}
|
||||
virtual ~LocalFileHeader(void) {
|
||||
delete[] mFileName;
|
||||
delete[] mExtraField;
|
||||
}
|
||||
|
||||
status_t read(FILE* fp);
|
||||
status_t write(FILE* fp);
|
||||
|
||||
// unsigned long mSignature;
|
||||
unsigned short mVersionToExtract;
|
||||
unsigned short mGPBitFlag;
|
||||
unsigned short mCompressionMethod;
|
||||
unsigned short mLastModFileTime;
|
||||
unsigned short mLastModFileDate;
|
||||
unsigned long mCRC32;
|
||||
unsigned long mCompressedSize;
|
||||
unsigned long mUncompressedSize;
|
||||
unsigned short mFileNameLength;
|
||||
unsigned short mExtraFieldLength;
|
||||
unsigned char* mFileName;
|
||||
unsigned char* mExtraField;
|
||||
|
||||
enum {
|
||||
kSignature = 0x04034b50,
|
||||
kLFHLen = 30, // LocalFileHdr len, excl. var fields
|
||||
};
|
||||
|
||||
void dump(void) const;
|
||||
};
|
||||
|
||||
/*
|
||||
* Every entry in the Zip archive has one of these in the "central
|
||||
* directory" at the end of the file.
|
||||
*/
|
||||
class CentralDirEntry {
|
||||
public:
|
||||
CentralDirEntry(void) :
|
||||
mVersionMadeBy(0),
|
||||
mVersionToExtract(0),
|
||||
mGPBitFlag(0),
|
||||
mCompressionMethod(0),
|
||||
mLastModFileTime(0),
|
||||
mLastModFileDate(0),
|
||||
mCRC32(0),
|
||||
mCompressedSize(0),
|
||||
mUncompressedSize(0),
|
||||
mFileNameLength(0),
|
||||
mExtraFieldLength(0),
|
||||
mFileCommentLength(0),
|
||||
mDiskNumberStart(0),
|
||||
mInternalAttrs(0),
|
||||
mExternalAttrs(0),
|
||||
mLocalHeaderRelOffset(0),
|
||||
mFileName(NULL),
|
||||
mExtraField(NULL),
|
||||
mFileComment(NULL)
|
||||
{}
|
||||
virtual ~CentralDirEntry(void) {
|
||||
delete[] mFileName;
|
||||
delete[] mExtraField;
|
||||
delete[] mFileComment;
|
||||
}
|
||||
|
||||
status_t read(FILE* fp);
|
||||
status_t write(FILE* fp);
|
||||
|
||||
// unsigned long mSignature;
|
||||
unsigned short mVersionMadeBy;
|
||||
unsigned short mVersionToExtract;
|
||||
unsigned short mGPBitFlag;
|
||||
unsigned short mCompressionMethod;
|
||||
unsigned short mLastModFileTime;
|
||||
unsigned short mLastModFileDate;
|
||||
unsigned long mCRC32;
|
||||
unsigned long mCompressedSize;
|
||||
unsigned long mUncompressedSize;
|
||||
unsigned short mFileNameLength;
|
||||
unsigned short mExtraFieldLength;
|
||||
unsigned short mFileCommentLength;
|
||||
unsigned short mDiskNumberStart;
|
||||
unsigned short mInternalAttrs;
|
||||
unsigned long mExternalAttrs;
|
||||
unsigned long mLocalHeaderRelOffset;
|
||||
unsigned char* mFileName;
|
||||
unsigned char* mExtraField;
|
||||
unsigned char* mFileComment;
|
||||
|
||||
void dump(void) const;
|
||||
|
||||
enum {
|
||||
kSignature = 0x02014b50,
|
||||
kCDELen = 46, // CentralDirEnt len, excl. var fields
|
||||
};
|
||||
};
|
||||
|
||||
enum {
|
||||
//kDataDescriptorSignature = 0x08074b50, // currently unused
|
||||
kDataDescriptorLen = 16, // four 32-bit fields
|
||||
|
||||
kDefaultVersion = 20, // need deflate, nothing much else
|
||||
kDefaultMadeBy = 0x0317, // 03=UNIX, 17=spec v2.3
|
||||
kUsesDataDescr = 0x0008, // GPBitFlag bit 3
|
||||
};
|
||||
|
||||
LocalFileHeader mLFH;
|
||||
CentralDirEntry mCDE;
|
||||
};
|
||||
|
||||
}; // namespace android
|
||||
|
||||
#endif // __LIBS_ZIPENTRY_H
|
@ -1,269 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2006 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.
|
||||
*/
|
||||
|
||||
//
|
||||
// General-purpose Zip archive access. This class allows both reading and
|
||||
// writing to Zip archives, including deletion of existing entries.
|
||||
//
|
||||
#ifndef __LIBS_ZIPFILE_H
|
||||
#define __LIBS_ZIPFILE_H
|
||||
|
||||
#include "ZipEntry.h"
|
||||
#include "Vector.h"
|
||||
#include "Errors.h"
|
||||
#include <stdio.h>
|
||||
|
||||
namespace android {
|
||||
|
||||
/*
|
||||
* Manipulate a Zip archive.
|
||||
*
|
||||
* Some changes will not be visible in the until until "flush" is called.
|
||||
*
|
||||
* The correct way to update a file archive is to make all changes to a
|
||||
* copy of the archive in a temporary file, and then unlink/rename over
|
||||
* the original after everything completes. Because we're only interested
|
||||
* in using this for packaging, we don't worry about such things. Crashing
|
||||
* after making changes and before flush() completes could leave us with
|
||||
* an unusable Zip archive.
|
||||
*/
|
||||
class ZipFile {
|
||||
public:
|
||||
ZipFile(void)
|
||||
: mZipFp(NULL), mReadOnly(false), mNeedCDRewrite(false)
|
||||
{}
|
||||
~ZipFile(void) {
|
||||
if (!mReadOnly)
|
||||
flush();
|
||||
if (mZipFp != NULL)
|
||||
fclose(mZipFp);
|
||||
discardEntries();
|
||||
}
|
||||
|
||||
/*
|
||||
* Open a new or existing archive.
|
||||
*/
|
||||
typedef enum {
|
||||
kOpenReadOnly = 0x01,
|
||||
kOpenReadWrite = 0x02,
|
||||
kOpenCreate = 0x04, // create if it doesn't exist
|
||||
kOpenTruncate = 0x08, // if it exists, empty it
|
||||
};
|
||||
status_t open(const char* zipFileName, int flags);
|
||||
|
||||
/*
|
||||
* Add a file to the end of the archive. Specify whether you want the
|
||||
* library to try to store it compressed.
|
||||
*
|
||||
* If "storageName" is specified, the archive will use that instead
|
||||
* of "fileName".
|
||||
*
|
||||
* If there is already an entry with the same name, the call fails.
|
||||
* Existing entries with the same name must be removed first.
|
||||
*
|
||||
* If "ppEntry" is non-NULL, a pointer to the new entry will be returned.
|
||||
*/
|
||||
status_t add(const char* fileName, int compressionMethod,
|
||||
ZipEntry** ppEntry)
|
||||
{
|
||||
return add(fileName, fileName, compressionMethod, ppEntry);
|
||||
}
|
||||
status_t add(const char* fileName, const char* storageName,
|
||||
int compressionMethod, ZipEntry** ppEntry)
|
||||
{
|
||||
return addCommon(fileName, NULL, 0, storageName,
|
||||
ZipEntry::kCompressStored,
|
||||
compressionMethod, ppEntry);
|
||||
}
|
||||
|
||||
/*
|
||||
* Add a file that is already compressed with gzip.
|
||||
*
|
||||
* If "ppEntry" is non-NULL, a pointer to the new entry will be returned.
|
||||
*/
|
||||
status_t addGzip(const char* fileName, const char* storageName,
|
||||
ZipEntry** ppEntry)
|
||||
{
|
||||
return addCommon(fileName, NULL, 0, storageName,
|
||||
ZipEntry::kCompressDeflated,
|
||||
ZipEntry::kCompressDeflated, ppEntry);
|
||||
}
|
||||
|
||||
/*
|
||||
* Add a file from an in-memory data buffer.
|
||||
*
|
||||
* If "ppEntry" is non-NULL, a pointer to the new entry will be returned.
|
||||
*/
|
||||
status_t add(const void* data, size_t size, const char* storageName,
|
||||
int compressionMethod, ZipEntry** ppEntry)
|
||||
{
|
||||
return addCommon(NULL, data, size, storageName,
|
||||
ZipEntry::kCompressStored,
|
||||
compressionMethod, ppEntry);
|
||||
}
|
||||
|
||||
/*
|
||||
* Add an entry by copying it from another zip file. If "padding" is
|
||||
* nonzero, the specified number of bytes will be added to the "extra"
|
||||
* field in the header.
|
||||
*
|
||||
* If "ppEntry" is non-NULL, a pointer to the new entry will be returned.
|
||||
*/
|
||||
status_t add(const ZipFile* pSourceZip, const ZipEntry* pSourceEntry,
|
||||
int padding, ZipEntry** ppEntry);
|
||||
|
||||
/*
|
||||
* Mark an entry as having been removed. It is not actually deleted
|
||||
* from the archive or our internal data structures until flush() is
|
||||
* called.
|
||||
*/
|
||||
status_t remove(ZipEntry* pEntry);
|
||||
|
||||
/*
|
||||
* Flush changes. If mNeedCDRewrite is set, this writes the central dir.
|
||||
*/
|
||||
status_t flush(void);
|
||||
|
||||
/*
|
||||
* Expand the data into the buffer provided. The buffer must hold
|
||||
* at least <uncompressed len> bytes. Variation expands directly
|
||||
* to a file.
|
||||
*
|
||||
* Returns "false" if an error was encountered in the compressed data.
|
||||
*/
|
||||
//bool uncompress(const ZipEntry* pEntry, void* buf) const;
|
||||
//bool uncompress(const ZipEntry* pEntry, FILE* fp) const;
|
||||
void* uncompress(const ZipEntry* pEntry);
|
||||
|
||||
/*
|
||||
* Get an entry, by name. Returns NULL if not found.
|
||||
*
|
||||
* Does not return entries pending deletion.
|
||||
*/
|
||||
ZipEntry* getEntryByName(const char* fileName) const;
|
||||
|
||||
/*
|
||||
* Get the Nth entry in the archive.
|
||||
*
|
||||
* This will return an entry that is pending deletion.
|
||||
*/
|
||||
int getNumEntries(void) const { return mEntries.size(); }
|
||||
ZipEntry* getEntryByIndex(int idx) const;
|
||||
|
||||
private:
|
||||
/* these are private and not defined */
|
||||
ZipFile(const ZipFile& src);
|
||||
ZipFile& operator=(const ZipFile& src);
|
||||
|
||||
class EndOfCentralDir {
|
||||
public:
|
||||
EndOfCentralDir(void) :
|
||||
mDiskNumber(0),
|
||||
mDiskWithCentralDir(0),
|
||||
mNumEntries(0),
|
||||
mTotalNumEntries(0),
|
||||
mCentralDirSize(0),
|
||||
mCentralDirOffset(0),
|
||||
mCommentLen(0),
|
||||
mComment(NULL)
|
||||
{}
|
||||
virtual ~EndOfCentralDir(void) {
|
||||
delete[] mComment;
|
||||
}
|
||||
|
||||
status_t readBuf(const unsigned char* buf, int len);
|
||||
status_t write(FILE* fp);
|
||||
|
||||
//unsigned long mSignature;
|
||||
unsigned short mDiskNumber;
|
||||
unsigned short mDiskWithCentralDir;
|
||||
unsigned short mNumEntries;
|
||||
unsigned short mTotalNumEntries;
|
||||
unsigned long mCentralDirSize;
|
||||
unsigned long mCentralDirOffset; // offset from first disk
|
||||
unsigned short mCommentLen;
|
||||
unsigned char* mComment;
|
||||
|
||||
enum {
|
||||
kSignature = 0x06054b50,
|
||||
kEOCDLen = 22, // EndOfCentralDir len, excl. comment
|
||||
|
||||
kMaxCommentLen = 65535, // longest possible in ushort
|
||||
kMaxEOCDSearch = kMaxCommentLen + EndOfCentralDir::kEOCDLen,
|
||||
|
||||
};
|
||||
|
||||
void dump(void) const;
|
||||
};
|
||||
|
||||
|
||||
/* read all entries in the central dir */
|
||||
status_t readCentralDir(void);
|
||||
|
||||
/* crunch deleted entries out */
|
||||
status_t crunchArchive(void);
|
||||
|
||||
/* clean up mEntries */
|
||||
void discardEntries(void);
|
||||
|
||||
/* common handler for all "add" functions */
|
||||
status_t addCommon(const char* fileName, const void* data, size_t size,
|
||||
const char* storageName, int sourceType, int compressionMethod,
|
||||
ZipEntry** ppEntry);
|
||||
|
||||
/* copy all of "srcFp" into "dstFp" */
|
||||
status_t copyFpToFp(FILE* dstFp, FILE* srcFp, unsigned long* pCRC32);
|
||||
/* copy all of "data" into "dstFp" */
|
||||
status_t copyDataToFp(FILE* dstFp,
|
||||
const void* data, size_t size, unsigned long* pCRC32);
|
||||
/* copy some of "srcFp" into "dstFp" */
|
||||
status_t copyPartialFpToFp(FILE* dstFp, FILE* srcFp, long length,
|
||||
unsigned long* pCRC32);
|
||||
/* like memmove(), but on parts of a single file */
|
||||
status_t filemove(FILE* fp, off_t dest, off_t src, size_t n);
|
||||
/* compress all of "srcFp" into "dstFp", using Deflate */
|
||||
status_t compressFpToFp(FILE* dstFp, FILE* srcFp,
|
||||
const void* data, size_t size, unsigned long* pCRC32);
|
||||
|
||||
/* get modification date from a file descriptor */
|
||||
time_t getModTime(int fd);
|
||||
|
||||
/*
|
||||
* We use stdio FILE*, which gives us buffering but makes dealing
|
||||
* with files >2GB awkward. Until we support Zip64, we're fine.
|
||||
*/
|
||||
FILE* mZipFp; // Zip file pointer
|
||||
|
||||
/* one of these per file */
|
||||
EndOfCentralDir mEOCD;
|
||||
|
||||
/* did we open this read-only? */
|
||||
bool mReadOnly;
|
||||
|
||||
/* set this when we trash the central dir */
|
||||
bool mNeedCDRewrite;
|
||||
|
||||
/*
|
||||
* One ZipEntry per entry in the zip file. I'm using pointers instead
|
||||
* of objects because it's easier than making operator= work for the
|
||||
* classes and sub-classes.
|
||||
*/
|
||||
Vector<ZipEntry*> mEntries;
|
||||
};
|
||||
|
||||
}; // namespace android
|
||||
|
||||
#endif // __LIBS_ZIPFILE_H
|
@ -1,103 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2005 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.
|
||||
*/
|
||||
|
||||
//
|
||||
// Internet address classes. Modeled after Java classes.
|
||||
//
|
||||
#ifndef _RUNTIME_INET_ADDRESS_H
|
||||
#define _RUNTIME_INET_ADDRESS_H
|
||||
|
||||
#ifdef HAVE_ANDROID_OS
|
||||
#error DO NOT USE THIS FILE IN THE DEVICE BUILD
|
||||
#endif
|
||||
|
||||
|
||||
namespace android {
|
||||
|
||||
/*
|
||||
* This class holds Internet addresses. Perhaps more useful is its
|
||||
* ability to look up addresses by name.
|
||||
*
|
||||
* Invoke one of the static factory methods to create a new object.
|
||||
*/
|
||||
class InetAddress {
|
||||
public:
|
||||
virtual ~InetAddress(void);
|
||||
|
||||
// create from w.x.y.z or foo.bar.com notation
|
||||
static InetAddress* getByName(const char* host);
|
||||
|
||||
// copy-construction
|
||||
InetAddress(const InetAddress& orig);
|
||||
|
||||
const void* getAddress(void) const { return mAddress; }
|
||||
int getAddressLength(void) const { return mLength; }
|
||||
const char* getHostName(void) const { return mName; }
|
||||
|
||||
private:
|
||||
InetAddress(void);
|
||||
// assignment (private)
|
||||
InetAddress& operator=(const InetAddress& addr);
|
||||
|
||||
// use a void* here so we don't have to expose actual socket headers
|
||||
void* mAddress; // this is really a ptr to sockaddr_in
|
||||
int mLength;
|
||||
char* mName;
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* Base class for socket addresses.
|
||||
*/
|
||||
class SocketAddress {
|
||||
public:
|
||||
SocketAddress() {}
|
||||
virtual ~SocketAddress() {}
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* Internet address class. This combines an InetAddress with a port.
|
||||
*/
|
||||
class InetSocketAddress : public SocketAddress {
|
||||
public:
|
||||
InetSocketAddress() :
|
||||
mAddress(0), mPort(-1)
|
||||
{}
|
||||
~InetSocketAddress(void) {
|
||||
delete mAddress;
|
||||
}
|
||||
|
||||
// Create an address with a host wildcard (useful for servers).
|
||||
bool create(int port);
|
||||
// Create an address with the specified host and port.
|
||||
bool create(const InetAddress* addr, int port);
|
||||
// Create an address with the specified host and port. Does the
|
||||
// hostname lookup.
|
||||
bool create(const char* host, int port);
|
||||
|
||||
const InetAddress* getAddress(void) const { return mAddress; }
|
||||
const int getPort(void) const { return mPort; }
|
||||
const char* getHostName(void) const { return mAddress->getHostName(); }
|
||||
|
||||
private:
|
||||
InetAddress* mAddress;
|
||||
int mPort;
|
||||
};
|
||||
|
||||
}; // namespace android
|
||||
|
||||
#endif // _RUNTIME_INET_ADDRESS_H
|
@ -44,26 +44,13 @@ commonSources:= \
|
||||
misc.cpp \
|
||||
LogSocket.cpp
|
||||
|
||||
#
|
||||
# The cpp files listed here do not belong in the device
|
||||
# build. Consult with the swetland before even thinking about
|
||||
# putting them in commonSources.
|
||||
#
|
||||
# They're used by the simulator runtime and by host-side tools like
|
||||
# aapt and the simulator front-end.
|
||||
#
|
||||
hostSources:= \
|
||||
InetAddress.cpp \
|
||||
Socket.cpp \
|
||||
ZipEntry.cpp \
|
||||
ZipFile.cpp
|
||||
|
||||
# For the host
|
||||
# =====================================================
|
||||
|
||||
include $(CLEAR_VARS)
|
||||
|
||||
LOCAL_SRC_FILES:= $(commonSources) $(hostSources)
|
||||
LOCAL_SRC_FILES:= $(commonSources)
|
||||
|
||||
ifeq ($(HOST_OS),linux)
|
||||
# Use the futex based mutex and condition variable
|
||||
@ -100,10 +87,6 @@ LOCAL_SRC_FILES:= \
|
||||
BackupData.cpp \
|
||||
BackupHelpers.cpp
|
||||
|
||||
ifeq ($(TARGET_SIMULATOR),true)
|
||||
LOCAL_SRC_FILES += $(hostSources)
|
||||
endif
|
||||
|
||||
ifeq ($(TARGET_OS),linux)
|
||||
# Use the futex based mutex and condition variable
|
||||
# implementation from android-arm because it's shared mem safe
|
||||
@ -130,9 +113,5 @@ endif # linux-x86
|
||||
endif # sim
|
||||
|
||||
LOCAL_MODULE:= libutils
|
||||
|
||||
#LOCAL_CFLAGS+=
|
||||
#LOCAL_LDFLAGS:=
|
||||
|
||||
include $(BUILD_SHARED_LIBRARY)
|
||||
|
||||
|
@ -1,236 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2005 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.
|
||||
*/
|
||||
|
||||
//
|
||||
// Internet address class.
|
||||
//
|
||||
#ifdef HAVE_WINSOCK
|
||||
# include <winsock2.h>
|
||||
#else
|
||||
# include <sys/types.h>
|
||||
# include <sys/socket.h>
|
||||
# include <netinet/in.h>
|
||||
//# include <arpa/inet.h>
|
||||
# include <netdb.h>
|
||||
#endif
|
||||
|
||||
#include <utils/inet_address.h>
|
||||
#include <utils/threads.h>
|
||||
#include <utils/Log.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
using namespace android;
|
||||
|
||||
|
||||
/*
|
||||
* ===========================================================================
|
||||
* InetAddress
|
||||
* ===========================================================================
|
||||
*/
|
||||
|
||||
// lock for the next couple of functions; could tuck into InetAddress
|
||||
static Mutex* gGHBNLock;
|
||||
|
||||
/*
|
||||
* Lock/unlock access to the hostent struct returned by gethostbyname().
|
||||
*/
|
||||
static inline void lock_gethostbyname(void)
|
||||
{
|
||||
if (gGHBNLock == NULL)
|
||||
gGHBNLock = new Mutex;
|
||||
gGHBNLock->lock();
|
||||
}
|
||||
static inline void unlock_gethostbyname(void)
|
||||
{
|
||||
assert(gGHBNLock != NULL);
|
||||
gGHBNLock->unlock();
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Constructor -- just init members. This is private so that callers
|
||||
* are required to use getByName().
|
||||
*/
|
||||
InetAddress::InetAddress(void)
|
||||
: mAddress(NULL), mLength(-1), mName(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
/*
|
||||
* Destructor -- free address storage.
|
||||
*/
|
||||
InetAddress::~InetAddress(void)
|
||||
{
|
||||
delete[] (char*) mAddress;
|
||||
delete[] mName;
|
||||
}
|
||||
|
||||
/*
|
||||
* Copy constructor.
|
||||
*/
|
||||
InetAddress::InetAddress(const InetAddress& orig)
|
||||
{
|
||||
*this = orig; // use assignment code
|
||||
}
|
||||
|
||||
/*
|
||||
* Assignment operator.
|
||||
*/
|
||||
InetAddress& InetAddress::operator=(const InetAddress& addr)
|
||||
{
|
||||
// handle self-assignment
|
||||
if (this == &addr)
|
||||
return *this;
|
||||
// copy mLength and mAddress
|
||||
mLength = addr.mLength;
|
||||
if (mLength > 0) {
|
||||
mAddress = new char[mLength];
|
||||
memcpy(mAddress, addr.mAddress, mLength);
|
||||
LOG(LOG_DEBUG, "socket",
|
||||
"HEY: copied %d bytes in assignment operator\n", mLength);
|
||||
} else {
|
||||
mAddress = NULL;
|
||||
}
|
||||
// copy mName
|
||||
mName = new char[strlen(addr.mName)+1];
|
||||
strcpy(mName, addr.mName);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
/*
|
||||
* Create a new object from a name or a dotted-number IP notation.
|
||||
*
|
||||
* Returns NULL on failure.
|
||||
*/
|
||||
InetAddress*
|
||||
InetAddress::getByName(const char* host)
|
||||
{
|
||||
InetAddress* newAddr = NULL;
|
||||
struct sockaddr_in addr;
|
||||
struct hostent* he;
|
||||
DurationTimer hostTimer, lockTimer;
|
||||
|
||||
// gethostbyname() isn't reentrant, so we need to lock things until
|
||||
// we can copy the data out.
|
||||
lockTimer.start();
|
||||
lock_gethostbyname();
|
||||
hostTimer.start();
|
||||
|
||||
he = gethostbyname(host);
|
||||
if (he == NULL) {
|
||||
LOG(LOG_WARN, "socket", "WARNING: cannot resolve host %s\n", host);
|
||||
unlock_gethostbyname();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
memcpy(&addr.sin_addr, he->h_addr, he->h_length);
|
||||
addr.sin_family = he->h_addrtype;
|
||||
addr.sin_port = 0;
|
||||
|
||||
// got it, unlock us
|
||||
hostTimer.stop();
|
||||
he = NULL;
|
||||
unlock_gethostbyname();
|
||||
|
||||
lockTimer.stop();
|
||||
if ((long) lockTimer.durationUsecs() > 100000) {
|
||||
long lockTime = (long) lockTimer.durationUsecs();
|
||||
long hostTime = (long) hostTimer.durationUsecs();
|
||||
LOG(LOG_DEBUG, "socket",
|
||||
"Lookup of %s took %.3fs (gethostbyname=%.3fs lock=%.3fs)\n",
|
||||
host, lockTime / 1000000.0, hostTime / 1000000.0,
|
||||
(lockTime - hostTime) / 1000000.0);
|
||||
}
|
||||
|
||||
// Alloc storage and copy it over.
|
||||
newAddr = new InetAddress();
|
||||
if (newAddr == NULL)
|
||||
return NULL;
|
||||
|
||||
newAddr->mLength = sizeof(struct sockaddr_in);
|
||||
newAddr->mAddress = new char[sizeof(struct sockaddr_in)];
|
||||
if (newAddr->mAddress == NULL) {
|
||||
delete newAddr;
|
||||
return NULL;
|
||||
}
|
||||
memcpy(newAddr->mAddress, &addr, newAddr->mLength);
|
||||
|
||||
// Keep this for debug messages.
|
||||
newAddr->mName = new char[strlen(host)+1];
|
||||
if (newAddr->mName == NULL) {
|
||||
delete newAddr;
|
||||
return NULL;
|
||||
}
|
||||
strcpy(newAddr->mName, host);
|
||||
|
||||
return newAddr;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* ===========================================================================
|
||||
* InetSocketAddress
|
||||
* ===========================================================================
|
||||
*/
|
||||
|
||||
/*
|
||||
* Create an address with the host wildcard (INADDR_ANY).
|
||||
*/
|
||||
bool InetSocketAddress::create(int port)
|
||||
{
|
||||
assert(mAddress == NULL);
|
||||
|
||||
mAddress = InetAddress::getByName("0.0.0.0");
|
||||
if (mAddress == NULL)
|
||||
return false;
|
||||
mPort = port;
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Create address with host and port specified.
|
||||
*/
|
||||
bool InetSocketAddress::create(const InetAddress* addr, int port)
|
||||
{
|
||||
assert(mAddress == NULL);
|
||||
|
||||
mAddress = new InetAddress(*addr); // make a copy
|
||||
if (mAddress == NULL)
|
||||
return false;
|
||||
mPort = port;
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Create address with host and port specified.
|
||||
*/
|
||||
bool InetSocketAddress::create(const char* host, int port)
|
||||
{
|
||||
assert(mAddress == NULL);
|
||||
|
||||
mAddress = InetAddress::getByName(host);
|
||||
if (mAddress == NULL)
|
||||
return false;
|
||||
mPort = port;
|
||||
return true;
|
||||
}
|
||||
|
@ -1,388 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2005 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.
|
||||
*/
|
||||
|
||||
//
|
||||
// Internet address class.
|
||||
//
|
||||
|
||||
#ifdef HAVE_WINSOCK
|
||||
// This needs to come first, or Cygwin gets concerned about a potential
|
||||
// clash between WinSock and <sys/types.h>.
|
||||
# include <winsock2.h>
|
||||
#endif
|
||||
|
||||
#include <utils/Socket.h>
|
||||
#include <utils/inet_address.h>
|
||||
#include <utils/Log.h>
|
||||
#include <utils/Timers.h>
|
||||
|
||||
#ifndef HAVE_WINSOCK
|
||||
# include <sys/types.h>
|
||||
# include <sys/socket.h>
|
||||
# include <netinet/in.h>
|
||||
# include <arpa/inet.h>
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <assert.h>
|
||||
|
||||
using namespace android;
|
||||
|
||||
|
||||
/*
|
||||
* ===========================================================================
|
||||
* Socket
|
||||
* ===========================================================================
|
||||
*/
|
||||
|
||||
#ifndef INVALID_SOCKET
|
||||
# define INVALID_SOCKET (-1)
|
||||
#endif
|
||||
#define UNDEF_SOCKET ((unsigned long) INVALID_SOCKET)
|
||||
|
||||
/*static*/ bool Socket::mBootInitialized = false;
|
||||
|
||||
/*
|
||||
* Extract system-dependent error code.
|
||||
*/
|
||||
static inline int getSocketError(void) {
|
||||
#ifdef HAVE_WINSOCK
|
||||
return WSAGetLastError();
|
||||
#else
|
||||
return errno;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* One-time initialization for socket code.
|
||||
*/
|
||||
/*static*/ bool Socket::bootInit(void)
|
||||
{
|
||||
#ifdef HAVE_WINSOCK
|
||||
WSADATA wsaData;
|
||||
int err;
|
||||
|
||||
err = WSAStartup(MAKEWORD(2, 0), &wsaData);
|
||||
if (err != 0) {
|
||||
LOG(LOG_ERROR, "socket", "Unable to start WinSock\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
LOG(LOG_INFO, "socket", "Using WinSock v%d.%d\n",
|
||||
LOBYTE(wsaData.wVersion), HIBYTE(wsaData.wVersion));
|
||||
#endif
|
||||
|
||||
mBootInitialized = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* One-time shutdown for socket code.
|
||||
*/
|
||||
/*static*/ void Socket::finalShutdown(void)
|
||||
{
|
||||
#ifdef HAVE_WINSOCK
|
||||
WSACleanup();
|
||||
#endif
|
||||
mBootInitialized = false;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Simple constructor. Allow the application to create us and then make
|
||||
* bind/connect calls.
|
||||
*/
|
||||
Socket::Socket(void)
|
||||
: mSock(UNDEF_SOCKET)
|
||||
{
|
||||
if (!mBootInitialized)
|
||||
LOG(LOG_WARN, "socket", "WARNING: sockets not initialized\n");
|
||||
}
|
||||
|
||||
/*
|
||||
* Destructor. Closes the socket and resets our storage.
|
||||
*/
|
||||
Socket::~Socket(void)
|
||||
{
|
||||
close();
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Create a socket and connect to the specified host and port.
|
||||
*/
|
||||
int Socket::connect(const char* host, int port)
|
||||
{
|
||||
if (mSock != UNDEF_SOCKET) {
|
||||
LOG(LOG_WARN, "socket", "Socket already connected\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
InetSocketAddress sockAddr;
|
||||
if (!sockAddr.create(host, port))
|
||||
return -1;
|
||||
|
||||
//return doConnect(sockAddr);
|
||||
int foo;
|
||||
foo = doConnect(sockAddr);
|
||||
return foo;
|
||||
}
|
||||
|
||||
/*
|
||||
* Create a socket and connect to the specified host and port.
|
||||
*/
|
||||
int Socket::connect(const InetAddress* addr, int port)
|
||||
{
|
||||
if (mSock != UNDEF_SOCKET) {
|
||||
LOG(LOG_WARN, "socket", "Socket already connected\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
InetSocketAddress sockAddr;
|
||||
if (!sockAddr.create(addr, port))
|
||||
return -1;
|
||||
|
||||
return doConnect(sockAddr);
|
||||
}
|
||||
|
||||
/*
|
||||
* Finish creating a socket by connecting to the remote host.
|
||||
*
|
||||
* Returns 0 on success.
|
||||
*/
|
||||
int Socket::doConnect(const InetSocketAddress& sockAddr)
|
||||
{
|
||||
#ifdef HAVE_WINSOCK
|
||||
SOCKET sock;
|
||||
#else
|
||||
int sock;
|
||||
#endif
|
||||
const InetAddress* addr = sockAddr.getAddress();
|
||||
int port = sockAddr.getPort();
|
||||
struct sockaddr_in inaddr;
|
||||
DurationTimer connectTimer;
|
||||
|
||||
assert(sizeof(struct sockaddr_in) == addr->getAddressLength());
|
||||
memcpy(&inaddr, addr->getAddress(), addr->getAddressLength());
|
||||
inaddr.sin_port = htons(port);
|
||||
|
||||
//fprintf(stderr, "--- connecting to %s:%d\n",
|
||||
// sockAddr.getHostName(), port);
|
||||
|
||||
sock = ::socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
|
||||
if (sock == INVALID_SOCKET) {
|
||||
int err = getSocketError();
|
||||
LOG(LOG_ERROR, "socket", "Unable to create socket (err=%d)\n", err);
|
||||
return (err != 0) ? err : -1;
|
||||
}
|
||||
|
||||
connectTimer.start();
|
||||
|
||||
if (::connect(sock, (struct sockaddr*) &inaddr, sizeof(inaddr)) != 0) {
|
||||
int err = getSocketError();
|
||||
LOG(LOG_WARN, "socket", "Connect to %s:%d failed: %d\n",
|
||||
sockAddr.getHostName(), port, err);
|
||||
return (err != 0) ? err : -1;
|
||||
}
|
||||
|
||||
connectTimer.stop();
|
||||
if ((long) connectTimer.durationUsecs() > 100000) {
|
||||
LOG(LOG_INFO, "socket",
|
||||
"Connect to %s:%d took %.3fs\n", sockAddr.getHostName(),
|
||||
port, ((long) connectTimer.durationUsecs()) / 1000000.0);
|
||||
}
|
||||
|
||||
mSock = (unsigned long) sock;
|
||||
LOG(LOG_VERBOSE, "socket",
|
||||
"--- connected to %s:%d\n", sockAddr.getHostName(), port);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Close the socket if it needs closing.
|
||||
*/
|
||||
bool Socket::close(void)
|
||||
{
|
||||
if (mSock != UNDEF_SOCKET) {
|
||||
//fprintf(stderr, "--- closing socket %lu\n", mSock);
|
||||
#ifdef HAVE_WINSOCK
|
||||
if (::closesocket((SOCKET) mSock) != 0)
|
||||
return false;
|
||||
#else
|
||||
if (::close((int) mSock) != 0)
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
mSock = UNDEF_SOCKET;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Read data from socket.
|
||||
*
|
||||
* Standard semantics: read up to "len" bytes into "buf". Returns the
|
||||
* number of bytes read, or less than zero on error.
|
||||
*/
|
||||
int Socket::read(void* buf, ssize_t len) const
|
||||
{
|
||||
if (mSock == UNDEF_SOCKET) {
|
||||
LOG(LOG_ERROR, "socket", "ERROR: read on invalid socket\n");
|
||||
return -500;
|
||||
}
|
||||
|
||||
#ifdef HAVE_WINSOCK
|
||||
SOCKET sock = (SOCKET) mSock;
|
||||
#else
|
||||
int sock = (int) mSock;
|
||||
#endif
|
||||
int cc;
|
||||
|
||||
cc = recv(sock, (char*)buf, len, 0);
|
||||
if (cc < 0) {
|
||||
int err = getSocketError();
|
||||
return (err > 0) ? -err : -1;
|
||||
}
|
||||
|
||||
return cc;
|
||||
}
|
||||
|
||||
/*
|
||||
* Write data to a socket.
|
||||
*
|
||||
* Standard semantics: write up to "len" bytes into "buf". Returns the
|
||||
* number of bytes written, or less than zero on error.
|
||||
*/
|
||||
int Socket::write(const void* buf, ssize_t len) const
|
||||
{
|
||||
if (mSock == UNDEF_SOCKET) {
|
||||
LOG(LOG_ERROR, "socket", "ERROR: write on invalid socket\n");
|
||||
return -500;
|
||||
}
|
||||
|
||||
#ifdef HAVE_WINSOCK
|
||||
SOCKET sock = (SOCKET) mSock;
|
||||
#else
|
||||
int sock = (int) mSock;
|
||||
#endif
|
||||
int cc;
|
||||
|
||||
cc = send(sock, (const char*)buf, len, 0);
|
||||
if (cc < 0) {
|
||||
int err = getSocketError();
|
||||
return (err > 0) ? -err : -1;
|
||||
}
|
||||
|
||||
return cc;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* ===========================================================================
|
||||
* Socket tests
|
||||
* ===========================================================================
|
||||
*/
|
||||
|
||||
/*
|
||||
* Read all data from the socket. The data is read into a buffer that
|
||||
* expands as needed.
|
||||
*
|
||||
* On exit, the buffer is returned, and the length of the data is stored
|
||||
* in "*sz". A null byte is added to the end, but is not included in
|
||||
* the length.
|
||||
*/
|
||||
static char* socketReadAll(const Socket& s, int *sz)
|
||||
{
|
||||
int max, r;
|
||||
char *data, *ptr, *tmp;
|
||||
|
||||
data = (char*) malloc(max = 32768);
|
||||
if (data == NULL)
|
||||
return NULL;
|
||||
|
||||
ptr = data;
|
||||
|
||||
for (;;) {
|
||||
if ((ptr - data) == max) {
|
||||
tmp = (char*) realloc(data, max *= 2);
|
||||
if(tmp == 0) {
|
||||
free(data);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
r = s.read(ptr, max - (ptr - data));
|
||||
if (r == 0)
|
||||
break;
|
||||
if (r < 0) {
|
||||
LOG(LOG_WARN, "socket", "WARNING: socket read failed (res=%d)\n",r);
|
||||
break;
|
||||
}
|
||||
ptr += r;
|
||||
}
|
||||
|
||||
if ((ptr - data) == max) {
|
||||
tmp = (char*) realloc(data, max + 1);
|
||||
if (tmp == NULL) {
|
||||
free(data);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
*ptr = '\0';
|
||||
*sz = (ptr - data);
|
||||
return data;
|
||||
}
|
||||
|
||||
/*
|
||||
* Exercise the Socket class.
|
||||
*/
|
||||
void android::TestSockets(void)
|
||||
{
|
||||
printf("----- SOCKET TEST ------\n");
|
||||
Socket::bootInit();
|
||||
|
||||
char* buf = NULL;
|
||||
int len, cc;
|
||||
const char* kTestStr =
|
||||
"GET / HTTP/1.0\n"
|
||||
"Connection: close\n"
|
||||
"\n";
|
||||
|
||||
Socket sock;
|
||||
if (sock.connect("www.google.com", 80) != 0) {
|
||||
fprintf(stderr, "socket connected failed\n");
|
||||
goto bail;
|
||||
}
|
||||
|
||||
cc = sock.write(kTestStr, strlen(kTestStr));
|
||||
if (cc != (int) strlen(kTestStr)) {
|
||||
fprintf(stderr, "write failed, res=%d\n", cc);
|
||||
goto bail;
|
||||
}
|
||||
buf = socketReadAll(sock, &len);
|
||||
|
||||
printf("GOT '%s'\n", buf);
|
||||
|
||||
bail:
|
||||
sock.close();
|
||||
free(buf);
|
||||
}
|
||||
|
@ -1,696 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2006 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.
|
||||
*/
|
||||
|
||||
//
|
||||
// Access to entries in a Zip archive.
|
||||
//
|
||||
|
||||
#define LOG_TAG "zip"
|
||||
|
||||
#include <utils/ZipEntry.h>
|
||||
#include <utils/Log.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
using namespace android;
|
||||
|
||||
/*
|
||||
* Initialize a new ZipEntry structure from a FILE* positioned at a
|
||||
* CentralDirectoryEntry.
|
||||
*
|
||||
* On exit, the file pointer will be at the start of the next CDE or
|
||||
* at the EOCD.
|
||||
*/
|
||||
status_t ZipEntry::initFromCDE(FILE* fp)
|
||||
{
|
||||
status_t result;
|
||||
long posn;
|
||||
bool hasDD;
|
||||
|
||||
//LOGV("initFromCDE ---\n");
|
||||
|
||||
/* read the CDE */
|
||||
result = mCDE.read(fp);
|
||||
if (result != NO_ERROR) {
|
||||
LOGD("mCDE.read failed\n");
|
||||
return result;
|
||||
}
|
||||
|
||||
//mCDE.dump();
|
||||
|
||||
/* using the info in the CDE, go load up the LFH */
|
||||
posn = ftell(fp);
|
||||
if (fseek(fp, mCDE.mLocalHeaderRelOffset, SEEK_SET) != 0) {
|
||||
LOGD("local header seek failed (%ld)\n",
|
||||
mCDE.mLocalHeaderRelOffset);
|
||||
return UNKNOWN_ERROR;
|
||||
}
|
||||
|
||||
result = mLFH.read(fp);
|
||||
if (result != NO_ERROR) {
|
||||
LOGD("mLFH.read failed\n");
|
||||
return result;
|
||||
}
|
||||
|
||||
if (fseek(fp, posn, SEEK_SET) != 0)
|
||||
return UNKNOWN_ERROR;
|
||||
|
||||
//mLFH.dump();
|
||||
|
||||
/*
|
||||
* We *might* need to read the Data Descriptor at this point and
|
||||
* integrate it into the LFH. If this bit is set, the CRC-32,
|
||||
* compressed size, and uncompressed size will be zero. In practice
|
||||
* these seem to be rare.
|
||||
*/
|
||||
hasDD = (mLFH.mGPBitFlag & kUsesDataDescr) != 0;
|
||||
if (hasDD) {
|
||||
// do something clever
|
||||
//LOGD("+++ has data descriptor\n");
|
||||
}
|
||||
|
||||
/*
|
||||
* Sanity-check the LFH. Note that this will fail if the "kUsesDataDescr"
|
||||
* flag is set, because the LFH is incomplete. (Not a problem, since we
|
||||
* prefer the CDE values.)
|
||||
*/
|
||||
if (!hasDD && !compareHeaders()) {
|
||||
LOGW("WARNING: header mismatch\n");
|
||||
// keep going?
|
||||
}
|
||||
|
||||
/*
|
||||
* If the mVersionToExtract is greater than 20, we may have an
|
||||
* issue unpacking the record -- could be encrypted, compressed
|
||||
* with something we don't support, or use Zip64 extensions. We
|
||||
* can defer worrying about that to when we're extracting data.
|
||||
*/
|
||||
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize a new entry. Pass in the file name and an optional comment.
|
||||
*
|
||||
* Initializes the CDE and the LFH.
|
||||
*/
|
||||
void ZipEntry::initNew(const char* fileName, const char* comment)
|
||||
{
|
||||
assert(fileName != NULL && *fileName != '\0'); // name required
|
||||
|
||||
/* most fields are properly initialized by constructor */
|
||||
mCDE.mVersionMadeBy = kDefaultMadeBy;
|
||||
mCDE.mVersionToExtract = kDefaultVersion;
|
||||
mCDE.mCompressionMethod = kCompressStored;
|
||||
mCDE.mFileNameLength = strlen(fileName);
|
||||
if (comment != NULL)
|
||||
mCDE.mFileCommentLength = strlen(comment);
|
||||
mCDE.mExternalAttrs = 0x81b60020; // matches what WinZip does
|
||||
|
||||
if (mCDE.mFileNameLength > 0) {
|
||||
mCDE.mFileName = new unsigned char[mCDE.mFileNameLength+1];
|
||||
strcpy((char*) mCDE.mFileName, fileName);
|
||||
}
|
||||
if (mCDE.mFileCommentLength > 0) {
|
||||
/* TODO: stop assuming null-terminated ASCII here? */
|
||||
mCDE.mFileComment = new unsigned char[mCDE.mFileCommentLength+1];
|
||||
strcpy((char*) mCDE.mFileComment, comment);
|
||||
}
|
||||
|
||||
copyCDEtoLFH();
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize a new entry, starting with the ZipEntry from a different
|
||||
* archive.
|
||||
*
|
||||
* Initializes the CDE and the LFH.
|
||||
*/
|
||||
status_t ZipEntry::initFromExternal(const ZipFile* pZipFile,
|
||||
const ZipEntry* pEntry)
|
||||
{
|
||||
/*
|
||||
* Copy everything in the CDE over, then fix up the hairy bits.
|
||||
*/
|
||||
memcpy(&mCDE, &pEntry->mCDE, sizeof(mCDE));
|
||||
|
||||
if (mCDE.mFileNameLength > 0) {
|
||||
mCDE.mFileName = new unsigned char[mCDE.mFileNameLength+1];
|
||||
if (mCDE.mFileName == NULL)
|
||||
return NO_MEMORY;
|
||||
strcpy((char*) mCDE.mFileName, (char*)pEntry->mCDE.mFileName);
|
||||
}
|
||||
if (mCDE.mFileCommentLength > 0) {
|
||||
mCDE.mFileComment = new unsigned char[mCDE.mFileCommentLength+1];
|
||||
if (mCDE.mFileComment == NULL)
|
||||
return NO_MEMORY;
|
||||
strcpy((char*) mCDE.mFileComment, (char*)pEntry->mCDE.mFileComment);
|
||||
}
|
||||
if (mCDE.mExtraFieldLength > 0) {
|
||||
/* we null-terminate this, though it may not be a string */
|
||||
mCDE.mExtraField = new unsigned char[mCDE.mExtraFieldLength+1];
|
||||
if (mCDE.mExtraField == NULL)
|
||||
return NO_MEMORY;
|
||||
memcpy(mCDE.mExtraField, pEntry->mCDE.mExtraField,
|
||||
mCDE.mExtraFieldLength+1);
|
||||
}
|
||||
|
||||
/* construct the LFH from the CDE */
|
||||
copyCDEtoLFH();
|
||||
|
||||
/*
|
||||
* The LFH "extra" field is independent of the CDE "extra", so we
|
||||
* handle it here.
|
||||
*/
|
||||
assert(mLFH.mExtraField == NULL);
|
||||
mLFH.mExtraFieldLength = pEntry->mLFH.mExtraFieldLength;
|
||||
if (mLFH.mExtraFieldLength > 0) {
|
||||
mLFH.mExtraField = new unsigned char[mLFH.mExtraFieldLength+1];
|
||||
if (mLFH.mExtraField == NULL)
|
||||
return NO_MEMORY;
|
||||
memcpy(mLFH.mExtraField, pEntry->mLFH.mExtraField,
|
||||
mLFH.mExtraFieldLength+1);
|
||||
}
|
||||
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
/*
|
||||
* Insert pad bytes in the LFH by tweaking the "extra" field. This will
|
||||
* potentially confuse something that put "extra" data in here earlier,
|
||||
* but I can't find an actual problem.
|
||||
*/
|
||||
status_t ZipEntry::addPadding(int padding)
|
||||
{
|
||||
if (padding <= 0)
|
||||
return INVALID_OPERATION;
|
||||
|
||||
//LOGI("HEY: adding %d pad bytes to existing %d in %s\n",
|
||||
// padding, mLFH.mExtraFieldLength, mCDE.mFileName);
|
||||
|
||||
if (mLFH.mExtraFieldLength > 0) {
|
||||
/* extend existing field */
|
||||
unsigned char* newExtra;
|
||||
|
||||
newExtra = new unsigned char[mLFH.mExtraFieldLength + padding];
|
||||
if (newExtra == NULL)
|
||||
return NO_MEMORY;
|
||||
memset(newExtra + mLFH.mExtraFieldLength, 0, padding);
|
||||
memcpy(newExtra, mLFH.mExtraField, mLFH.mExtraFieldLength);
|
||||
|
||||
delete[] mLFH.mExtraField;
|
||||
mLFH.mExtraField = newExtra;
|
||||
mLFH.mExtraFieldLength += padding;
|
||||
} else {
|
||||
/* create new field */
|
||||
mLFH.mExtraField = new unsigned char[padding];
|
||||
memset(mLFH.mExtraField, 0, padding);
|
||||
mLFH.mExtraFieldLength = padding;
|
||||
}
|
||||
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the fields in the LFH equal to the corresponding fields in the CDE.
|
||||
*
|
||||
* This does not touch the LFH "extra" field.
|
||||
*/
|
||||
void ZipEntry::copyCDEtoLFH(void)
|
||||
{
|
||||
mLFH.mVersionToExtract = mCDE.mVersionToExtract;
|
||||
mLFH.mGPBitFlag = mCDE.mGPBitFlag;
|
||||
mLFH.mCompressionMethod = mCDE.mCompressionMethod;
|
||||
mLFH.mLastModFileTime = mCDE.mLastModFileTime;
|
||||
mLFH.mLastModFileDate = mCDE.mLastModFileDate;
|
||||
mLFH.mCRC32 = mCDE.mCRC32;
|
||||
mLFH.mCompressedSize = mCDE.mCompressedSize;
|
||||
mLFH.mUncompressedSize = mCDE.mUncompressedSize;
|
||||
mLFH.mFileNameLength = mCDE.mFileNameLength;
|
||||
// the "extra field" is independent
|
||||
|
||||
delete[] mLFH.mFileName;
|
||||
if (mLFH.mFileNameLength > 0) {
|
||||
mLFH.mFileName = new unsigned char[mLFH.mFileNameLength+1];
|
||||
strcpy((char*) mLFH.mFileName, (const char*) mCDE.mFileName);
|
||||
} else {
|
||||
mLFH.mFileName = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Set some information about a file after we add it.
|
||||
*/
|
||||
void ZipEntry::setDataInfo(long uncompLen, long compLen, unsigned long crc32,
|
||||
int compressionMethod)
|
||||
{
|
||||
mCDE.mCompressionMethod = compressionMethod;
|
||||
mCDE.mCRC32 = crc32;
|
||||
mCDE.mCompressedSize = compLen;
|
||||
mCDE.mUncompressedSize = uncompLen;
|
||||
mCDE.mCompressionMethod = compressionMethod;
|
||||
if (compressionMethod == kCompressDeflated) {
|
||||
mCDE.mGPBitFlag |= 0x0002; // indicates maximum compression used
|
||||
}
|
||||
copyCDEtoLFH();
|
||||
}
|
||||
|
||||
/*
|
||||
* See if the data in mCDE and mLFH match up. This is mostly useful for
|
||||
* debugging these classes, but it can be used to identify damaged
|
||||
* archives.
|
||||
*
|
||||
* Returns "false" if they differ.
|
||||
*/
|
||||
bool ZipEntry::compareHeaders(void) const
|
||||
{
|
||||
if (mCDE.mVersionToExtract != mLFH.mVersionToExtract) {
|
||||
LOGV("cmp: VersionToExtract\n");
|
||||
return false;
|
||||
}
|
||||
if (mCDE.mGPBitFlag != mLFH.mGPBitFlag) {
|
||||
LOGV("cmp: GPBitFlag\n");
|
||||
return false;
|
||||
}
|
||||
if (mCDE.mCompressionMethod != mLFH.mCompressionMethod) {
|
||||
LOGV("cmp: CompressionMethod\n");
|
||||
return false;
|
||||
}
|
||||
if (mCDE.mLastModFileTime != mLFH.mLastModFileTime) {
|
||||
LOGV("cmp: LastModFileTime\n");
|
||||
return false;
|
||||
}
|
||||
if (mCDE.mLastModFileDate != mLFH.mLastModFileDate) {
|
||||
LOGV("cmp: LastModFileDate\n");
|
||||
return false;
|
||||
}
|
||||
if (mCDE.mCRC32 != mLFH.mCRC32) {
|
||||
LOGV("cmp: CRC32\n");
|
||||
return false;
|
||||
}
|
||||
if (mCDE.mCompressedSize != mLFH.mCompressedSize) {
|
||||
LOGV("cmp: CompressedSize\n");
|
||||
return false;
|
||||
}
|
||||
if (mCDE.mUncompressedSize != mLFH.mUncompressedSize) {
|
||||
LOGV("cmp: UncompressedSize\n");
|
||||
return false;
|
||||
}
|
||||
if (mCDE.mFileNameLength != mLFH.mFileNameLength) {
|
||||
LOGV("cmp: FileNameLength\n");
|
||||
return false;
|
||||
}
|
||||
#if 0 // this seems to be used for padding, not real data
|
||||
if (mCDE.mExtraFieldLength != mLFH.mExtraFieldLength) {
|
||||
LOGV("cmp: ExtraFieldLength\n");
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
if (mCDE.mFileName != NULL) {
|
||||
if (strcmp((char*) mCDE.mFileName, (char*) mLFH.mFileName) != 0) {
|
||||
LOGV("cmp: FileName\n");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Convert the DOS date/time stamp into a UNIX time stamp.
|
||||
*/
|
||||
time_t ZipEntry::getModWhen(void) const
|
||||
{
|
||||
struct tm parts;
|
||||
|
||||
parts.tm_sec = (mCDE.mLastModFileTime & 0x001f) << 1;
|
||||
parts.tm_min = (mCDE.mLastModFileTime & 0x07e0) >> 5;
|
||||
parts.tm_hour = (mCDE.mLastModFileTime & 0xf800) >> 11;
|
||||
parts.tm_mday = (mCDE.mLastModFileDate & 0x001f);
|
||||
parts.tm_mon = ((mCDE.mLastModFileDate & 0x01e0) >> 5) -1;
|
||||
parts.tm_year = ((mCDE.mLastModFileDate & 0xfe00) >> 9) + 80;
|
||||
parts.tm_wday = parts.tm_yday = 0;
|
||||
parts.tm_isdst = -1; // DST info "not available"
|
||||
|
||||
return mktime(&parts);
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the CDE/LFH timestamp from UNIX time.
|
||||
*/
|
||||
void ZipEntry::setModWhen(time_t when)
|
||||
{
|
||||
#ifdef HAVE_LOCALTIME_R
|
||||
struct tm tmResult;
|
||||
#endif
|
||||
time_t even;
|
||||
unsigned short zdate, ztime;
|
||||
|
||||
struct tm* ptm;
|
||||
|
||||
/* round up to an even number of seconds */
|
||||
even = (time_t)(((unsigned long)(when) + 1) & (~1));
|
||||
|
||||
/* expand */
|
||||
#ifdef HAVE_LOCALTIME_R
|
||||
ptm = localtime_r(&even, &tmResult);
|
||||
#else
|
||||
ptm = localtime(&even);
|
||||
#endif
|
||||
|
||||
int year;
|
||||
year = ptm->tm_year;
|
||||
if (year < 80)
|
||||
year = 80;
|
||||
|
||||
zdate = (year - 80) << 9 | (ptm->tm_mon+1) << 5 | ptm->tm_mday;
|
||||
ztime = ptm->tm_hour << 11 | ptm->tm_min << 5 | ptm->tm_sec >> 1;
|
||||
|
||||
mCDE.mLastModFileTime = mLFH.mLastModFileTime = ztime;
|
||||
mCDE.mLastModFileDate = mLFH.mLastModFileDate = zdate;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* ===========================================================================
|
||||
* ZipEntry::LocalFileHeader
|
||||
* ===========================================================================
|
||||
*/
|
||||
|
||||
/*
|
||||
* Read a local file header.
|
||||
*
|
||||
* On entry, "fp" points to the signature at the start of the header.
|
||||
* On exit, "fp" points to the start of data.
|
||||
*/
|
||||
status_t ZipEntry::LocalFileHeader::read(FILE* fp)
|
||||
{
|
||||
status_t result = NO_ERROR;
|
||||
unsigned char buf[kLFHLen];
|
||||
|
||||
assert(mFileName == NULL);
|
||||
assert(mExtraField == NULL);
|
||||
|
||||
if (fread(buf, 1, kLFHLen, fp) != kLFHLen) {
|
||||
result = UNKNOWN_ERROR;
|
||||
goto bail;
|
||||
}
|
||||
|
||||
if (ZipEntry::getLongLE(&buf[0x00]) != kSignature) {
|
||||
LOGD("whoops: didn't find expected signature\n");
|
||||
result = UNKNOWN_ERROR;
|
||||
goto bail;
|
||||
}
|
||||
|
||||
mVersionToExtract = ZipEntry::getShortLE(&buf[0x04]);
|
||||
mGPBitFlag = ZipEntry::getShortLE(&buf[0x06]);
|
||||
mCompressionMethod = ZipEntry::getShortLE(&buf[0x08]);
|
||||
mLastModFileTime = ZipEntry::getShortLE(&buf[0x0a]);
|
||||
mLastModFileDate = ZipEntry::getShortLE(&buf[0x0c]);
|
||||
mCRC32 = ZipEntry::getLongLE(&buf[0x0e]);
|
||||
mCompressedSize = ZipEntry::getLongLE(&buf[0x12]);
|
||||
mUncompressedSize = ZipEntry::getLongLE(&buf[0x16]);
|
||||
mFileNameLength = ZipEntry::getShortLE(&buf[0x1a]);
|
||||
mExtraFieldLength = ZipEntry::getShortLE(&buf[0x1c]);
|
||||
|
||||
// TODO: validate sizes
|
||||
|
||||
/* grab filename */
|
||||
if (mFileNameLength != 0) {
|
||||
mFileName = new unsigned char[mFileNameLength+1];
|
||||
if (mFileName == NULL) {
|
||||
result = NO_MEMORY;
|
||||
goto bail;
|
||||
}
|
||||
if (fread(mFileName, 1, mFileNameLength, fp) != mFileNameLength) {
|
||||
result = UNKNOWN_ERROR;
|
||||
goto bail;
|
||||
}
|
||||
mFileName[mFileNameLength] = '\0';
|
||||
}
|
||||
|
||||
/* grab extra field */
|
||||
if (mExtraFieldLength != 0) {
|
||||
mExtraField = new unsigned char[mExtraFieldLength+1];
|
||||
if (mExtraField == NULL) {
|
||||
result = NO_MEMORY;
|
||||
goto bail;
|
||||
}
|
||||
if (fread(mExtraField, 1, mExtraFieldLength, fp) != mExtraFieldLength) {
|
||||
result = UNKNOWN_ERROR;
|
||||
goto bail;
|
||||
}
|
||||
mExtraField[mExtraFieldLength] = '\0';
|
||||
}
|
||||
|
||||
bail:
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* Write a local file header.
|
||||
*/
|
||||
status_t ZipEntry::LocalFileHeader::write(FILE* fp)
|
||||
{
|
||||
unsigned char buf[kLFHLen];
|
||||
|
||||
ZipEntry::putLongLE(&buf[0x00], kSignature);
|
||||
ZipEntry::putShortLE(&buf[0x04], mVersionToExtract);
|
||||
ZipEntry::putShortLE(&buf[0x06], mGPBitFlag);
|
||||
ZipEntry::putShortLE(&buf[0x08], mCompressionMethod);
|
||||
ZipEntry::putShortLE(&buf[0x0a], mLastModFileTime);
|
||||
ZipEntry::putShortLE(&buf[0x0c], mLastModFileDate);
|
||||
ZipEntry::putLongLE(&buf[0x0e], mCRC32);
|
||||
ZipEntry::putLongLE(&buf[0x12], mCompressedSize);
|
||||
ZipEntry::putLongLE(&buf[0x16], mUncompressedSize);
|
||||
ZipEntry::putShortLE(&buf[0x1a], mFileNameLength);
|
||||
ZipEntry::putShortLE(&buf[0x1c], mExtraFieldLength);
|
||||
|
||||
if (fwrite(buf, 1, kLFHLen, fp) != kLFHLen)
|
||||
return UNKNOWN_ERROR;
|
||||
|
||||
/* write filename */
|
||||
if (mFileNameLength != 0) {
|
||||
if (fwrite(mFileName, 1, mFileNameLength, fp) != mFileNameLength)
|
||||
return UNKNOWN_ERROR;
|
||||
}
|
||||
|
||||
/* write "extra field" */
|
||||
if (mExtraFieldLength != 0) {
|
||||
if (fwrite(mExtraField, 1, mExtraFieldLength, fp) != mExtraFieldLength)
|
||||
return UNKNOWN_ERROR;
|
||||
}
|
||||
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Dump the contents of a LocalFileHeader object.
|
||||
*/
|
||||
void ZipEntry::LocalFileHeader::dump(void) const
|
||||
{
|
||||
LOGD(" LocalFileHeader contents:\n");
|
||||
LOGD(" versToExt=%u gpBits=0x%04x compression=%u\n",
|
||||
mVersionToExtract, mGPBitFlag, mCompressionMethod);
|
||||
LOGD(" modTime=0x%04x modDate=0x%04x crc32=0x%08lx\n",
|
||||
mLastModFileTime, mLastModFileDate, mCRC32);
|
||||
LOGD(" compressedSize=%lu uncompressedSize=%lu\n",
|
||||
mCompressedSize, mUncompressedSize);
|
||||
LOGD(" filenameLen=%u extraLen=%u\n",
|
||||
mFileNameLength, mExtraFieldLength);
|
||||
if (mFileName != NULL)
|
||||
LOGD(" filename: '%s'\n", mFileName);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* ===========================================================================
|
||||
* ZipEntry::CentralDirEntry
|
||||
* ===========================================================================
|
||||
*/
|
||||
|
||||
/*
|
||||
* Read the central dir entry that appears next in the file.
|
||||
*
|
||||
* On entry, "fp" should be positioned on the signature bytes for the
|
||||
* entry. On exit, "fp" will point at the signature word for the next
|
||||
* entry or for the EOCD.
|
||||
*/
|
||||
status_t ZipEntry::CentralDirEntry::read(FILE* fp)
|
||||
{
|
||||
status_t result = NO_ERROR;
|
||||
unsigned char buf[kCDELen];
|
||||
|
||||
/* no re-use */
|
||||
assert(mFileName == NULL);
|
||||
assert(mExtraField == NULL);
|
||||
assert(mFileComment == NULL);
|
||||
|
||||
if (fread(buf, 1, kCDELen, fp) != kCDELen) {
|
||||
result = UNKNOWN_ERROR;
|
||||
goto bail;
|
||||
}
|
||||
|
||||
if (ZipEntry::getLongLE(&buf[0x00]) != kSignature) {
|
||||
LOGD("Whoops: didn't find expected signature\n");
|
||||
result = UNKNOWN_ERROR;
|
||||
goto bail;
|
||||
}
|
||||
|
||||
mVersionMadeBy = ZipEntry::getShortLE(&buf[0x04]);
|
||||
mVersionToExtract = ZipEntry::getShortLE(&buf[0x06]);
|
||||
mGPBitFlag = ZipEntry::getShortLE(&buf[0x08]);
|
||||
mCompressionMethod = ZipEntry::getShortLE(&buf[0x0a]);
|
||||
mLastModFileTime = ZipEntry::getShortLE(&buf[0x0c]);
|
||||
mLastModFileDate = ZipEntry::getShortLE(&buf[0x0e]);
|
||||
mCRC32 = ZipEntry::getLongLE(&buf[0x10]);
|
||||
mCompressedSize = ZipEntry::getLongLE(&buf[0x14]);
|
||||
mUncompressedSize = ZipEntry::getLongLE(&buf[0x18]);
|
||||
mFileNameLength = ZipEntry::getShortLE(&buf[0x1c]);
|
||||
mExtraFieldLength = ZipEntry::getShortLE(&buf[0x1e]);
|
||||
mFileCommentLength = ZipEntry::getShortLE(&buf[0x20]);
|
||||
mDiskNumberStart = ZipEntry::getShortLE(&buf[0x22]);
|
||||
mInternalAttrs = ZipEntry::getShortLE(&buf[0x24]);
|
||||
mExternalAttrs = ZipEntry::getLongLE(&buf[0x26]);
|
||||
mLocalHeaderRelOffset = ZipEntry::getLongLE(&buf[0x2a]);
|
||||
|
||||
// TODO: validate sizes and offsets
|
||||
|
||||
/* grab filename */
|
||||
if (mFileNameLength != 0) {
|
||||
mFileName = new unsigned char[mFileNameLength+1];
|
||||
if (mFileName == NULL) {
|
||||
result = NO_MEMORY;
|
||||
goto bail;
|
||||
}
|
||||
if (fread(mFileName, 1, mFileNameLength, fp) != mFileNameLength) {
|
||||
result = UNKNOWN_ERROR;
|
||||
goto bail;
|
||||
}
|
||||
mFileName[mFileNameLength] = '\0';
|
||||
}
|
||||
|
||||
/* read "extra field" */
|
||||
if (mExtraFieldLength != 0) {
|
||||
mExtraField = new unsigned char[mExtraFieldLength+1];
|
||||
if (mExtraField == NULL) {
|
||||
result = NO_MEMORY;
|
||||
goto bail;
|
||||
}
|
||||
if (fread(mExtraField, 1, mExtraFieldLength, fp) != mExtraFieldLength) {
|
||||
result = UNKNOWN_ERROR;
|
||||
goto bail;
|
||||
}
|
||||
mExtraField[mExtraFieldLength] = '\0';
|
||||
}
|
||||
|
||||
|
||||
/* grab comment, if any */
|
||||
if (mFileCommentLength != 0) {
|
||||
mFileComment = new unsigned char[mFileCommentLength+1];
|
||||
if (mFileComment == NULL) {
|
||||
result = NO_MEMORY;
|
||||
goto bail;
|
||||
}
|
||||
if (fread(mFileComment, 1, mFileCommentLength, fp) != mFileCommentLength)
|
||||
{
|
||||
result = UNKNOWN_ERROR;
|
||||
goto bail;
|
||||
}
|
||||
mFileComment[mFileCommentLength] = '\0';
|
||||
}
|
||||
|
||||
bail:
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* Write a central dir entry.
|
||||
*/
|
||||
status_t ZipEntry::CentralDirEntry::write(FILE* fp)
|
||||
{
|
||||
unsigned char buf[kCDELen];
|
||||
|
||||
ZipEntry::putLongLE(&buf[0x00], kSignature);
|
||||
ZipEntry::putShortLE(&buf[0x04], mVersionMadeBy);
|
||||
ZipEntry::putShortLE(&buf[0x06], mVersionToExtract);
|
||||
ZipEntry::putShortLE(&buf[0x08], mGPBitFlag);
|
||||
ZipEntry::putShortLE(&buf[0x0a], mCompressionMethod);
|
||||
ZipEntry::putShortLE(&buf[0x0c], mLastModFileTime);
|
||||
ZipEntry::putShortLE(&buf[0x0e], mLastModFileDate);
|
||||
ZipEntry::putLongLE(&buf[0x10], mCRC32);
|
||||
ZipEntry::putLongLE(&buf[0x14], mCompressedSize);
|
||||
ZipEntry::putLongLE(&buf[0x18], mUncompressedSize);
|
||||
ZipEntry::putShortLE(&buf[0x1c], mFileNameLength);
|
||||
ZipEntry::putShortLE(&buf[0x1e], mExtraFieldLength);
|
||||
ZipEntry::putShortLE(&buf[0x20], mFileCommentLength);
|
||||
ZipEntry::putShortLE(&buf[0x22], mDiskNumberStart);
|
||||
ZipEntry::putShortLE(&buf[0x24], mInternalAttrs);
|
||||
ZipEntry::putLongLE(&buf[0x26], mExternalAttrs);
|
||||
ZipEntry::putLongLE(&buf[0x2a], mLocalHeaderRelOffset);
|
||||
|
||||
if (fwrite(buf, 1, kCDELen, fp) != kCDELen)
|
||||
return UNKNOWN_ERROR;
|
||||
|
||||
/* write filename */
|
||||
if (mFileNameLength != 0) {
|
||||
if (fwrite(mFileName, 1, mFileNameLength, fp) != mFileNameLength)
|
||||
return UNKNOWN_ERROR;
|
||||
}
|
||||
|
||||
/* write "extra field" */
|
||||
if (mExtraFieldLength != 0) {
|
||||
if (fwrite(mExtraField, 1, mExtraFieldLength, fp) != mExtraFieldLength)
|
||||
return UNKNOWN_ERROR;
|
||||
}
|
||||
|
||||
/* write comment */
|
||||
if (mFileCommentLength != 0) {
|
||||
if (fwrite(mFileComment, 1, mFileCommentLength, fp) != mFileCommentLength)
|
||||
return UNKNOWN_ERROR;
|
||||
}
|
||||
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
/*
|
||||
* Dump the contents of a CentralDirEntry object.
|
||||
*/
|
||||
void ZipEntry::CentralDirEntry::dump(void) const
|
||||
{
|
||||
LOGD(" CentralDirEntry contents:\n");
|
||||
LOGD(" versMadeBy=%u versToExt=%u gpBits=0x%04x compression=%u\n",
|
||||
mVersionMadeBy, mVersionToExtract, mGPBitFlag, mCompressionMethod);
|
||||
LOGD(" modTime=0x%04x modDate=0x%04x crc32=0x%08lx\n",
|
||||
mLastModFileTime, mLastModFileDate, mCRC32);
|
||||
LOGD(" compressedSize=%lu uncompressedSize=%lu\n",
|
||||
mCompressedSize, mUncompressedSize);
|
||||
LOGD(" filenameLen=%u extraLen=%u commentLen=%u\n",
|
||||
mFileNameLength, mExtraFieldLength, mFileCommentLength);
|
||||
LOGD(" diskNumStart=%u intAttr=0x%04x extAttr=0x%08lx relOffset=%lu\n",
|
||||
mDiskNumberStart, mInternalAttrs, mExternalAttrs,
|
||||
mLocalHeaderRelOffset);
|
||||
|
||||
if (mFileName != NULL)
|
||||
LOGD(" filename: '%s'\n", mFileName);
|
||||
if (mFileComment != NULL)
|
||||
LOGD(" comment: '%s'\n", mFileComment);
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user