mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 446464: File permissions are not preserved when zipping with zipwriter. r=biesi
This commit is contained in:
parent
4998d614a8
commit
c801ea2744
@ -45,8 +45,15 @@
|
||||
#include "nsIZipReader.h"
|
||||
#include "nsAutoPtr.h"
|
||||
|
||||
#define ZIP_ATTRS_FILE 0
|
||||
#define ZIP_ATTRS_DIRECTORY 16
|
||||
// High word is S_IFREG, low word is DOS file attribute
|
||||
#define ZIP_ATTRS_FILE 0x80000000
|
||||
// High word is S_IFDIR, low word is DOS dir attribute
|
||||
#define ZIP_ATTRS_DIRECTORY 0x40000010
|
||||
#define PERMISSIONS_FILE 0644
|
||||
#define PERMISSIONS_DIR 0755
|
||||
|
||||
// Combine file type attributes with unix style permissions
|
||||
#define ZIP_ATTRS(p, a) ((p & 0xfff) << 16) | a
|
||||
|
||||
class nsZipHeader : public nsIZipEntry
|
||||
{
|
||||
@ -61,8 +68,8 @@ public:
|
||||
mEAttr(0),
|
||||
mOffset(0),
|
||||
mFieldLength(0),
|
||||
mVersionMade(20),
|
||||
mVersionNeeded(20),
|
||||
mVersionMade(0x0300 + 23), // Generated on Unix by v2.3 (matches infozip)
|
||||
mVersionNeeded(20), // Requires v2.0 to extract
|
||||
mFlags(0),
|
||||
mMethod(0),
|
||||
mTime(0),
|
||||
|
@ -357,6 +357,7 @@ NS_IMETHODIMP nsZipWriter::AddEntryDirectory(const nsACString & aZipEntry,
|
||||
item.mOperation = OPERATION_ADD;
|
||||
item.mZipEntry = aZipEntry;
|
||||
item.mModTime = aModTime;
|
||||
item.mPermissions = PERMISSIONS_DIR;
|
||||
if (!mQueue.AppendElement(item))
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
return NS_OK;
|
||||
@ -364,7 +365,7 @@ NS_IMETHODIMP nsZipWriter::AddEntryDirectory(const nsACString & aZipEntry,
|
||||
|
||||
if (mInQueue)
|
||||
return NS_ERROR_IN_PROGRESS;
|
||||
return InternalAddEntryDirectory(aZipEntry, aModTime);
|
||||
return InternalAddEntryDirectory(aZipEntry, aModTime, PERMISSIONS_DIR);
|
||||
}
|
||||
|
||||
/* void addEntryFile (in AUTF8String aZipEntry, in PRInt32 aCompression,
|
||||
@ -408,8 +409,12 @@ NS_IMETHODIMP nsZipWriter::AddEntryFile(const nsACString & aZipEntry,
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
modtime *= PR_USEC_PER_MSEC;
|
||||
|
||||
PRUint32 permissions;
|
||||
rv = aFile->GetPermissions(&permissions);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (isdir)
|
||||
return InternalAddEntryDirectory(aZipEntry, modtime);
|
||||
return InternalAddEntryDirectory(aZipEntry, modtime, permissions);
|
||||
|
||||
if (mEntryHash.Get(aZipEntry, nsnull))
|
||||
return NS_ERROR_FILE_ALREADY_EXISTS;
|
||||
@ -420,7 +425,7 @@ NS_IMETHODIMP nsZipWriter::AddEntryFile(const nsACString & aZipEntry,
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = AddEntryStream(aZipEntry, modtime, aCompression, inputStream,
|
||||
PR_FALSE);
|
||||
PR_FALSE, permissions);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return inputStream->Close();
|
||||
@ -445,6 +450,7 @@ NS_IMETHODIMP nsZipWriter::AddEntryChannel(const nsACString & aZipEntry,
|
||||
item.mZipEntry = aZipEntry;
|
||||
item.mModTime = aModTime;
|
||||
item.mCompression = aCompression;
|
||||
item.mPermissions = PERMISSIONS_FILE;
|
||||
item.mChannel = aChannel;
|
||||
if (!mQueue.AppendElement(item))
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
@ -461,7 +467,7 @@ NS_IMETHODIMP nsZipWriter::AddEntryChannel(const nsACString & aZipEntry,
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = AddEntryStream(aZipEntry, aModTime, aCompression, inputStream,
|
||||
PR_FALSE);
|
||||
PR_FALSE, PERMISSIONS_FILE);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return inputStream->Close();
|
||||
@ -475,6 +481,20 @@ NS_IMETHODIMP nsZipWriter::AddEntryStream(const nsACString & aZipEntry,
|
||||
PRInt32 aCompression,
|
||||
nsIInputStream *aStream,
|
||||
PRBool aQueue)
|
||||
{
|
||||
return AddEntryStream(aZipEntry, aModTime, aCompression, aStream, aQueue,
|
||||
PERMISSIONS_FILE);
|
||||
}
|
||||
|
||||
/* void addEntryStream (in AUTF8String aZipEntry, in PRTime aModTime,
|
||||
* in PRInt32 aCompression, in nsIInputStream aStream,
|
||||
* in boolean aQueue, in unsigned long aPermissions); */
|
||||
nsresult nsZipWriter::AddEntryStream(const nsACString & aZipEntry,
|
||||
PRTime aModTime,
|
||||
PRInt32 aCompression,
|
||||
nsIInputStream *aStream,
|
||||
PRBool aQueue,
|
||||
PRUint32 aPermissions)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aStream);
|
||||
if (!mStream)
|
||||
@ -486,6 +506,7 @@ NS_IMETHODIMP nsZipWriter::AddEntryStream(const nsACString & aZipEntry,
|
||||
item.mZipEntry = aZipEntry;
|
||||
item.mModTime = aModTime;
|
||||
item.mCompression = aCompression;
|
||||
item.mPermissions = aPermissions;
|
||||
item.mStream = aStream;
|
||||
if (!mQueue.AppendElement(item))
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
@ -499,7 +520,8 @@ NS_IMETHODIMP nsZipWriter::AddEntryStream(const nsACString & aZipEntry,
|
||||
|
||||
nsRefPtr<nsZipHeader> header = new nsZipHeader();
|
||||
NS_ENSURE_TRUE(header, NS_ERROR_OUT_OF_MEMORY);
|
||||
header->Init(aZipEntry, aModTime, ZIP_ATTRS_FILE, mCDSOffset);
|
||||
header->Init(aZipEntry, aModTime, ZIP_ATTRS(aPermissions, ZIP_ATTRS_FILE),
|
||||
mCDSOffset);
|
||||
nsresult rv = header->WriteFileHeader(mStream);
|
||||
if (NS_FAILED(rv)) {
|
||||
SeekCDS();
|
||||
@ -742,18 +764,21 @@ NS_IMETHODIMP nsZipWriter::OnStopRequest(nsIRequest *aRequest,
|
||||
}
|
||||
|
||||
nsresult nsZipWriter::InternalAddEntryDirectory(const nsACString & aZipEntry,
|
||||
PRTime aModTime)
|
||||
PRTime aModTime,
|
||||
PRUint32 aPermissions)
|
||||
{
|
||||
nsRefPtr<nsZipHeader> header = new nsZipHeader();
|
||||
NS_ENSURE_TRUE(header, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
PRUint32 zipAttributes = ZIP_ATTRS(aPermissions, ZIP_ATTRS_DIRECTORY);
|
||||
|
||||
if (aZipEntry.Last() != '/') {
|
||||
nsCString dirPath;
|
||||
dirPath.Assign(aZipEntry + NS_LITERAL_CSTRING("/"));
|
||||
header->Init(dirPath, aModTime, ZIP_ATTRS_DIRECTORY, mCDSOffset);
|
||||
header->Init(dirPath, aModTime, zipAttributes, mCDSOffset);
|
||||
}
|
||||
else
|
||||
header->Init(aZipEntry, aModTime, ZIP_ATTRS_DIRECTORY, mCDSOffset);
|
||||
header->Init(aZipEntry, aModTime, zipAttributes, mCDSOffset);
|
||||
|
||||
if (mEntryHash.Get(header->mName, nsnull))
|
||||
return NS_ERROR_FILE_ALREADY_EXISTS;
|
||||
@ -860,6 +885,9 @@ inline nsresult nsZipWriter::BeginProcessingAddition(nsZipQueueItem* aItem,
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
aItem->mModTime *= PR_USEC_PER_MSEC;
|
||||
|
||||
rv = aItem->mFile->GetPermissions(&aItem->mPermissions);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (!isdir) {
|
||||
// Set up for fall through to stream reader
|
||||
rv = NS_NewLocalFileInputStream(getter_AddRefs(aItem->mStream),
|
||||
@ -869,11 +897,13 @@ inline nsresult nsZipWriter::BeginProcessingAddition(nsZipQueueItem* aItem,
|
||||
// If a dir then this will fall through to the plain dir addition
|
||||
}
|
||||
|
||||
PRUint32 zipAttributes = ZIP_ATTRS(aItem->mPermissions, ZIP_ATTRS_FILE);
|
||||
|
||||
if (aItem->mStream) {
|
||||
nsRefPtr<nsZipHeader> header = new nsZipHeader();
|
||||
NS_ENSURE_TRUE(header, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
header->Init(aItem->mZipEntry, aItem->mModTime, ZIP_ATTRS_FILE,
|
||||
header->Init(aItem->mZipEntry, aItem->mModTime, zipAttributes,
|
||||
mCDSOffset);
|
||||
nsresult rv = header->WriteFileHeader(mStream);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
@ -897,7 +927,7 @@ inline nsresult nsZipWriter::BeginProcessingAddition(nsZipQueueItem* aItem,
|
||||
nsRefPtr<nsZipHeader> header = new nsZipHeader();
|
||||
NS_ENSURE_TRUE(header, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
header->Init(aItem->mZipEntry, aItem->mModTime, ZIP_ATTRS_FILE,
|
||||
header->Init(aItem->mZipEntry, aItem->mModTime, zipAttributes,
|
||||
mCDSOffset);
|
||||
|
||||
nsRefPtr<nsZipDataStream> stream = new nsZipDataStream();
|
||||
@ -912,7 +942,8 @@ inline nsresult nsZipWriter::BeginProcessingAddition(nsZipQueueItem* aItem,
|
||||
|
||||
// Must be plain directory addition
|
||||
*complete = PR_TRUE;
|
||||
return InternalAddEntryDirectory(aItem->mZipEntry, aItem->mModTime);
|
||||
return InternalAddEntryDirectory(aItem->mZipEntry, aItem->mModTime,
|
||||
aItem->mPermissions);
|
||||
}
|
||||
|
||||
inline nsresult nsZipWriter::BeginProcessingRemoval(PRInt32 aPos)
|
||||
|
@ -67,6 +67,7 @@ public:
|
||||
nsCOMPtr<nsIInputStream> mStream;
|
||||
PRTime mModTime;
|
||||
PRInt32 mCompression;
|
||||
PRUint32 mPermissions;
|
||||
};
|
||||
|
||||
class nsZipWriter : public nsIZipWriter,
|
||||
@ -100,9 +101,12 @@ private:
|
||||
void Cleanup();
|
||||
nsresult ReadFile(nsIFile *aFile);
|
||||
nsresult InternalAddEntryDirectory(const nsACString & aZipEntry,
|
||||
PRTime aModTime);
|
||||
PRTime aModTime, PRUint32 aPermissions);
|
||||
nsresult BeginProcessingAddition(nsZipQueueItem* aItem, PRBool* complete);
|
||||
nsresult BeginProcessingRemoval(PRInt32 aPos);
|
||||
nsresult AddEntryStream(const nsACString & aZipEntry, PRTime aModTime,
|
||||
PRInt32 aCompression, nsIInputStream *aStream,
|
||||
PRBool aQueue, PRUint32 aPermissions);
|
||||
void BeginProcessingNextItem();
|
||||
void FinishQueue(nsresult aStatus);
|
||||
};
|
||||
|
@ -30,23 +30,8 @@ function AddToZip(zipWriter, path, file)
|
||||
|
||||
function RecursivelyZipDirectory(bundle)
|
||||
{
|
||||
// create directory service
|
||||
var dirUtils = Components.classes["@mozilla.org/file/directory_service;1"]
|
||||
.createInstance(Components.interfaces.nsIProperties);
|
||||
|
||||
// get the temp dir, where our temporary zip attachments can be stored
|
||||
var tempFile = dirUtils.get("TmpD", Components.interfaces.nsIFile).clone();
|
||||
|
||||
// create unique file there
|
||||
tempFile.append(bundle.leafName + ".zip");
|
||||
tempFile.createUnique(Components.interfaces.nsIFile.NORMAL_FILE_TYPE,
|
||||
0600);
|
||||
|
||||
zipW.open(tempFile, PR_RDWR | PR_CREATE_FILE | PR_TRUNCATE);
|
||||
|
||||
zipW.open(tmpFile, PR_RDWR | PR_CREATE_FILE | PR_TRUNCATE);
|
||||
AddToZip(zipW, "", bundle);
|
||||
|
||||
// we're done.
|
||||
zipW.close();
|
||||
}
|
||||
|
||||
|
106
modules/libjar/zipwriter/test/unit/test_zippermissions.js
Normal file
106
modules/libjar/zipwriter/test/unit/test_zippermissions.js
Normal file
@ -0,0 +1,106 @@
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (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.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Zip Writer Component.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Dave Townsend <dtownsend@oxymoronical.com>.
|
||||
*
|
||||
* Portions created by the Initial Developer are Copyright (C) 2008
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
const DATA = "ZIP WRITER TEST DATA";
|
||||
|
||||
var TESTS = [];
|
||||
|
||||
function build_tests() {
|
||||
var id = 0;
|
||||
|
||||
// Minimum mode is 0400
|
||||
for (let u = 4; u <= 7; u++) {
|
||||
for (let g = 0; g <= 7; g++) {
|
||||
for (let o = 0; o <= 7; o++) {
|
||||
TESTS[id] = {
|
||||
name: "test" + u + g + o,
|
||||
permission: (u << 6) + (g << 3) + o
|
||||
};
|
||||
id++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function run_test() {
|
||||
build_tests();
|
||||
|
||||
var foStream = Cc["@mozilla.org/network/file-output-stream;1"].
|
||||
createInstance(Ci.nsIFileOutputStream);
|
||||
|
||||
var tmp = tmpDir.clone();
|
||||
tmp.append("temp-permissions");
|
||||
tmp.createUnique(Ci.nsILocalFile.DIRECTORY_TYPE, 0755);
|
||||
|
||||
var file = tmp.clone();
|
||||
file.append("tempfile");
|
||||
|
||||
zipW.open(tmpFile, PR_RDWR | PR_CREATE_FILE | PR_TRUNCATE);
|
||||
for (let i = 0; i < TESTS.length; i++) {
|
||||
// Open the file with the permissions to match how the zipreader extracts
|
||||
// This obeys the umask
|
||||
foStream.init(file, 0x02 | 0x08 | 0x20, TESTS[i].permission, 0);
|
||||
foStream.close();
|
||||
|
||||
// umask may have altered the permissions so test against what they really were.
|
||||
// This reduces the coverage of the test but there isn't much we can do
|
||||
var perm = file.permissions & 0xfff;
|
||||
if (TESTS[i].permission != perm) {
|
||||
dump("File permissions for " + TESTS[i].name + " were " + perm.toString(8) + "\n");
|
||||
TESTS[i].permission = perm;
|
||||
}
|
||||
|
||||
zipW.addEntryFile(TESTS[i].name, Ci.nsIZipWriter.COMPRESSION_NONE, file, false);
|
||||
file.permissions = 0600;
|
||||
file.remove(true);
|
||||
}
|
||||
zipW.close();
|
||||
|
||||
zipR = new ZipReader(tmpFile);
|
||||
for (let i = 0; i < TESTS.length; i++) {
|
||||
zipR.extract(TESTS[i].name, file);
|
||||
dump("Testing file permissions for " + TESTS[i].name + "\n");
|
||||
do_check_eq(file.permissions & 0xfff, TESTS[i].permission);
|
||||
do_check_false(file.isDirectory());
|
||||
file.permissions = 0600;
|
||||
file.remove(true);
|
||||
}
|
||||
zipR.close();
|
||||
|
||||
tmp.remove(true);
|
||||
}
|
Loading…
Reference in New Issue
Block a user