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:
Cristian Tuns 2022-11-16 13:58:36 -05:00
parent 7124a20f47
commit c93d8c6464
10 changed files with 143 additions and 417 deletions

View File

@ -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.
*

View File

@ -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 */

View File

@ -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;
};

View File

@ -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");

View File

@ -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

View File

@ -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

View File

@ -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)

View File

@ -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) {

View File

@ -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);

View File

@ -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();