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

This commit is contained in:
Nils Maier 2013-10-28 05:40:00 +00:00
Родитель 5bfe05a87c
Коммит 500ac6e588
3 изменённых файлов: 117 добавлений и 0 удалений

Просмотреть файл

@ -514,6 +514,11 @@ static const dom::ConstantSpec gLibcProperties[] =
// (may not be exact, depending on padding).
{ "OSFILE_SIZEOF_DIRENT_D_NAME", INT_TO_JSVAL(sizeof (struct dirent) - offsetof (struct dirent, d_name)) },
// Defining |timeval|.
{ "OSFILE_SIZEOF_TIMEVAL", INT_TO_JSVAL(sizeof (struct timeval)) },
{ "OSFILE_OFFSETOF_TIMEVAL_TV_SEC", INT_TO_JSVAL(offsetof (struct timeval, tv_sec)) },
{ "OSFILE_OFFSETOF_TIMEVAL_TV_USEC", INT_TO_JSVAL(offsetof (struct timeval, tv_usec)) },
#if defined(DT_UNKNOWN)
// Position of field |d_type| in |dirent|
// Not strictly posix, but seems defined on all platforms

Просмотреть файл

@ -200,6 +200,24 @@
return ctypes.CDataFinalizer(dir, SysFile._close_dir);
};
// Structure |timeval|
{
let timeval = new SharedAll.HollowStructure(
"timeval",
Const.OSFILE_SIZEOF_TIMEVAL);
timeval.add_field_at(
Const.OSFILE_OFFSETOF_TIMEVAL_TV_SEC,
"tv_sec",
Type.long.implementation);
timeval.add_field_at(
Const.OSFILE_OFFSETOF_TIMEVAL_TV_USEC,
"tv_usec",
Type.long.implementation);
Type.timeval = timeval.getType();
Type.timevals = new SharedAll.Type("two timevals",
ctypes.ArrayType(Type.timeval.implementation, 2));
}
// Declare libc functions as functions of |OS.Unix.File|
// Finalizer-related functions
@ -570,6 +588,17 @@
array[1] = ctypes.CDataFinalizer(_pipebuf[1], SysFile._close);
return result;
};
declareLazyFFI(SysFile, "utimes", libc, "utimes", ctypes.default_abi,
/*return*/ Type.negativeone_or_nothing,
/*path*/ Type.path,
/*timeval[2]*/ Type.timevals.out_ptr
);
declareLazyFFI(SysFile, "futimes", libc, "futimes", ctypes.default_abi,
/*return*/ Type.negativeone_or_nothing,
/*fd*/ Type.fd,
/*timeval[2]*/ Type.timevals.out_ptr
);
};
exports.OS.Unix = {

Просмотреть файл

@ -168,6 +168,33 @@
return new File.Info(gStatData);
};
/**
* 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 = normalizeDate("File.prototype.setDates", accessDate);
modificationDate = normalizeDate("File.prototype.setDates",
modificationDate);
gTimevals[0].tv_sec = (accessDate / 1000) | 0;
gTimevals[0].tv_usec = 0;
gTimevals[1].tv_sec = (modificationDate / 1000) | 0;
gTimevals[1].tv_usec = 0;
throw_on_negative("setDates",
UnixFile.futimes(this.fd, gTimevalsPtr));
};
/**
* Flushes the file's buffers and causes all buffered data
* to be written.
@ -756,6 +783,8 @@
let gStatData = new Type.stat.implementation();
let gStatDataPtr = gStatData.address();
let gTimevals = new Type.timevals.implementation();
let gTimevalsPtr = gTimevals.address();
let MODE_MASK = 4095 /*= 07777*/;
File.Info = function Info(stat) {
let isDir = (stat.st_mode & Const.S_IFMT) == Const.S_IFDIR;
@ -839,6 +868,33 @@
return new File.Info(gStatData);
};
/**
* 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 {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) {
accessDate = normalizeDate("File.setDates", accessDate);
modificationDate = normalizeDate("File.setDates", modificationDate);
gTimevals[0].tv_sec = (accessDate / 1000) | 0;
gTimevals[0].tv_usec = 0;
gTimevals[1].tv_sec = (modificationDate / 1000) | 0;
gTimevals[1].tv_usec = 0;
throw_on_negative("setDates",
UnixFile.utimes(path, gTimevalsPtr));
};
File.read = exports.OS.Shared.AbstractFile.read;
File.writeAtomic = exports.OS.Shared.AbstractFile.writeAtomic;
File.openUnique = exports.OS.Shared.AbstractFile.openUnique;
@ -911,6 +967,33 @@
return result;
}
/**
* Normalize and verify a Date or numeric date value.
*
* @param {string} fn Function name of the calling function.
* @param {Date,number} date The date to normalize. If omitted or null,
* then the current date will be used.
*
* @throws {TypeError} Invalid date provided.
*
* @return {number} Sanitized, numeric date in milliseconds since epoch.
*/
function normalizeDate(fn, date) {
if (typeof date !== "number" && !date) {
// |date| was Omitted or null.
date = Date.now();
} else if (typeof date.getTime === "function") {
// Input might be a date or date-like object.
date = date.getTime();
}
if (isNaN(date)) {
throw new TypeError("|date| parameter of " + fn + " must be a " +
"|Date| instance or number");
}
return date;
};
File.Unix = exports.OS.Unix.File;
File.Error = SysAll.Error;
exports.OS.File = File;