mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-01-13 15:34:01 +00:00
Bug 1022816 - OS.File will now be able to change the readOnly, hidden, and system file attributes on Windows. r=paolo
This commit is contained in:
parent
a552b87f85
commit
4b15c2aa09
@ -727,9 +727,11 @@ static const dom::ConstantSpec gWinProperties[] =
|
||||
// CreateFile attributes
|
||||
INT_CONSTANT(FILE_ATTRIBUTE_ARCHIVE),
|
||||
INT_CONSTANT(FILE_ATTRIBUTE_DIRECTORY),
|
||||
INT_CONSTANT(FILE_ATTRIBUTE_HIDDEN),
|
||||
INT_CONSTANT(FILE_ATTRIBUTE_NORMAL),
|
||||
INT_CONSTANT(FILE_ATTRIBUTE_READONLY),
|
||||
INT_CONSTANT(FILE_ATTRIBUTE_REPARSE_POINT),
|
||||
INT_CONSTANT(FILE_ATTRIBUTE_SYSTEM),
|
||||
INT_CONSTANT(FILE_ATTRIBUTE_TEMPORARY),
|
||||
INT_CONSTANT(FILE_FLAG_BACKUP_SEMANTICS),
|
||||
|
||||
|
@ -210,7 +210,8 @@ exports.Error = OSError;
|
||||
*/
|
||||
let AbstractInfo = function AbstractInfo(path, isDir, isSymLink, size,
|
||||
winBirthDate,
|
||||
lastAccessDate, lastWriteDate) {
|
||||
lastAccessDate, lastWriteDate,
|
||||
winAttributes) {
|
||||
this._path = path;
|
||||
this._isDir = isDir;
|
||||
this._isSymLink = isSymLink;
|
||||
@ -218,6 +219,7 @@ let AbstractInfo = function AbstractInfo(path, isDir, isSymLink, size,
|
||||
this._winBirthDate = winBirthDate;
|
||||
this._lastAccessDate = lastAccessDate;
|
||||
this._lastModificationDate = lastWriteDate;
|
||||
this._winAttributes = winAttributes;
|
||||
};
|
||||
|
||||
AbstractInfo.prototype = {
|
||||
@ -285,6 +287,15 @@ AbstractInfo.prototype = {
|
||||
*/
|
||||
get lastModificationDate() {
|
||||
return this._lastModificationDate;
|
||||
},
|
||||
/**
|
||||
* The Object with following boolean properties of this file.
|
||||
* {readOnly, system, hidden}
|
||||
*
|
||||
* @type {object}
|
||||
*/
|
||||
get winAttributes() {
|
||||
return this._winAttributes;
|
||||
}
|
||||
};
|
||||
exports.AbstractInfo = AbstractInfo;
|
||||
|
@ -236,10 +236,19 @@
|
||||
|
||||
/**
|
||||
* Set the file's access permission bits.
|
||||
* Not implemented for Windows (bug 1022816).
|
||||
*/
|
||||
File.prototype.setPermissions = function setPermissions(options = {}) {
|
||||
// do nothing
|
||||
if (!("winAttributes" in options)) {
|
||||
return;
|
||||
}
|
||||
let oldAttributes = WinFile.GetFileAttributes(this._path);
|
||||
if (oldAttributes == Const.INVALID_FILE_ATTRIBUTES) {
|
||||
throw new File.Error("setPermissions", ctypes.winLastError, this._path);
|
||||
}
|
||||
let newAttributes = toFileAttributes(options.winAttributes, oldAttributes);
|
||||
throw_on_zero("setPermissions",
|
||||
WinFile.SetFileAttributes(this._path, newAttributes),
|
||||
this._path);
|
||||
};
|
||||
|
||||
/**
|
||||
@ -904,9 +913,14 @@
|
||||
|
||||
let value = ctypes.UInt64.join(stat.nFileSizeHigh, stat.nFileSizeLow);
|
||||
let size = Type.uint64_t.importFromC(value);
|
||||
let winAttributes = {
|
||||
readOnly: !!(stat.dwFileAttributes & Const.FILE_ATTRIBUTE_READONLY),
|
||||
system: !!(stat.dwFileAttributes & Const.FILE_ATTRIBUTE_SYSTEM),
|
||||
hidden: !!(stat.dwFileAttributes & Const.FILE_ATTRIBUTE_HIDDEN),
|
||||
};
|
||||
|
||||
SysAll.AbstractInfo.call(this, path, isDir, isSymLink, size,
|
||||
winBirthDate, lastAccessDate, lastWriteDate);
|
||||
winBirthDate, lastAccessDate, lastWriteDate, winAttributes);
|
||||
};
|
||||
File.Info.prototype = Object.create(SysAll.AbstractInfo.prototype);
|
||||
|
||||
@ -963,10 +977,19 @@
|
||||
|
||||
/**
|
||||
* Set the file's access permission bits.
|
||||
* Not implemented for Windows (bug 1022816).
|
||||
*/
|
||||
File.setPermissions = function setPermissions(path, options = {}) {
|
||||
// do nothing
|
||||
if (!("winAttributes" in options)) {
|
||||
return;
|
||||
}
|
||||
let oldAttributes = WinFile.GetFileAttributes(path);
|
||||
if (oldAttributes == Const.INVALID_FILE_ATTRIBUTES) {
|
||||
throw new File.Error("setPermissions", ctypes.winLastError, path);
|
||||
}
|
||||
let newAttributes = toFileAttributes(options.winAttributes, oldAttributes);
|
||||
throw_on_zero("setPermissions",
|
||||
WinFile.SetFileAttributes(path, newAttributes),
|
||||
path);
|
||||
};
|
||||
|
||||
/**
|
||||
@ -1175,6 +1198,34 @@
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper used by both versions of setPermissions
|
||||
*/
|
||||
function toFileAttributes(winAttributes, oldDwAttrs) {
|
||||
if ("readOnly" in winAttributes) {
|
||||
if (winAttributes.readOnly) {
|
||||
oldDwAttrs |= Const.FILE_ATTRIBUTE_READONLY;
|
||||
} else {
|
||||
oldDwAttrs &= ~Const.FILE_ATTRIBUTE_READONLY;
|
||||
}
|
||||
}
|
||||
if ("system" in winAttributes) {
|
||||
if (winAttributes.system) {
|
||||
oldDwAttrs |= Const.FILE_ATTRIBUTE_SYSTEM;
|
||||
} else {
|
||||
oldDwAttrs &= ~Const.FILE_ATTRIBUTE_SYSTEM;
|
||||
}
|
||||
}
|
||||
if ("hidden" in winAttributes) {
|
||||
if (winAttributes.hidden) {
|
||||
oldDwAttrs |= Const.FILE_ATTRIBUTE_HIDDEN;
|
||||
} else {
|
||||
oldDwAttrs &= ~Const.FILE_ATTRIBUTE_HIDDEN;
|
||||
}
|
||||
}
|
||||
return oldDwAttrs;
|
||||
}
|
||||
|
||||
File.Win = exports.OS.Win.File;
|
||||
File.Error = SysAll.Error;
|
||||
exports.OS.File = File;
|
||||
|
@ -0,0 +1,114 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
/**
|
||||
* A test to ensure that OS.File.setPermissions and
|
||||
* OS.File.prototype.setPermissions are all working correctly.
|
||||
* (see bug 1022816)
|
||||
* The manifest tests on Windows.
|
||||
*/
|
||||
|
||||
// Sequence of setPermission parameters.
|
||||
let testSequence = [
|
||||
[ { winAttributes: { readOnly: true, system: true, hidden: true } },
|
||||
{ readOnly: true, system: true, hidden: true } ],
|
||||
[ { winAttributes: { readOnly: false } },
|
||||
{ readOnly: false, system: true, hidden: true } ],
|
||||
[ { winAttributes: { system: false } },
|
||||
{ readOnly: false, system: false, hidden: true } ],
|
||||
[ { winAttributes: { hidden: false } },
|
||||
{ readOnly: false, system: false, hidden: false } ],
|
||||
[ { winAttributes: {readOnly: true, system: false, hidden: false} },
|
||||
{ readOnly: true, system: false, hidden: false } ],
|
||||
[ { winAttributes: {readOnly: false, system: true, hidden: false} },
|
||||
{ readOnly: false, system: true, hidden: false } ],
|
||||
[ { winAttributes: {readOnly: false, system: false, hidden: true} },
|
||||
{ readOnly: false, system: false, hidden: true } ],
|
||||
];
|
||||
|
||||
// Test application to paths.
|
||||
add_task(function* test_path_setPermissions() {
|
||||
let path = OS.Path.join(OS.Constants.Path.tmpDir,
|
||||
"test_osfile_win_async_setPermissions_path.tmp");
|
||||
yield OS.File.writeAtomic(path, new Uint8Array(1));
|
||||
|
||||
try {
|
||||
for (let [options, attributesExpected] of testSequence) {
|
||||
if (options !== null) {
|
||||
do_print("Setting permissions to " + JSON.stringify(options));
|
||||
yield OS.File.setPermissions(path, options);
|
||||
}
|
||||
|
||||
let stat = yield OS.File.stat(path);
|
||||
do_print("Got stat winAttributes: " + JSON.stringify(stat.winAttributes));
|
||||
|
||||
do_check_eq(stat.winAttributes.readOnly, attributesExpected.readOnly);
|
||||
do_check_eq(stat.winAttributes.system, attributesExpected.system);
|
||||
do_check_eq(stat.winAttributes.hidden, attributesExpected.hidden);
|
||||
|
||||
}
|
||||
} finally {
|
||||
yield OS.File.remove(path);
|
||||
}
|
||||
});
|
||||
|
||||
// Test application to open files.
|
||||
add_task(function* test_file_setPermissions() {
|
||||
let path = OS.Path.join(OS.Constants.Path.tmpDir,
|
||||
"test_osfile_win_async_setPermissions_file.tmp");
|
||||
yield OS.File.writeAtomic(path, new Uint8Array(1));
|
||||
|
||||
try {
|
||||
let fd = yield OS.File.open(path, { write: true });
|
||||
try {
|
||||
for (let [options, attributesExpected] of testSequence) {
|
||||
if (options !== null) {
|
||||
do_print("Setting permissions to " + JSON.stringify(options));
|
||||
yield fd.setPermissions(options);
|
||||
}
|
||||
|
||||
let stat = yield fd.stat();
|
||||
do_print("Got stat winAttributes: " + JSON.stringify(stat.winAttributes));
|
||||
do_check_eq(stat.winAttributes.readOnly, attributesExpected.readOnly);
|
||||
do_check_eq(stat.winAttributes.system, attributesExpected.system);
|
||||
do_check_eq(stat.winAttributes.hidden, attributesExpected.hidden);
|
||||
}
|
||||
} finally {
|
||||
yield fd.close();
|
||||
}
|
||||
} finally {
|
||||
yield OS.File.remove(path);
|
||||
}
|
||||
});
|
||||
|
||||
// Test application to Check setPermissions on a non-existant file path.
|
||||
add_task(function* test_non_existant_file_path_setPermissions() {
|
||||
let path = OS.Path.join(OS.Constants.Path.tmpDir,
|
||||
"test_osfile_win_async_setPermissions_path.tmp");
|
||||
Assert.rejects(OS.File.setPermissions(path, {winAttributes: {readOnly: true}}),
|
||||
/The system cannot find the file specified/,
|
||||
"setPermissions failed as expected on a non-existant file path");
|
||||
});
|
||||
|
||||
// Test application to Check setPermissions on a invalid file handle.
|
||||
add_task(function* test_closed_file_handle_setPermissions() {
|
||||
let path = OS.Path.join(OS.Constants.Path.tmpDir,
|
||||
"test_osfile_win_async_setPermissions_path.tmp");
|
||||
yield OS.File.writeAtomic(path, new Uint8Array(1));
|
||||
|
||||
try {
|
||||
let fd = yield OS.File.open(path, { write: true });
|
||||
yield fd.close();
|
||||
Assert.rejects(fd.setPermissions(path, {winAttributes: {readOnly: true}}),
|
||||
/The handle is invalid/,
|
||||
"setPermissions failed as expected on a invalid file handle");
|
||||
} finally {
|
||||
yield OS.File.remove(path);
|
||||
}
|
||||
});
|
||||
|
||||
function run_test() {
|
||||
run_next_test();
|
||||
}
|
@ -46,3 +46,7 @@ support-files =
|
||||
# filesystem backing /mnt/sdcard (not worth trying to fix).
|
||||
[test_osfile_async_setPermissions.js]
|
||||
skip-if = os == "win" || os == "android"
|
||||
|
||||
# Windows test
|
||||
[test_osfile_win_async_setPermissions.js]
|
||||
skip-if = os != "win"
|
||||
|
Loading…
x
Reference in New Issue
Block a user