Bug 847479 - Add a command line argument to szip to decompress an existing seekable stream. r=nfroyd
authorMike Hommey <mh+mozilla@glandium.org>
Wed, 06 Mar 2013 07:29:22 +0100
changeset 123912 2244aa90a7b32e82c0218dbf24aa0a8a5b6daf48
parent 123911 c6b328fb4f3ec9f8e0efec2f9a543a6f40b9d1b9
child 123913 4b2e14d6c70508ea9de28e34c1ccda87db37e141
push id1401
push userpastithas@mozilla.com
push dateThu, 07 Mar 2013 07:26:45 +0000
treeherderfx-team@ee4879719f78 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersnfroyd
bugs847479
milestone22.0a1
Bug 847479 - Add a command line argument to szip to decompress an existing seekable stream. r=nfroyd
mozglue/linker/Logging.h
mozglue/linker/Makefile.in
mozglue/linker/szip.cpp
--- a/mozglue/linker/Logging.h
+++ b/mozglue/linker/Logging.h
@@ -37,19 +37,23 @@
 #endif
 
 #ifdef MOZ_DEBUG_LINKER
 #define debug log
 #else
 #define debug(...)
 #endif
 
-#ifdef HAVE_64BIT_OS
+/* HAVE_64BIT_OS is not defined when building host tools, so use
+ * __SIZEOF_POINTER__ */
+#if defined(HAVE_64BIT_OS) || __SIZEOF_POINTER__ == 8
 #  define PRIxAddr "lx"
 #  define PRIxSize "lx"
 #  define PRIdSize "ld"
+#  define PRIuSize "lu"
 #else
 #  define PRIxAddr "x"
 #  define PRIxSize "x"
 #  define PRIdSize "d"
+#  define PRIuSize "u"
 #endif
 
 #endif /* Logging_h */
--- a/mozglue/linker/Makefile.in
+++ b/mozglue/linker/Makefile.in
@@ -17,16 +17,17 @@ STL_FLAGS =
 CPPSRCS = \
   Zip.cpp \
   $(NULL)
 
 HOST_PROGRAM = szip
 
 HOST_CPPSRCS = \
   szip.cpp \
+  SeekableZStream.cpp \
   $(NULL)
 
 HOST_LIBS = -lz
 
 CPPSRCS += \
   ElfLoader.cpp \
   CustomElf.cpp \
   Mappable.cpp \
--- a/mozglue/linker/szip.cpp
+++ b/mozglue/linker/szip.cpp
@@ -44,68 +44,65 @@ public:
 
 private:
   AutoCloseFD fd;
   bool writable;
 };
 
 static const size_t CHUNK = 16384;
 
-/* Generate a seekable compressed stream. */
-
-int main(int argc, char* argv[])
+/* Decompress a seekable compressed stream */
+int do_decompress(const char *name, FileBuffer &origBuf,
+                  const char *outName, FileBuffer &outBuf)
 {
-  if (argc != 3 || !argv[1] || !argv[2] || (strcmp(argv[1], argv[2]) == 0)) {
-    log("usage: %s file_to_compress out_file", argv[0]);
-    return 1;
-  }
-
-  FileBuffer origBuf;
-  if (!origBuf.Init(argv[1])) {
-    log("Couldn't open %s: %s", argv[1], strerror(errno));
+  size_t origSize = origBuf.GetLength();
+  if (origSize < sizeof(SeekableZStreamHeader)) {
+    log("%s is not a seekable zstream", name);
     return 1;
   }
 
-  struct stat st;
-  int ret = fstat(origBuf.getFd(), &st);
-  if (ret == -1) {
-    log("Couldn't stat %s: %s", argv[1], strerror(errno));
+  SeekableZStream zstream;
+  if (!zstream.Init(origBuf, origSize))
+    return 1;
+
+  size_t size = zstream.GetUncompressedSize();
+
+  /* Give enough room for the uncompressed data */
+  if (!outBuf.Resize(size)) {
+    log("Error resizing %s: %s", outName, strerror(errno));
     return 1;
   }
 
-  size_t origSize = st.st_size;
-  log("Size = %lu", origSize);
+  if (!zstream.Decompress(outBuf, 0, size))
+    return 1;
+
+  return 0;
+}
+
+/* Generate a seekable compressed stream. */
+int do_compress(const char *name, FileBuffer &origBuf,
+                const char *outName, FileBuffer &outBuf)
+{
+  size_t origSize = origBuf.GetLength();
   if (origSize == 0) {
-    log("Won't compress %s: it's empty", argv[1]);
+    log("Won't compress %s: it's empty", name);
     return 1;
   }
-
-  /* Mmap the original file */
-  if (!origBuf.Resize(origSize)) {
-    log("Couldn't mmap %s: %s", argv[1], strerror(errno));
-    return 1;
-  }
-
-  /* Create the compressed file */
-  FileBuffer outBuf;
-  if (!outBuf.Init(argv[2], true)) {
-    log("Couldn't open %s: %s", argv[2], strerror(errno));
-    return 1;
-  }
+  log("Size = %" PRIuSize, origSize);
 
   /* Expected total number of chunks */
   size_t nChunks = ((origSize + CHUNK - 1) / CHUNK);
 
   /* The first chunk is going to be stored after the header and the offset
    * table */
   size_t offset = sizeof(SeekableZStreamHeader) + nChunks * sizeof(uint32_t);
 
   /* Give enough room for the header and the offset table, and map them */
   if (!outBuf.Resize(origSize)) {
-    log("Couldn't mmap %s: %s", argv[2], strerror(errno));
+    log("Couldn't mmap %s: %s", outName, strerror(errno));
     return 1;
   }
 
   SeekableZStreamHeader *header = new (outBuf) SeekableZStreamHeader;
   le_uint32 *entry = reinterpret_cast<le_uint32 *>(&header[1]);
 
   /* Initialize header */
   header->chunkSize = CHUNK;
@@ -119,17 +116,17 @@ int main(int argc, char* argv[])
 
   Bytef *origData = static_cast<Bytef*>(origBuf);
   size_t avail = 0;
   size_t size = origSize;
   while (size) {
     avail = std::min(size, CHUNK);
 
     /* Compress chunk */
-    ret = deflateInit(&zStream, 9);
+    int ret = deflateInit(&zStream, 9);
     MOZ_ASSERT(ret == Z_OK);
     zStream.avail_in = avail;
     zStream.next_in = origData;
     ret = deflate(&zStream, Z_FINISH);
     MOZ_ASSERT(ret == Z_STREAM_END);
     ret = deflateEnd(&zStream);
     MOZ_ASSERT(ret == Z_OK);
     MOZ_ASSERT(zStream.avail_out > 0);
@@ -143,17 +140,66 @@ int main(int argc, char* argv[])
 
     /* Prepare for next iteration */
     size -= avail;
     origData += avail;
     offset += len;
   }
   header->lastChunkSize = avail;
   if (!outBuf.Resize(offset)) {
-    log("Error resizing %s: %s", argv[2], strerror(errno));
+    log("Error resizing %s: %s", outName, strerror(errno));
     return 1;
   }
 
   MOZ_ASSERT(header->nChunks == nChunks);
-  log("Compressed size is %lu", offset);
+  log("Compressed size is %" PRIuSize, offset);
 
   return 0;
 }
+
+int main(int argc, char* argv[])
+{
+  int (*func)(const char *, FileBuffer &,
+              const char *, FileBuffer &) = do_compress;
+  char **firstArg = &argv[1];
+
+  if ((argc > 1) && strcmp(argv[1], "-d") == 0) {
+    func = do_decompress;
+    firstArg++;
+    argc--;
+  }
+
+  if (argc != 3 || !firstArg[0] || !firstArg[1] ||
+      (strcmp(firstArg[0], firstArg[1]) == 0)) {
+    log("usage: %s [-d] in_file out_file", argv[0]);
+    return 1;
+  }
+
+  FileBuffer origBuf;
+  if (!origBuf.Init(firstArg[0])) {
+    log("Couldn't open %s: %s", firstArg[0], strerror(errno));
+    return 1;
+  }
+
+  struct stat st;
+  int ret = fstat(origBuf.getFd(), &st);
+  if (ret == -1) {
+    log("Couldn't stat %s: %s", firstArg[0], strerror(errno));
+    return 1;
+  }
+
+  size_t origSize = st.st_size;
+
+  /* Mmap the original file */
+  if (!origBuf.Resize(origSize)) {
+    log("Couldn't mmap %s: %s", firstArg[0], strerror(errno));
+    return 1;
+  }
+
+  /* Create the compressed file */
+  FileBuffer outBuf;
+  if (!outBuf.Init(firstArg[1], true)) {
+    log("Couldn't open %s: %s", firstArg[1], strerror(errno));
+    return 1;
+  }
+
+  return func(firstArg[0], origBuf, firstArg[1], outBuf);
+}