Bug 924916: Part 2 - Implement OS.File.setDates() for Windows. r=yoric

This commit is contained in:
Nils Maier 2013-10-28 05:40:00 +00:00
parent 500ac6e588
commit 44cb229436
2 changed files with 115 additions and 0 deletions

View File

@ -237,6 +237,12 @@
/*filetime*/Type.FILETIME.in_ptr,
/*systime*/ Type.SystemTime.out_ptr);
declareLazyFFI(SysFile, "SystemTimeToFileTime", libc,
"SystemTimeToFileTime", ctypes.winapi_abi,
/*return*/ Type.zero_or_nothing,
/*systime*/ Type.SystemTime.in_ptr,
/*filetime*/ Type.FILETIME.out_ptr);
declareLazyFFI(SysFile, "FindFirstFile", libc,
"FindFirstFileW", ctypes.winapi_abi,
/*return*/ Type.find_HANDLE,
@ -316,6 +322,15 @@
/*disthi*/ Type.long.in_ptr,
/*method*/ Type.DWORD);
declareLazyFFI(SysFile, "SetFileTime", libc,
"SetFileTime", ctypes.winapi_abi,
/*return*/ Type.zero_or_nothing,
/*file*/ Type.HANDLE,
/*creation*/ Type.FILETIME.in_ptr,
/*access*/ Type.FILETIME.in_ptr,
/*write*/ Type.FILETIME.in_ptr);
declareLazyFFI(SysFile, "WriteFile", libc,
"WriteFile", ctypes.winapi_abi,
/*return*/ Type.zero_or_nothing,

View File

@ -188,6 +188,30 @@
return new File.Info(gFileInfo);
};
/**
* Set the last access and modification date of the file.
* The time stamp resolution is 1 second at best, but might be worse
* depending on the platform.
*
* @param {Date,number=} accessDate The last access date. If numeric,
* milliseconds since epoch. If omitted or null, then the current date
* will be used.
* @param {Date,number=} modificationDate The last modification date. If
* numeric, milliseconds since epoch. If omitted or null, then the current
* date will be used.
*
* @throws {TypeError} In case of invalid parameters.
* @throws {OS.File.Error} In case of I/O error.
*/
File.prototype.setDates = function setDates(accessDate, modificationDate) {
accessDate = Date_to_FILETIME("File.prototype.setDates", accessDate);
modificationDate = Date_to_FILETIME("File.prototype.setDates",
modificationDate);
throw_on_zero("setDates",
WinFile.SetFileTime(this.fd, null, accessDate.address(),
modificationDate.address()));
};
/**
* Flushes the file's buffers and causes all buffered data
* to be written.
@ -507,6 +531,38 @@
return new Date(utc);
};
/**
* Utility function: convert Javascript Date to FileTime.
*
* @param {string} fn Name of the calling function.
* @param {Date,number} date The date to be converted. If omitted or null,
* then the current date will be used. If numeric, assumed to be the date
* in milliseconds since epoch.
*/
let Date_to_FILETIME = function Date_to_FILETIME(fn, date) {
if (typeof date === "number") {
date = new Date(date);
} else if (!date) {
date = new Date();
} else if (typeof date.getUTCFullYear !== "function") {
throw new TypeError("|date| parameter of " + fn + " must be a " +
"|Date| instance or number");
}
gSystemTime.wYear = date.getUTCFullYear();
// Windows counts months from 1, JS from 0.
gSystemTime.wMonth = date.getUTCMonth() + 1;
gSystemTime.wDay = date.getUTCDate();
gSystemTime.wHour = date.getUTCHours();
gSystemTime.wMinute = date.getUTCMinutes();
gSystemTime.wSecond = date.getUTCSeconds();
gSystemTime.wMilliseconds = date.getUTCMilliseconds();
let result = new OS.Shared.Type.FILETIME.implementation();
throw_on_zero("Date_to_FILETIME",
WinFile.SystemTimeToFileTime(gSystemTimePtr,
result.address()));
return result;
};
/**
* Iterate on one directory.
*
@ -772,6 +828,50 @@
winDisposition: Const.OPEN_EXISTING
};
/**
* Set the last access and modification date of the file.
* The time stamp resolution is 1 second at best, but might be worse
* depending on the platform.
*
* Performance note: if you have opened the file already in write mode,
* method |File.prototype.stat| is generally much faster
* than method |File.stat|.
*
* Platform-specific note: under Windows, if the file is
* already opened without sharing of the write capability,
* this function will fail.
*
* @param {string} path The full name of the file to set the dates for.
* @param {Date,number=} accessDate The last access date. If numeric,
* milliseconds since epoch. If omitted or null, then the current date
* will be used.
* @param {Date,number=} modificationDate The last modification date. If
* numeric, milliseconds since epoch. If omitted or null, then the current
* date will be used.
*
* @throws {TypeError} In case of invalid paramters.
* @throws {OS.File.Error} In case of I/O error.
*/
File.setDates = function setDates(path, accessDate, modificationDate) {
let file = File.open(path, FILE_SETDATES_MODE, FILE_SETDATES_OPTIONS);
try {
return file.setDates(accessDate, modificationDate);
} finally {
file.close();
}
};
// All of the following is required to ensure that File.setDates
// also works on directories.
const FILE_SETDATES_MODE = {
write: true
};
const FILE_SETDATES_OPTIONS = {
winAccess: Const.GENERIC_WRITE,
// Directories can only be opened with backup semantics(!)
winFlags: Const.FILE_FLAG_BACKUP_SEMANTICS,
winDisposition: Const.OPEN_EXISTING
};
File.read = exports.OS.Shared.AbstractFile.read;
File.writeAtomic = exports.OS.Shared.AbstractFile.writeAtomic;
File.openUnique = exports.OS.Shared.AbstractFile.openUnique;