Bug 1660843 - Return creation time from IOUtils.stat() on supported platforms r=emalysz

Differential Revision: https://phabricator.services.mozilla.com/D96890
This commit is contained in:
Barret Rennie 2020-12-03 05:37:33 +00:00
Родитель e0e9d2d31b
Коммит 69d3035e96
4 изменённых файлов: 70 добавлений и 17 удалений

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

@ -297,4 +297,12 @@ dictionary FileInfo {
* since Epoch (1970-01-01T00:00:00.000Z).
*/
long long lastModified;
/**
* The timestamp of file creation, represented in milliseconds since Epoch
* (1970-01-01T00:00:00.000Z).
*
* This is only available on MacOS and Windows.
*/
long long creationTime;
};

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

@ -127,6 +127,10 @@ MOZ_MUST_USE inline bool ToJSValue(
info.mType.Construct(aInternalFileInfo.mType);
info.mSize.Construct(aInternalFileInfo.mSize);
info.mLastModified.Construct(aInternalFileInfo.mLastModified);
if (aInternalFileInfo.mCreationTime.isSome()) {
info.mCreationTime.Construct(aInternalFileInfo.mCreationTime.ref());
}
return ToJSValue(aCx, info, aValue);
}
@ -1105,6 +1109,14 @@ Result<IOUtils::InternalFileInfo, IOUtils::IOError> IOUtils::StatSync(
MOZ_TRY(aFile->GetLastModifiedTime(&lastModified));
info.mLastModified = static_cast<int64_t>(lastModified);
PRTime creationTime = 0;
if (nsresult rv = aFile->GetCreationTime(&creationTime); NS_SUCCEEDED(rv)) {
info.mCreationTime.emplace(static_cast<int64_t>(creationTime));
} else if (NS_FAILED(rv) && rv != NS_ERROR_NOT_IMPLEMENTED) {
// This field is only supported on some platforms.
return Err(IOError(rv));
}
return info;
}

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

@ -381,6 +381,7 @@ struct IOUtils::InternalFileInfo {
FileType mType;
uint64_t mSize;
uint64_t mLastModified;
Maybe<uint64_t> mCreationTime;
};
/**

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

@ -14,17 +14,14 @@
const { Assert } = ChromeUtils.import("resource://testing-common/Assert.jsm");
const { ObjectUtils } = ChromeUtils.import("resource://gre/modules/ObjectUtils.jsm");
// TODO: Remove this import for OS.File. It is currently being used as a
// stop gap for missing IOUtils functionality.
const { OS } = ChromeUtils.import("resource://gre/modules/osfile.jsm");
const tmpDir = OS.Constants.Path.tmpDir;
const { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
add_task(async function test_stat() {
info("Test attempt to stat a regular empty file");
const emptyFileName = OS.Path.join(tmpDir, "test_stat_empty.tmp");
const tmpDir = await PathUtils.getTempDir();
const emptyFileName = PathUtils.join(tmpDir, "test_stat_empty.tmp");
await createFile(emptyFileName);
const emptyFileInfo = await IOUtils.stat(emptyFileName);
@ -38,7 +35,7 @@
);
info("Test attempt to stat a regular binary file");
const tempFileName = OS.Path.join(tmpDir, "test_stat_binary.tmp");
const tempFileName = PathUtils.join(tmpDir, "test_stat_binary.tmp");
const bytes = Uint8Array.of(...new Array(50).keys());
await createFile(tempFileName, bytes);
@ -53,8 +50,8 @@
);
info("Test attempt to stat a directory");
const tempDirName = OS.Path.join(tmpDir, "test_stat_dir.tmp.d");
await OS.File.makeDir(tempDirName);
const tempDirName = PathUtils.join(tmpDir, "test_stat_dir.tmp.d");
await IOUtils.makeDirectory(tempDirName);
const dirInfo = await IOUtils.stat(tempDirName);
is(dirInfo.size, -1, "IOUtils::stat reports -1 size for directories")
@ -71,7 +68,10 @@
add_task(async function test_stat_failures() {
info("Test attempt to stat a non-existing file");
const notExistsFile = OS.Path.join(tmpDir, "test_stat_not_exists.tmp");
const tmpDir = await PathUtils.getTempDir();
const notExistsFile = PathUtils.join(tmpDir, "test_stat_not_exists.tmp");
await Assert.rejects(
IOUtils.stat(notExistsFile),
@ -82,7 +82,10 @@
add_task(async function test_touch_and_stat() {
info("Test attempt to touch a file");
const tmpFileName = OS.Path.join(tmpDir, "test_touch_and_stat.tmp");
const tmpDir = await PathUtils.getTempDir();
const tmpFileName = PathUtils.join(tmpDir, "test_touch_and_stat.tmp");
await createFile(tmpFileName);
const oldFileInfo = await IOUtils.stat(tmpFileName);
@ -103,14 +106,16 @@
);
info("Test attempt to touch a directory");
const tmpDirName = OS.Path.join(tmpDir, "test_touch_and_stat.tmp.d");
const tmpDirName = PathUtils.join(tmpDir, "test_touch_and_stat.tmp.d");
await createDir(tmpDirName);
await cleanup(tmpFileName, tmpDirName);
});
add_task(async function test_touch_custom_mod_time() {
const tempFileName = OS.Path.join(tmpDir, "test_touch_custom_mod_time.tmp");
const tmpDir = await PathUtils.getTempDir();
const tempFileName = PathUtils.join(tmpDir, "test_touch_custom_mod_time.tmp");
await createFile(tempFileName);
const originalInfo = await IOUtils.stat(tempFileName);
const now = originalInfo.lastModified;
@ -138,9 +143,36 @@
await cleanup(tempFileName);
});
add_task(async function test_stat_btime() {
if (["Darwin", "WINNT"].includes(Services.appinfo.OS)) {
const tmpDir = await PathUtils.getTempDir();
const tempFileName = PathUtils.join(tmpDir, "test_stat_btime.tmp");
await createFile(tempFileName);
const originalInfo = await IOUtils.stat(tempFileName);
const future = originalInfo.lastModified + 6000;
await IOUtils.touch(tempFileName, future);
const futureInfo = await IOUtils.stat(tempFileName);
ok(originalInfo.hasOwnProperty("creationTime"), "originalInfo has creationTime field");
ok(originalInfo.creationTime !== undefined && originalInfo.creationTime !== null, "originalInfo has non-null creationTime");
ok(futureInfo.hasOwnProperty("creationTime"), "futureInfo has creationTime field");
ok(futureInfo.creationTime !== undefined && futureInfo.creationTime !== null, "futureInfo has non-null creationTime");
is(originalInfo.creationTime, futureInfo.creationTime, "creationTime matches");
await cleanup(tempFileName);
} else {
ok(true, `skipping test_stat_btime() on unsupported platform ${Services.appinfo.OS}`);
}
});
add_task(async function test_touch_failures() {
info("Test attempt to touch a non-existing file");
const notExistsFile = OS.Path.join(tmpDir, "test_touch_not_exists.tmp");
const tmpDir = await PathUtils.getTempDir();
const notExistsFile = PathUtils.join(tmpDir, "test_touch_not_exists.tmp");
await Assert.rejects(
IOUtils.touch(notExistsFile),
@ -149,7 +181,7 @@
);
info("Test attempt to set modification time to Epoch");
const tempFileName = OS.Path.join(tmpDir, "test_touch_epoch.tmp");
const tempFileName = PathUtils.join(tmpDir, "test_touch_epoch.tmp");
await createFile(tempFileName);
await Assert.rejects(