1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/xpcom/base/nsGZFileWriter.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,98 @@ 1.4 +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 1.5 +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ 1.6 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.7 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.8 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.9 + 1.10 +#include "nsGZFileWriter.h" 1.11 +#include "nsIFile.h" 1.12 +#include "nsString.h" 1.13 +#include "zlib.h" 1.14 + 1.15 +#ifdef XP_WIN 1.16 +#include <io.h> 1.17 +#define _dup dup 1.18 +#else 1.19 +#include <unistd.h> 1.20 +#endif 1.21 + 1.22 +NS_IMPL_ISUPPORTS(nsGZFileWriter, nsIGZFileWriter) 1.23 + 1.24 +nsGZFileWriter::nsGZFileWriter() 1.25 + : mInitialized(false) 1.26 + , mFinished(false) 1.27 +{} 1.28 + 1.29 +nsGZFileWriter::~nsGZFileWriter() 1.30 +{ 1.31 + if (mInitialized && !mFinished) { 1.32 + Finish(); 1.33 + } 1.34 +} 1.35 + 1.36 +NS_IMETHODIMP 1.37 +nsGZFileWriter::Init(nsIFile* aFile) 1.38 +{ 1.39 + if (NS_WARN_IF(mInitialized) || 1.40 + NS_WARN_IF(mFinished)) 1.41 + return NS_ERROR_FAILURE; 1.42 + 1.43 + // Get a FILE out of our nsIFile. Convert that into a file descriptor which 1.44 + // gzip can own. Then close our FILE, leaving only gzip's fd open. 1.45 + 1.46 + FILE* file; 1.47 + nsresult rv = aFile->OpenANSIFileDesc("wb", &file); 1.48 + if (NS_WARN_IF(NS_FAILED(rv))) 1.49 + return rv; 1.50 + 1.51 + mGZFile = gzdopen(dup(fileno(file)), "wb"); 1.52 + fclose(file); 1.53 + 1.54 + // gzdopen returns nullptr on error. 1.55 + if (NS_WARN_IF(!mGZFile)) 1.56 + return NS_ERROR_FAILURE; 1.57 + 1.58 + mInitialized = true; 1.59 + 1.60 + return NS_OK; 1.61 +} 1.62 + 1.63 +NS_IMETHODIMP 1.64 +nsGZFileWriter::Write(const nsACString& aStr) 1.65 +{ 1.66 + if (NS_WARN_IF(!mInitialized) || 1.67 + NS_WARN_IF(mFinished)) 1.68 + return NS_ERROR_FAILURE; 1.69 + 1.70 + // gzwrite uses a return value of 0 to indicate failure. Otherwise, it 1.71 + // returns the number of uncompressed bytes written. To ensure we can 1.72 + // distinguish between success and failure, don't call gzwrite when we have 0 1.73 + // bytes to write. 1.74 + if (aStr.IsEmpty()) { 1.75 + return NS_OK; 1.76 + } 1.77 + 1.78 + // gzwrite never does a short write -- that is, the return value should 1.79 + // always be either 0 or aStr.Length(), and we shouldn't have to call it 1.80 + // multiple times in order to get it to read the whole buffer. 1.81 + int rv = gzwrite(mGZFile, aStr.BeginReading(), aStr.Length()); 1.82 + if (NS_WARN_IF(rv != static_cast<int>(aStr.Length()))) 1.83 + return NS_ERROR_FAILURE; 1.84 + 1.85 + return NS_OK; 1.86 +} 1.87 + 1.88 +NS_IMETHODIMP 1.89 +nsGZFileWriter::Finish() 1.90 +{ 1.91 + if (NS_WARN_IF(!mInitialized) || 1.92 + NS_WARN_IF(mFinished)) 1.93 + return NS_ERROR_FAILURE; 1.94 + 1.95 + mFinished = true; 1.96 + gzclose(mGZFile); 1.97 + 1.98 + // Ignore errors from gzclose; it's not like there's anything we can do about 1.99 + // it, at this point! 1.100 + return NS_OK; 1.101 +}