Back to index

lightning-sunbird  0.9+nobinonly
archivereader.cpp
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
00002 /* vim:set ts=2 sw=2 sts=2 et cindent: */
00003 /* ***** BEGIN LICENSE BLOCK *****
00004  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00005  *
00006  * The contents of this file are subject to the Mozilla Public License Version
00007  * 1.1 (the "License"); you may not use this file except in compliance with
00008  * the License. You may obtain a copy of the License at
00009  * http://www.mozilla.org/MPL/
00010  *
00011  * Software distributed under the License is distributed on an "AS IS" basis,
00012  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00013  * for the specific language governing rights and limitations under the
00014  * License.
00015  *
00016  * The Original Code is mozilla.org code.
00017  *
00018  * The Initial Developer of the Original Code is Google Inc.
00019  * Portions created by the Initial Developer are Copyright (C) 2005
00020  * the Initial Developer. All Rights Reserved.
00021  *
00022  * Contributor(s):
00023  *  Darin Fisher <darin@meer.net>
00024  *
00025  * Alternatively, the contents of this file may be used under the terms of
00026  * either the GNU General Public License Version 2 or later (the "GPL"), or
00027  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00028  * in which case the provisions of the GPL or the LGPL are applicable instead
00029  * of those above. If you wish to allow use of your version of this file only
00030  * under the terms of either the GPL or the LGPL, and not to allow others to
00031  * use your version of this file under the terms of the MPL, indicate your
00032  * decision by deleting the provisions above and replace them with the notice
00033  * and other provisions required by the GPL or the LGPL. If you do not delete
00034  * the provisions above, a recipient may use your version of this file under
00035  * the terms of any one of the MPL, the GPL or the LGPL.
00036  *
00037  * ***** END LICENSE BLOCK ***** */
00038 
00039 #include <string.h>
00040 #include <fcntl.h>
00041 #include "bzlib.h"
00042 #include "archivereader.h"
00043 #include "errors.h"
00044 
00045 #if defined(XP_UNIX)
00046 # include <sys/types.h>
00047 #elif defined(XP_WIN)
00048 # include <io.h>
00049 #endif
00050 
00051 int
00052 ArchiveReader::Open(const char *path)
00053 {
00054   if (mArchive)
00055     Close();
00056 
00057   mArchive = mar_open(path);
00058   if (!mArchive)
00059     return READ_ERROR;
00060 
00061   return OK;
00062 }
00063 
00064 void
00065 ArchiveReader::Close()
00066 {
00067   if (mArchive) {
00068     mar_close(mArchive);
00069     mArchive = NULL;
00070   }
00071 }
00072 
00073 int
00074 ArchiveReader::ExtractFile(const char *name, const char *dest)
00075 {
00076   const MarItem *item = mar_find_item(mArchive, name);
00077   if (!item)
00078     return READ_ERROR;
00079 
00080 #ifdef XP_WIN
00081   int fd = _open(dest, _O_BINARY|_O_CREAT|_O_TRUNC|_O_WRONLY, item->flags);
00082 #else
00083   int fd = creat(dest, item->flags);
00084 #endif
00085   if (fd == -1)
00086     return WRITE_ERROR;
00087 
00088   FILE *fp = fdopen(fd, "wb");
00089   if (!fp)
00090     return WRITE_ERROR;
00091 
00092   int rv = ExtractItemToStream(item, fp);
00093 
00094   fclose(fp);
00095   return rv;
00096 }
00097 
00098 int
00099 ArchiveReader::ExtractItemToStream(const MarItem *item, FILE *fp)
00100 {
00101   /* decompress the data chunk by chunk */
00102 
00103   char inbuf[BUFSIZ], outbuf[BUFSIZ];
00104   bz_stream strm;
00105   int offset, inlen, ret = OK;
00106 
00107   memset(&strm, 0, sizeof(strm));
00108   if (BZ2_bzDecompressInit(&strm, 0, 0) != BZ_OK)
00109     return UNEXPECTED_ERROR;
00110 
00111   offset = 0;
00112   for (;;) {
00113     if (!item->length) {
00114       ret = UNEXPECTED_ERROR;
00115       break;
00116     }
00117 
00118     if (offset < (int) item->length && strm.avail_in == 0) {
00119       inlen = mar_read(mArchive, item, offset, inbuf, BUFSIZ);
00120       if (inlen <= 0)
00121         return READ_ERROR;
00122       offset += inlen;
00123       strm.next_in = inbuf;
00124       strm.avail_in = inlen;
00125     }
00126 
00127     strm.next_out = outbuf;
00128     strm.avail_out = BUFSIZ;
00129 
00130     ret = BZ2_bzDecompress(&strm);
00131     if (ret != BZ_OK && ret != BZ_STREAM_END) {
00132       ret = UNEXPECTED_ERROR;
00133       break;
00134     }
00135 
00136     if (strm.avail_out < BUFSIZ) {
00137       if (fwrite(outbuf, BUFSIZ - strm.avail_out, 1, fp) != 1) {
00138         ret = WRITE_ERROR;
00139         break;
00140       }
00141     }
00142 
00143     if (ret == BZ_STREAM_END) {
00144       ret = OK;
00145       break;
00146     }
00147   }
00148 
00149   BZ2_bzDecompressEnd(&strm);
00150   return ret;
00151 }