mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-24 05:11:16 +00:00
Backed out 3 changesets (bug 1786608) for causing build bustages CLOSED TREE
Backed out changeset 8eb603c625f4 (bug 1786608) Backed out changeset 0df0cf8f67b4 (bug 1786608) Backed out changeset 2b3815684692 (bug 1786608)
This commit is contained in:
parent
7124a20f47
commit
c93d8c6464
@ -172,24 +172,7 @@ namespace IOUtils {
|
||||
[NewObject]
|
||||
Promise<undefined> copy(DOMString sourcePath, DOMString destPath, optional CopyOptions options = {});
|
||||
/**
|
||||
* Updates the access time for the file at |path|.
|
||||
*
|
||||
* @param path An absolute file path identifying the file whose
|
||||
* modification time is to be set. This file must exist
|
||||
* and will not be created.
|
||||
* @param modification An optional access time for the file expressed in
|
||||
* milliseconds since the Unix epoch
|
||||
* (1970-01-01T00:00:00Z). The current system time is used
|
||||
* if this parameter is not provided.
|
||||
*
|
||||
* @return Resolves with the updated access time time expressed in
|
||||
* milliseconds since the Unix epoch, otherwise rejects with a
|
||||
* DOMException.
|
||||
*/
|
||||
[NewObject]
|
||||
Promise<long long> setAccessTime(DOMString path, optional long long access);
|
||||
/**
|
||||
* Updates the modification time for the file at |path|.
|
||||
* Updates the |modification| time for the file at |path|.
|
||||
*
|
||||
* @param path An absolute file path identifying the file whose
|
||||
* modification time is to be set. This file must exist
|
||||
@ -640,18 +623,21 @@ dictionary FileInfo {
|
||||
* obtained.
|
||||
*/
|
||||
DOMString path;
|
||||
|
||||
/**
|
||||
* Identifies if the file at |path| is a regular file, directory, or something
|
||||
* something else.
|
||||
*/
|
||||
FileType type;
|
||||
|
||||
/**
|
||||
* If this represents a regular file, the size of the file in bytes.
|
||||
* Otherwise, -1.
|
||||
*/
|
||||
long long size;
|
||||
/**
|
||||
* The timestamp of the last file modification, represented in milliseconds
|
||||
* since Epoch (1970-01-01T00:00:00.000Z).
|
||||
*/
|
||||
long long lastModified;
|
||||
|
||||
/**
|
||||
* The timestamp of file creation, represented in milliseconds since Epoch
|
||||
@ -660,19 +646,6 @@ dictionary FileInfo {
|
||||
* This is only available on MacOS and Windows.
|
||||
*/
|
||||
long long creationTime;
|
||||
|
||||
/**
|
||||
* The timestmp of last file accesss, represented in milliseconds since Epoch
|
||||
* (1970-01-01T00:00:00.000Z).
|
||||
*/
|
||||
long long lastAccessed;
|
||||
|
||||
/**
|
||||
* The timestamp of the last file modification, represented in milliseconds
|
||||
* since Epoch (1970-01-01T00:00:00.000Z).
|
||||
*/
|
||||
long long lastModified;
|
||||
|
||||
/**
|
||||
* The permissions of the file, expressed as a UNIX file mode.
|
||||
*
|
||||
|
@ -154,12 +154,11 @@ static nsCString FormatErrorMessage(nsresult aError,
|
||||
info.mPath.Construct(aInternalFileInfo.mPath);
|
||||
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());
|
||||
}
|
||||
info.mLastAccessed.Construct(aInternalFileInfo.mLastAccessed);
|
||||
info.mLastModified.Construct(aInternalFileInfo.mLastModified);
|
||||
|
||||
info.mPermissions.Construct(aInternalFileInfo.mPermissions);
|
||||
|
||||
@ -730,39 +729,22 @@ already_AddRefed<Promise> IOUtils::Copy(GlobalObject& aGlobal,
|
||||
});
|
||||
}
|
||||
|
||||
/* static */
|
||||
already_AddRefed<Promise> IOUtils::SetAccessTime(
|
||||
GlobalObject& aGlobal, const nsAString& aPath,
|
||||
const Optional<int64_t>& aAccess, ErrorResult& aError) {
|
||||
return SetTime(aGlobal, aPath, aAccess, &nsIFile::SetLastAccessedTime,
|
||||
aError);
|
||||
}
|
||||
|
||||
/* static */
|
||||
already_AddRefed<Promise> IOUtils::SetModificationTime(
|
||||
GlobalObject& aGlobal, const nsAString& aPath,
|
||||
const Optional<int64_t>& aModification, ErrorResult& aError) {
|
||||
return SetTime(aGlobal, aPath, aModification, &nsIFile::SetLastModifiedTime,
|
||||
aError);
|
||||
}
|
||||
|
||||
/* static */
|
||||
already_AddRefed<Promise> IOUtils::SetTime(GlobalObject& aGlobal,
|
||||
const nsAString& aPath,
|
||||
const Optional<int64_t>& aNewTime,
|
||||
IOUtils::SetTimeFn aSetTimeFn,
|
||||
ErrorResult& aError) {
|
||||
return WithPromiseAndState(
|
||||
aGlobal, aError, [&](Promise* promise, auto& state) {
|
||||
nsCOMPtr<nsIFile> file = new nsLocalFile();
|
||||
REJECT_IF_INIT_PATH_FAILED(file, aPath, promise);
|
||||
|
||||
int64_t newTime = aNewTime.WasPassed() ? aNewTime.Value()
|
||||
: PR_Now() / PR_USEC_PER_MSEC;
|
||||
Maybe<int64_t> newTime = Nothing();
|
||||
if (aModification.WasPassed()) {
|
||||
newTime = Some(aModification.Value());
|
||||
}
|
||||
DispatchAndResolve<int64_t>(
|
||||
state->mEventQueue, promise,
|
||||
[file = std::move(file), aSetTimeFn, newTime]() {
|
||||
return SetTimeSync(file, aSetTimeFn, newTime);
|
||||
state->mEventQueue, promise, [file = std::move(file), newTime]() {
|
||||
return SetModificationTimeSync(file, newTime);
|
||||
});
|
||||
});
|
||||
}
|
||||
@ -1738,6 +1720,9 @@ Result<IOUtils::InternalFileInfo, IOUtils::IOError> IOUtils::StatSync(
|
||||
MOZ_TRY(aFile->GetFileSize(&size));
|
||||
}
|
||||
info.mSize = size;
|
||||
PRTime lastModified = 0;
|
||||
MOZ_TRY(aFile->GetLastModifiedTime(&lastModified));
|
||||
info.mLastModified = static_cast<int64_t>(lastModified);
|
||||
|
||||
PRTime creationTime = 0;
|
||||
if (nsresult rv = aFile->GetCreationTime(&creationTime); NS_SUCCEEDED(rv)) {
|
||||
@ -1747,24 +1732,26 @@ Result<IOUtils::InternalFileInfo, IOUtils::IOError> IOUtils::StatSync(
|
||||
return Err(IOError(rv));
|
||||
}
|
||||
|
||||
PRTime lastAccessed = 0;
|
||||
MOZ_TRY(aFile->GetLastAccessedTime(&lastAccessed));
|
||||
info.mLastAccessed = static_cast<int64_t>(lastAccessed);
|
||||
|
||||
PRTime lastModified = 0;
|
||||
MOZ_TRY(aFile->GetLastModifiedTime(&lastModified));
|
||||
info.mLastModified = static_cast<int64_t>(lastModified);
|
||||
|
||||
MOZ_TRY(aFile->GetPermissions(&info.mPermissions));
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
/* static */
|
||||
Result<int64_t, IOUtils::IOError> IOUtils::SetTimeSync(
|
||||
nsIFile* aFile, IOUtils::SetTimeFn aSetTimeFn, int64_t aNewTime) {
|
||||
Result<int64_t, IOUtils::IOError> IOUtils::SetModificationTimeSync(
|
||||
nsIFile* aFile, const Maybe<int64_t>& aNewModTime) {
|
||||
MOZ_ASSERT(!NS_IsMainThread());
|
||||
|
||||
int64_t now = aNewModTime.valueOrFrom([]() {
|
||||
// NB: PR_Now reports time in microseconds since the Unix epoch
|
||||
// (1970-01-01T00:00:00Z). Both nsLocalFile's lastModifiedTime and
|
||||
// JavaScript's Date primitive values are to be expressed in
|
||||
// milliseconds since Epoch.
|
||||
int64_t nowMicros = PR_Now();
|
||||
int64_t nowMillis = nowMicros / PR_USEC_PER_MSEC;
|
||||
return nowMillis;
|
||||
});
|
||||
|
||||
// nsIFile::SetLastModifiedTime will *not* do what is expected when passed 0
|
||||
// as an argument. Rather than setting the time to 0, it will recalculate the
|
||||
// system time and set it to that value instead. We explicit forbid this,
|
||||
@ -1772,7 +1759,7 @@ Result<int64_t, IOUtils::IOError> IOUtils::SetTimeSync(
|
||||
//
|
||||
// If it ever becomes possible to set a file time to 0, this check should be
|
||||
// removed, though this use case seems rare.
|
||||
if (aNewTime == 0) {
|
||||
if (now == 0) {
|
||||
return Err(
|
||||
IOError(NS_ERROR_ILLEGAL_VALUE)
|
||||
.WithMessage(
|
||||
@ -1782,7 +1769,7 @@ Result<int64_t, IOUtils::IOError> IOUtils::SetTimeSync(
|
||||
aFile->HumanReadablePath().get()));
|
||||
}
|
||||
|
||||
nsresult rv = (aFile->*aSetTimeFn)(aNewTime);
|
||||
nsresult rv = aFile->SetLastModifiedTime(now);
|
||||
|
||||
if (NS_FAILED(rv)) {
|
||||
IOError err(rv);
|
||||
@ -1794,7 +1781,7 @@ Result<int64_t, IOUtils::IOError> IOUtils::SetTimeSync(
|
||||
}
|
||||
return Err(err);
|
||||
}
|
||||
return aNewTime;
|
||||
return now;
|
||||
}
|
||||
|
||||
/* static */
|
||||
|
@ -19,7 +19,6 @@
|
||||
#include "mozilla/dom/IOUtilsBinding.h"
|
||||
#include "mozilla/dom/TypedArray.h"
|
||||
#include "nsIAsyncShutdown.h"
|
||||
#include "nsIFile.h"
|
||||
#include "nsISerialEventTarget.h"
|
||||
#include "nsPrintfCString.h"
|
||||
#include "nsProxyRelease.h"
|
||||
@ -130,27 +129,10 @@ class IOUtils final {
|
||||
const CopyOptions& aOptions,
|
||||
ErrorResult& aError);
|
||||
|
||||
static already_AddRefed<Promise> SetAccessTime(
|
||||
GlobalObject& aGlobal, const nsAString& aPath,
|
||||
const Optional<int64_t>& aAccess, ErrorResult& aError);
|
||||
|
||||
static already_AddRefed<Promise> SetModificationTime(
|
||||
GlobalObject& aGlobal, const nsAString& aPath,
|
||||
const Optional<int64_t>& aModification, ErrorResult& aError);
|
||||
|
||||
private:
|
||||
using SetTimeFn = decltype(&nsIFile::SetLastAccessedTime);
|
||||
|
||||
static_assert(
|
||||
std::is_same_v<SetTimeFn, decltype(&nsIFile::SetLastModifiedTime)>);
|
||||
|
||||
static already_AddRefed<Promise> SetTime(GlobalObject& aGlobal,
|
||||
const nsAString& aPath,
|
||||
const Optional<int64_t>& aNewTime,
|
||||
SetTimeFn aSetTimeFn,
|
||||
ErrorResult& aError);
|
||||
|
||||
public:
|
||||
static already_AddRefed<Promise> GetChildren(
|
||||
GlobalObject& aGlobal, const nsAString& aPath,
|
||||
const GetChildrenOptions& aOptions, ErrorResult& aError);
|
||||
@ -443,20 +425,16 @@ class IOUtils final {
|
||||
static Result<IOUtils::InternalFileInfo, IOError> StatSync(nsIFile* aFile);
|
||||
|
||||
/**
|
||||
* Attempts to update the last access or modification time of the file at
|
||||
* |aFile|.
|
||||
* Attempts to update the last modification time of the file at |aFile|.
|
||||
*
|
||||
* @param aFile The location of the file.
|
||||
* @param SetTimeFn A member function pointer to either
|
||||
* nsIFile::SetLastAccessedTime or
|
||||
* nsIFile::SetLastModifiedTime.
|
||||
* @param aNewTime Some value in milliseconds since Epoch.
|
||||
* @param aNewModTime Some value in milliseconds since Epoch. For the current
|
||||
* system time, use |Nothing|.
|
||||
*
|
||||
* @return Timestamp of the file if the operation was successful, or an error.
|
||||
*/
|
||||
static Result<int64_t, IOError> SetTimeSync(nsIFile* aFile,
|
||||
SetTimeFn aSetTimeFn,
|
||||
int64_t aNewTime);
|
||||
static Result<int64_t, IOError> SetModificationTimeSync(
|
||||
nsIFile* aFile, const Maybe<int64_t>& aNewModTime);
|
||||
|
||||
/**
|
||||
* Returns the immediate children of the directory at |aFile|, if any.
|
||||
@ -695,9 +673,8 @@ struct IOUtils::InternalFileInfo {
|
||||
nsString mPath;
|
||||
FileType mType = FileType::Other;
|
||||
uint64_t mSize = 0;
|
||||
Maybe<PRTime> mCreationTime; // In ms since epoch.
|
||||
PRTime mLastAccessed = 0; // In ms since epoch.
|
||||
PRTime mLastModified = 0; // In ms since epoch.
|
||||
uint64_t mLastModified = 0;
|
||||
Maybe<uint64_t> mCreationTime;
|
||||
uint32_t mPermissions = 0;
|
||||
};
|
||||
|
||||
|
@ -59,11 +59,6 @@
|
||||
1000, // Allow for 1 second deviation in case of slow tests.
|
||||
"IOUtils::stat can get the last modification date for a regular file"
|
||||
);
|
||||
Assert.less(
|
||||
(fileInfo.lastAccessed - new Date().valueOf()),
|
||||
1000,
|
||||
"IOUtils::stat can get the last access date for a regular file"
|
||||
);
|
||||
|
||||
await cleanup(emptyFileName, tempFileName, tempDirName)
|
||||
});
|
||||
@ -102,31 +97,6 @@
|
||||
newFileInfo.lastModified,
|
||||
"IOUtils::setModificationTime returns the updated time stamp."
|
||||
);
|
||||
is(
|
||||
newFileInfo.lastAccessed,
|
||||
oldFileInfo.lastAccessed,
|
||||
"IOUtils::setModificationTime does not change lastAccessed"
|
||||
);
|
||||
|
||||
await sleep(500);
|
||||
|
||||
const newerStamp = await IOUtils.setAccessTime(tmpFileName);
|
||||
const newerFileInfo = await IOUtils.stat(tmpFileName);
|
||||
|
||||
ok(
|
||||
newerFileInfo.lastAccessed > newFileInfo.lastAccessed,
|
||||
"IOUtils::setAccessTimetime can update the lastAccessed time stamp on the file system"
|
||||
);
|
||||
is(
|
||||
newerStamp,
|
||||
newerFileInfo.lastAccessed,
|
||||
"IOUtils::setAccessTimeTime returns the updated time stamp."
|
||||
);
|
||||
is(
|
||||
newerFileInfo.lastModified,
|
||||
newFileInfo.lastModified,
|
||||
"IOUtils::setAccessTimeTime does not change lastModified"
|
||||
);
|
||||
}
|
||||
|
||||
const tmpDirName = PathUtils.join(PathUtils.tempDir, "test_setModificationTime_and_stat.tmp.d");
|
||||
|
@ -243,13 +243,6 @@ interface nsIFile : nsISupports
|
||||
attribute unsigned long permissions;
|
||||
attribute unsigned long permissionsOfLink;
|
||||
|
||||
/**
|
||||
* The last accesss time of the file in milliseconds from midnight, January
|
||||
* 1, 1970 GMT, if available.
|
||||
*/
|
||||
attribute PRTime lastAccessedTime;
|
||||
attribute PRTime lastAccessedTimeOfLink;
|
||||
|
||||
/**
|
||||
* File Times are to be in milliseconds from
|
||||
* midnight (00:00:00), January 1, 1970 Greenwich Mean
|
||||
|
@ -1155,11 +1155,10 @@ nsLocalFile::Remove(bool aRecursive) {
|
||||
return NSRESULT_FOR_RETURN(rmdir(mPath.get()));
|
||||
}
|
||||
|
||||
nsresult nsLocalFile::GetTimeImpl(PRTime* aTime,
|
||||
nsLocalFile::TimeField aTimeField,
|
||||
nsresult nsLocalFile::GetLastModifiedTimeImpl(PRTime* aLastModTime,
|
||||
bool aFollowLinks) {
|
||||
CHECK_mPath();
|
||||
if (NS_WARN_IF(!aTime)) {
|
||||
if (NS_WARN_IF(!aLastModTime)) {
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
|
||||
@ -1171,35 +1170,16 @@ nsresult nsLocalFile::GetTimeImpl(PRTime* aTime,
|
||||
return NSRESULT_FOR_ERRNO();
|
||||
}
|
||||
|
||||
struct timespec* timespec;
|
||||
switch (aTimeField) {
|
||||
case TimeField::AccessedTime:
|
||||
#if (defined(__APPLE__) && defined(__MACH__))
|
||||
timespec = &fileStats.st_atimespec;
|
||||
*aLastModTime = TimespecToMillis(fileStats.st_mtimespec);
|
||||
#else
|
||||
timespec = &fileStats.st_atim;
|
||||
*aLastModTime = TimespecToMillis(fileStats.st_mtim);
|
||||
#endif
|
||||
break;
|
||||
|
||||
case TimeField::ModifiedTime:
|
||||
#if (defined(__APPLE__) && defined(__MACH__))
|
||||
timespec = &fileStats.st_mtimespec;
|
||||
#else
|
||||
timespec = &fileStats.st_mtim;
|
||||
#endif
|
||||
break;
|
||||
|
||||
default:
|
||||
MOZ_CRASH("Unknown TimeField");
|
||||
}
|
||||
|
||||
*aTime = TimespecToMillis(*timespec);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult nsLocalFile::SetTimeImpl(PRTime aTime,
|
||||
nsLocalFile::TimeField aTimeField,
|
||||
nsresult nsLocalFile::SetLastModifiedTimeImpl(PRTime aLastModTime,
|
||||
bool aFollowLinks) {
|
||||
CHECK_mPath();
|
||||
|
||||
@ -1212,82 +1192,49 @@ nsresult nsLocalFile::SetTimeImpl(PRTime aTime,
|
||||
}
|
||||
#endif
|
||||
|
||||
int result;
|
||||
if (aLastModTime != 0) {
|
||||
ENSURE_STAT_CACHE();
|
||||
|
||||
if (aTime == 0) {
|
||||
aTime = PR_Now();
|
||||
}
|
||||
timeval access{};
|
||||
#if (defined(__APPLE__) && defined(__MACH__))
|
||||
access.tv_sec = mCachedStat.st_atimespec.tv_sec;
|
||||
access.tv_usec = mCachedStat.st_atimespec.tv_nsec / 1000;
|
||||
#else
|
||||
access.tv_sec = mCachedStat.st_atim.tv_sec;
|
||||
access.tv_usec = mCachedStat.st_atim.tv_nsec / 1000;
|
||||
#endif
|
||||
timeval modification{};
|
||||
modification.tv_sec = aLastModTime / PR_MSEC_PER_SEC;
|
||||
modification.tv_usec = (aLastModTime % PR_MSEC_PER_SEC) * PR_USEC_PER_MSEC;
|
||||
|
||||
timeval times[2];
|
||||
|
||||
const size_t writeIndex = aTimeField == TimeField::AccessedTime ? 0 : 1;
|
||||
const size_t copyIndex = aTimeField == TimeField::AccessedTime ? 1 : 0;
|
||||
|
||||
#if (defined(__APPLE__) && defined(__MACH__))
|
||||
auto* copyFrom = aTimeField == TimeField::AccessedTime
|
||||
? &mCachedStat.st_atimespec
|
||||
: &mCachedStat.st_mtimespec;
|
||||
#else
|
||||
auto* copyFrom = aTimeField == TimeField::AccessedTime ? &mCachedStat.st_atim
|
||||
: &mCachedStat.st_mtim;
|
||||
#endif
|
||||
|
||||
times[copyIndex].tv_sec = copyFrom->tv_sec;
|
||||
times[copyIndex].tv_usec = copyFrom->tv_nsec / 1000;
|
||||
|
||||
times[writeIndex].tv_sec = aTime / PR_MSEC_PER_SEC;
|
||||
times[writeIndex].tv_usec = (aTime % PR_MSEC_PER_SEC) * PR_USEC_PER_MSEC;
|
||||
|
||||
int result = utimesFn(mPath.get(), times);
|
||||
times[0] = access;
|
||||
times[1] = modification;
|
||||
result = utimesFn(mPath.get(), times);
|
||||
} else {
|
||||
result = utimesFn(mPath.get(), nullptr);
|
||||
}
|
||||
return NSRESULT_FOR_RETURN(result);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsLocalFile::GetLastAccessedTime(PRTime* aLastAccessedTime) {
|
||||
return GetTimeImpl(aLastAccessedTime, TimeField::AccessedTime,
|
||||
/* follow links? */ true);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsLocalFile::SetLastAccessedTime(PRTime aLastAccessedTime) {
|
||||
return SetTimeImpl(aLastAccessedTime, TimeField::AccessedTime,
|
||||
/* follow links? */ true);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsLocalFile::GetLastAccessedTimeOfLink(PRTime* aLastAccessedTime) {
|
||||
return GetTimeImpl(aLastAccessedTime, TimeField::AccessedTime,
|
||||
/* follow links? */ false);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsLocalFile::SetLastAccessedTimeOfLink(PRTime aLastAccessedTime) {
|
||||
return SetTimeImpl(aLastAccessedTime, TimeField::AccessedTime,
|
||||
/* follow links? */ false);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsLocalFile::GetLastModifiedTime(PRTime* aLastModTime) {
|
||||
return GetTimeImpl(aLastModTime, TimeField::ModifiedTime,
|
||||
/* follow links? */ true);
|
||||
return GetLastModifiedTimeImpl(aLastModTime, /* follow links? */ true);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsLocalFile::SetLastModifiedTime(PRTime aLastModTime) {
|
||||
return SetTimeImpl(aLastModTime, TimeField::ModifiedTime,
|
||||
/* follow links ? */ true);
|
||||
return SetLastModifiedTimeImpl(aLastModTime, /* follow links ? */ true);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsLocalFile::GetLastModifiedTimeOfLink(PRTime* aLastModTimeOfLink) {
|
||||
return GetTimeImpl(aLastModTimeOfLink, TimeField::ModifiedTime,
|
||||
/* follow link? */ false);
|
||||
return GetLastModifiedTimeImpl(aLastModTimeOfLink, /* follow link? */ false);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsLocalFile::SetLastModifiedTimeOfLink(PRTime aLastModTimeOfLink) {
|
||||
return SetTimeImpl(aLastModTimeOfLink, TimeField::ModifiedTime,
|
||||
/* follow links? */ false);
|
||||
return SetLastModifiedTimeImpl(aLastModTimeOfLink, /* follow links? */ false);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
@ -85,10 +85,8 @@ class nsLocalFile final
|
||||
nsresult CreateAndKeepOpen(uint32_t aType, int aFlags, uint32_t aPermissions,
|
||||
bool aSkipAncestors, PRFileDesc** aResult);
|
||||
|
||||
enum class TimeField { AccessedTime, ModifiedTime };
|
||||
nsresult SetTimeImpl(PRTime aTime, TimeField aTimeField, bool aFollowLinks);
|
||||
nsresult GetTimeImpl(PRTime* aTime, TimeField aTimeField, bool aFollowLinks);
|
||||
|
||||
nsresult SetLastModifiedTimeImpl(PRTime aLastModTime, bool aFollowLinks);
|
||||
nsresult GetLastModifiedTimeImpl(PRTime* aLastModTime, bool aFollowLinks);
|
||||
nsresult GetCreationTimeImpl(PRTime* aCreationTime, bool aFollowLinks);
|
||||
|
||||
#if defined(USE_LINUX_QUOTACTL)
|
||||
|
@ -607,8 +607,7 @@ static void FileTimeToPRTime(const FILETIME* aFiletime, PRTime* aPrtm) {
|
||||
|
||||
// copied from nsprpub/pr/src/{io/prfile.c | md/windows/w95io.c} with some
|
||||
// changes : PR_GetFileInfo64, _PR_MD_GETFILEINFO64
|
||||
static nsresult GetFileInfo(const nsString& aName,
|
||||
nsLocalFile::FileInfo* aInfo) {
|
||||
static nsresult GetFileInfo(const nsString& aName, PRFileInfo64* aInfo) {
|
||||
if (aName.IsEmpty()) {
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
@ -639,6 +638,8 @@ static nsresult GetFileInfo(const nsString& aName,
|
||||
aInfo->size = fileData.nFileSizeHigh;
|
||||
aInfo->size = (aInfo->size << 32) + fileData.nFileSizeLow;
|
||||
|
||||
FileTimeToPRTime(&fileData.ftLastWriteTime, &aInfo->modifyTime);
|
||||
|
||||
if (0 == fileData.ftCreationTime.dwLowDateTime &&
|
||||
0 == fileData.ftCreationTime.dwHighDateTime) {
|
||||
aInfo->creationTime = aInfo->modifyTime;
|
||||
@ -646,9 +647,6 @@ static nsresult GetFileInfo(const nsString& aName,
|
||||
FileTimeToPRTime(&fileData.ftCreationTime, &aInfo->creationTime);
|
||||
}
|
||||
|
||||
FileTimeToPRTime(&fileData.ftLastAccessTime, &aInfo->accessTime);
|
||||
FileTimeToPRTime(&fileData.ftLastWriteTime, &aInfo->modifyTime);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -926,7 +924,7 @@ nsresult nsLocalFile::ResolveSymlink() {
|
||||
}
|
||||
|
||||
// Resolve any shortcuts and stat the resolved path. After a successful return
|
||||
// the path is guaranteed valid and the members of mFileInfo can be used.
|
||||
// the path is guaranteed valid and the members of mFileInfo64 can be used.
|
||||
nsresult nsLocalFile::ResolveAndStat() {
|
||||
// if we aren't dirty then we are already done
|
||||
if (!mDirty) {
|
||||
@ -950,12 +948,12 @@ nsresult nsLocalFile::ResolveAndStat() {
|
||||
|
||||
// first we will see if the working path exists. If it doesn't then
|
||||
// there is nothing more that can be done
|
||||
nsresult rv = GetFileInfo(nsprPath, &mFileInfo);
|
||||
nsresult rv = GetFileInfo(nsprPath, &mFileInfo64);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
if (mFileInfo.type != PR_FILE_OTHER) {
|
||||
if (mFileInfo64.type != PR_FILE_OTHER) {
|
||||
mResolveDirty = false;
|
||||
mDirty = false;
|
||||
return NS_OK;
|
||||
@ -972,7 +970,7 @@ nsresult nsLocalFile::ResolveAndStat() {
|
||||
|
||||
mResolveDirty = false;
|
||||
// get the details of the resolved path
|
||||
rv = GetFileInfo(mResolvedPath, &mFileInfo);
|
||||
rv = GetFileInfo(mResolvedPath, &mFileInfo64);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
@ -2358,86 +2356,64 @@ nsLocalFile::Remove(bool aRecursive) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult nsLocalFile::GetDateImpl(PRTime* aTime,
|
||||
nsLocalFile::TimeField aTimeField,
|
||||
bool aFollowLinks) {
|
||||
NS_IMETHODIMP
|
||||
nsLocalFile::GetLastModifiedTime(PRTime* aLastModifiedTime) {
|
||||
// Check we are correctly initialized.
|
||||
CHECK_mWorkingPath();
|
||||
|
||||
if (NS_WARN_IF(!aTime)) {
|
||||
if (NS_WARN_IF(!aLastModifiedTime)) {
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
|
||||
FileInfo symlinkInfo{};
|
||||
FileInfo* pInfo;
|
||||
// get the modified time of the target as determined by mFollowSymlinks
|
||||
// If true, then this will be for the target of the shortcut file,
|
||||
// otherwise it will be for the shortcut file itself (i.e. the same
|
||||
// results as GetLastModifiedTimeOfLink)
|
||||
|
||||
if (aFollowLinks) {
|
||||
if (nsresult rv = GetFileInfo(mWorkingPath, &symlinkInfo); NS_FAILED(rv)) {
|
||||
nsresult rv = ResolveAndStat();
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
pInfo = &symlinkInfo;
|
||||
} else {
|
||||
if (nsresult rv = ResolveAndStat(); NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
pInfo = &mFileInfo;
|
||||
}
|
||||
|
||||
switch (aTimeField) {
|
||||
case TimeField::AccessedTime:
|
||||
*aTime = pInfo->accessTime / PR_USEC_PER_MSEC;
|
||||
break;
|
||||
|
||||
case TimeField::ModifiedTime:
|
||||
*aTime = pInfo->modifyTime / PR_USEC_PER_MSEC;
|
||||
break;
|
||||
|
||||
default:
|
||||
MOZ_CRASH("Unknown time field");
|
||||
}
|
||||
|
||||
// microseconds -> milliseconds
|
||||
*aLastModifiedTime = mFileInfo64.modifyTime / PR_USEC_PER_MSEC;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsLocalFile::GetLastAccessedTime(PRTime* aLastAccessedTime) {
|
||||
return GetDateImpl(aLastAccessedTime, TimeField::AccessedTime,
|
||||
/* aFollowSymlinks = */ true);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsLocalFile::GetLastAccessedTimeOfLink(PRTime* aLastAccessedTime) {
|
||||
return GetDateImpl(aLastAccessedTime, TimeField::AccessedTime,
|
||||
/* aFollowSymlinks = */ false);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsLocalFile::SetLastAccessedTime(PRTime aLastAccessedTime) {
|
||||
return SetDateImpl(aLastAccessedTime, TimeField::AccessedTime);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsLocalFile::SetLastAccessedTimeOfLink(PRTime aLastAccessedTime) {
|
||||
return SetLastAccessedTime(aLastAccessedTime);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsLocalFile::GetLastModifiedTime(PRTime* aLastModifiedTime) {
|
||||
return GetDateImpl(aLastModifiedTime, TimeField::ModifiedTime,
|
||||
/* aFollowSymlinks = */ true);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsLocalFile::GetLastModifiedTimeOfLink(PRTime* aLastModifiedTime) {
|
||||
return GetDateImpl(aLastModifiedTime, TimeField::ModifiedTime,
|
||||
/* aFollowSymlinks = */ false);
|
||||
// Check we are correctly initialized.
|
||||
CHECK_mWorkingPath();
|
||||
|
||||
if (NS_WARN_IF(!aLastModifiedTime)) {
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
|
||||
// The caller is assumed to have already called IsSymlink
|
||||
// and to have found that this file is a link.
|
||||
|
||||
PRFileInfo64 info;
|
||||
nsresult rv = GetFileInfo(mWorkingPath, &info);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
// microseconds -> milliseconds
|
||||
*aLastModifiedTime = info.modifyTime / PR_USEC_PER_MSEC;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsLocalFile::SetLastModifiedTime(PRTime aLastModifiedTime) {
|
||||
return SetDateImpl(aLastModifiedTime, TimeField::ModifiedTime);
|
||||
// Check we are correctly initialized.
|
||||
CHECK_mWorkingPath();
|
||||
|
||||
nsresult rv = SetModDate(aLastModifiedTime, mWorkingPath.get());
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
MakeDirty();
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
@ -2456,7 +2432,7 @@ nsLocalFile::GetCreationTime(PRTime* aCreationTime) {
|
||||
nsresult rv = ResolveAndStat();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
*aCreationTime = mFileInfo.creationTime / PR_USEC_PER_MSEC;
|
||||
*aCreationTime = mFileInfo64.creationTime / PR_USEC_PER_MSEC;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
@ -2469,7 +2445,7 @@ nsLocalFile::GetCreationTimeOfLink(PRTime* aCreationTime) {
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
|
||||
FileInfo info;
|
||||
PRFileInfo64 info;
|
||||
nsresult rv = GetFileInfo(mWorkingPath, &info);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
@ -2478,15 +2454,11 @@ nsLocalFile::GetCreationTimeOfLink(PRTime* aCreationTime) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult nsLocalFile::SetDateImpl(PRTime aTime,
|
||||
nsLocalFile::TimeField aTimeField) {
|
||||
// Check we are correctly initialized.
|
||||
CHECK_mWorkingPath();
|
||||
|
||||
nsresult nsLocalFile::SetModDate(PRTime aLastModifiedTime,
|
||||
const wchar_t* aFilePath) {
|
||||
// The FILE_FLAG_BACKUP_SEMANTICS is required in order to change the
|
||||
// modification time for directories.
|
||||
HANDLE file =
|
||||
::CreateFileW(mWorkingPath.get(), // pointer to name of the file
|
||||
HANDLE file = ::CreateFileW(aFilePath, // pointer to name of the file
|
||||
GENERIC_WRITE, // access (write) mode
|
||||
0, // share mode
|
||||
nullptr, // pointer to security attributes
|
||||
@ -2502,12 +2474,8 @@ nsresult nsLocalFile::SetDateImpl(PRTime aTime,
|
||||
SYSTEMTIME st;
|
||||
PRExplodedTime pret;
|
||||
|
||||
if (aTime == 0) {
|
||||
aTime = PR_Now();
|
||||
}
|
||||
|
||||
// PR_ExplodeTime expects usecs...
|
||||
PR_ExplodeTime(aTime * PR_USEC_PER_MSEC, PR_GMTParameters, &pret);
|
||||
PR_ExplodeTime(aLastModifiedTime * PR_USEC_PER_MSEC, PR_GMTParameters, &pret);
|
||||
st.wYear = pret.tm_year;
|
||||
st.wMonth =
|
||||
pret.tm_month + 1; // Convert start offset -- Win32: Jan=1; NSPR: Jan=0
|
||||
@ -2518,25 +2486,14 @@ nsresult nsLocalFile::SetDateImpl(PRTime aTime,
|
||||
st.wSecond = pret.tm_sec;
|
||||
st.wMilliseconds = pret.tm_usec / 1000;
|
||||
|
||||
const FILETIME* accessTime = nullptr;
|
||||
const FILETIME* modifiedTime = nullptr;
|
||||
|
||||
if (aTimeField == TimeField::AccessedTime) {
|
||||
accessTime = &ft;
|
||||
} else {
|
||||
modifiedTime = &ft;
|
||||
}
|
||||
|
||||
nsresult rv = NS_OK;
|
||||
|
||||
// if at least one of these fails...
|
||||
if (!(SystemTimeToFileTime(&st, &ft) != 0 &&
|
||||
SetFileTime(file, nullptr, accessTime, modifiedTime) != 0)) {
|
||||
SetFileTime(file, nullptr, &ft, &ft) != 0)) {
|
||||
rv = ConvertWinError(GetLastError());
|
||||
}
|
||||
|
||||
CloseHandle(file);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
@ -2667,7 +2624,7 @@ nsLocalFile::GetFileSize(int64_t* aFileSize) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
*aFileSize = mFileInfo.size;
|
||||
*aFileSize = mFileInfo64.size;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -2683,7 +2640,7 @@ nsLocalFile::GetFileSizeOfLink(int64_t* aFileSize) {
|
||||
// The caller is assumed to have already called IsSymlink
|
||||
// and to have found that this file is a link.
|
||||
|
||||
FileInfo info{};
|
||||
PRFileInfo64 info;
|
||||
if (NS_FAILED(GetFileInfo(mWorkingPath, &info))) {
|
||||
return NS_ERROR_FILE_INVALID_PATH;
|
||||
}
|
||||
@ -2756,7 +2713,7 @@ nsLocalFile::GetDiskSpaceAvailable(int64_t* aDiskSpaceAvailable) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
if (mFileInfo.type == PR_FILE_FILE) {
|
||||
if (mFileInfo64.type == PR_FILE_FILE) {
|
||||
// Since GetDiskFreeSpaceExW works only on directories, use the parent.
|
||||
nsCOMPtr<nsIFile> parent;
|
||||
if (NS_SUCCEEDED(GetParent(getter_AddRefs(parent))) && parent) {
|
||||
@ -2782,7 +2739,7 @@ nsLocalFile::GetDiskCapacity(int64_t* aDiskCapacity) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
if (mFileInfo.type == PR_FILE_FILE) {
|
||||
if (mFileInfo64.type == PR_FILE_FILE) {
|
||||
// Since GetDiskFreeSpaceExW works only on directories, use the parent.
|
||||
nsCOMPtr<nsIFile> parent;
|
||||
if (NS_SUCCEEDED(GetParent(getter_AddRefs(parent))) && parent) {
|
||||
|
@ -53,15 +53,6 @@ class nsLocalFile final : public nsILocalFileWin {
|
||||
// (com1, com2, etc...) and truncates the string if so.
|
||||
static void CheckForReservedFileName(nsString& aFileName);
|
||||
|
||||
// PRFileInfo64 does not hvae an accessTime field;
|
||||
struct FileInfo {
|
||||
PRFileType type;
|
||||
PROffset64 size;
|
||||
PRTime creationTime;
|
||||
PRTime accessTime;
|
||||
PRTime modifyTime;
|
||||
};
|
||||
|
||||
private:
|
||||
// CopyMove and CopySingleFile constants for |options| parameter:
|
||||
enum CopyFileOption {
|
||||
@ -90,7 +81,7 @@ class nsLocalFile final : public nsILocalFileWin {
|
||||
// mWorkingPath
|
||||
nsString mShortWorkingPath;
|
||||
|
||||
FileInfo mFileInfo;
|
||||
PRFileInfo64 mFileInfo64;
|
||||
|
||||
void MakeDirty() {
|
||||
mDirty = true;
|
||||
@ -112,10 +103,7 @@ class nsLocalFile final : public nsILocalFileWin {
|
||||
nsresult CopySingleFile(nsIFile* aSource, nsIFile* aDest,
|
||||
const nsAString& aNewName, uint32_t aOptions);
|
||||
|
||||
enum class TimeField { AccessedTime, ModifiedTime };
|
||||
|
||||
nsresult SetDateImpl(int64_t aTime, TimeField aTimeField);
|
||||
nsresult GetDateImpl(PRTime* aTime, TimeField aTimeField, bool aFollowLinks);
|
||||
nsresult SetModDate(int64_t aLastModifiedTime, const wchar_t* aFilePath);
|
||||
nsresult HasFileAttribute(DWORD aFileAttrib, bool* aResult);
|
||||
nsresult AppendInternal(const nsString& aNode, bool aMultipleComponents);
|
||||
|
||||
|
@ -38,8 +38,8 @@ add_task(function test_normalize_crash_if_media_missing() {
|
||||
});
|
||||
|
||||
// Tests that changing a file's modification time is possible
|
||||
add_task(async function test_file_modification_time() {
|
||||
let file = do_get_profile();
|
||||
add_task(function test_file_modification_time() {
|
||||
var file = do_get_profile();
|
||||
file.append("testfile");
|
||||
|
||||
// Should never happen but get rid of it anyway
|
||||
@ -47,100 +47,36 @@ add_task(async function test_file_modification_time() {
|
||||
file.remove(true);
|
||||
}
|
||||
|
||||
const now = Date.now();
|
||||
var now = Date.now();
|
||||
file.create(Ci.nsIFile.NORMAL_FILE_TYPE, 0o644);
|
||||
Assert.ok(file.exists());
|
||||
|
||||
const atime = file.lastAccessedTime;
|
||||
|
||||
// Modification time may be out by up to 2 seconds on FAT filesystems. Test
|
||||
// with a bit of leeway, close enough probably means it is correct.
|
||||
let diff = Math.abs(file.lastModifiedTime - now);
|
||||
var diff = Math.abs(file.lastModifiedTime - now);
|
||||
Assert.ok(diff < MAX_TIME_DIFFERENCE);
|
||||
|
||||
const yesterday = now - MILLIS_PER_DAY;
|
||||
var yesterday = now - MILLIS_PER_DAY;
|
||||
file.lastModifiedTime = yesterday;
|
||||
|
||||
diff = Math.abs(file.lastModifiedTime - yesterday);
|
||||
Assert.ok(diff < MAX_TIME_DIFFERENCE);
|
||||
Assert.equal(
|
||||
file.lastAccessedTime,
|
||||
atime,
|
||||
"Setting lastModifiedTime should not set lastAccessedTime"
|
||||
);
|
||||
|
||||
const tomorrow = now - MILLIS_PER_DAY;
|
||||
var tomorrow = now - MILLIS_PER_DAY;
|
||||
file.lastModifiedTime = tomorrow;
|
||||
|
||||
diff = Math.abs(file.lastModifiedTime - tomorrow);
|
||||
Assert.ok(diff < MAX_TIME_DIFFERENCE);
|
||||
|
||||
const bug377307 = 1172950238000;
|
||||
var bug377307 = 1172950238000;
|
||||
file.lastModifiedTime = bug377307;
|
||||
|
||||
diff = Math.abs(file.lastModifiedTime - bug377307);
|
||||
Assert.ok(diff < MAX_TIME_DIFFERENCE);
|
||||
|
||||
file.lastModifiedTime = 0;
|
||||
Assert.greater(
|
||||
file.lastModifiedTime,
|
||||
now,
|
||||
"Setting lastModifiedTime to 0 should set it to current date and time"
|
||||
);
|
||||
|
||||
file.remove(true);
|
||||
});
|
||||
|
||||
add_task(function test_lastAccessedTime() {
|
||||
const file = do_get_profile();
|
||||
|
||||
file.append("test-atime");
|
||||
if (file.exists()) {
|
||||
file.remove(true);
|
||||
}
|
||||
|
||||
const now = Date.now();
|
||||
file.create(Ci.nsIFile.NORMAL_FILE_TYPE, 0o644);
|
||||
Assert.ok(file.exists());
|
||||
|
||||
const mtime = file.lastModifiedTime;
|
||||
|
||||
// Modification time may be out by up to 2 seconds on FAT filesystems. Test
|
||||
// with a bit of leeway, close enough probably means it is correct.
|
||||
let diff = Math.abs(file.lastModifiedTime - now);
|
||||
Assert.ok(diff < MAX_TIME_DIFFERENCE);
|
||||
|
||||
const yesterday = now - MILLIS_PER_DAY;
|
||||
file.lastModifiedTime = yesterday;
|
||||
|
||||
diff = Math.abs(file.lastAccessedTime - yesterday);
|
||||
Assert.ok(diff < MAX_TIME_DIFFERENCE);
|
||||
Assert.equal(
|
||||
file.lastModifiedTime,
|
||||
mtime,
|
||||
"Setting lastAccessedTime should not set lastModifiedTime"
|
||||
);
|
||||
|
||||
const tomorrow = now - MILLIS_PER_DAY;
|
||||
file.lastAccessedTime = tomorrow;
|
||||
|
||||
diff = Math.abs(file.lastAccessedTime - tomorrow);
|
||||
Assert.ok(diff < MAX_TIME_DIFFERENCE);
|
||||
|
||||
const bug377307 = 1172950238000;
|
||||
file.lastAccessedTime = bug377307;
|
||||
|
||||
diff = Math.abs(file.lastAccessedTime - bug377307);
|
||||
Assert.ok(diff < MAX_TIME_DIFFERENCE);
|
||||
|
||||
file.lastAccessedTime = 0;
|
||||
Assert.greater(
|
||||
file.lastAccessedTime,
|
||||
now,
|
||||
"Setting lastAccessedTime to 0 should set it to the current date and time"
|
||||
);
|
||||
});
|
||||
|
||||
// Tests that changing a directory's modification time is possible
|
||||
add_task(function test_directory_modification_time() {
|
||||
var dir = do_get_profile();
|
||||
|
Loading…
Reference in New Issue
Block a user