зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1786608 - Add nsIFile::accessTime{,OfLink} r=xpcom-reviewers,nika
Differential Revision: https://phabricator.services.mozilla.com/D155926
This commit is contained in:
Родитель
6d99f6fc5c
Коммит
6d359be1d0
|
@ -243,6 +243,13 @@ 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,10 +1155,11 @@ nsLocalFile::Remove(bool aRecursive) {
|
|||
return NSRESULT_FOR_RETURN(rmdir(mPath.get()));
|
||||
}
|
||||
|
||||
nsresult nsLocalFile::GetLastModifiedTimeImpl(PRTime* aLastModTime,
|
||||
bool aFollowLinks) {
|
||||
nsresult nsLocalFile::GetTimeImpl(PRTime* aTime,
|
||||
nsLocalFile::TimeField aTimeField,
|
||||
bool aFollowLinks) {
|
||||
CHECK_mPath();
|
||||
if (NS_WARN_IF(!aLastModTime)) {
|
||||
if (NS_WARN_IF(!aTime)) {
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
|
||||
|
@ -1170,17 +1171,36 @@ nsresult nsLocalFile::GetLastModifiedTimeImpl(PRTime* aLastModTime,
|
|||
return NSRESULT_FOR_ERRNO();
|
||||
}
|
||||
|
||||
struct timespec* timespec;
|
||||
switch (aTimeField) {
|
||||
case TimeField::AccessedTime:
|
||||
#if (defined(__APPLE__) && defined(__MACH__))
|
||||
*aLastModTime = TimespecToMillis(fileStats.st_mtimespec);
|
||||
timespec = &fileStats.st_atimespec;
|
||||
#else
|
||||
*aLastModTime = TimespecToMillis(fileStats.st_mtim);
|
||||
timespec = &fileStats.st_atim;
|
||||
#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::SetLastModifiedTimeImpl(PRTime aLastModTime,
|
||||
bool aFollowLinks) {
|
||||
nsresult nsLocalFile::SetTimeImpl(PRTime aTime,
|
||||
nsLocalFile::TimeField aTimeField,
|
||||
bool aFollowLinks) {
|
||||
CHECK_mPath();
|
||||
|
||||
using UtimesFn = int (*)(const char*, const timeval*);
|
||||
|
@ -1192,49 +1212,82 @@ nsresult nsLocalFile::SetLastModifiedTimeImpl(PRTime aLastModTime,
|
|||
}
|
||||
#endif
|
||||
|
||||
int result;
|
||||
if (aLastModTime != 0) {
|
||||
ENSURE_STAT_CACHE();
|
||||
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;
|
||||
ENSURE_STAT_CACHE();
|
||||
|
||||
timeval times[2];
|
||||
times[0] = access;
|
||||
times[1] = modification;
|
||||
result = utimesFn(mPath.get(), times);
|
||||
} else {
|
||||
result = utimesFn(mPath.get(), nullptr);
|
||||
if (aTime == 0) {
|
||||
aTime = PR_Now();
|
||||
}
|
||||
|
||||
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);
|
||||
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 GetLastModifiedTimeImpl(aLastModTime, /* follow links? */ true);
|
||||
return GetTimeImpl(aLastModTime, TimeField::ModifiedTime,
|
||||
/* follow links? */ true);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsLocalFile::SetLastModifiedTime(PRTime aLastModTime) {
|
||||
return SetLastModifiedTimeImpl(aLastModTime, /* follow links ? */ true);
|
||||
return SetTimeImpl(aLastModTime, TimeField::ModifiedTime,
|
||||
/* follow links ? */ true);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsLocalFile::GetLastModifiedTimeOfLink(PRTime* aLastModTimeOfLink) {
|
||||
return GetLastModifiedTimeImpl(aLastModTimeOfLink, /* follow link? */ false);
|
||||
return GetTimeImpl(aLastModTimeOfLink, TimeField::ModifiedTime,
|
||||
/* follow link? */ false);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsLocalFile::SetLastModifiedTimeOfLink(PRTime aLastModTimeOfLink) {
|
||||
return SetLastModifiedTimeImpl(aLastModTimeOfLink, /* follow links? */ false);
|
||||
return SetTimeImpl(aLastModTimeOfLink, TimeField::ModifiedTime,
|
||||
/* follow links? */ false);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
|
|
@ -85,8 +85,10 @@ class nsLocalFile final
|
|||
nsresult CreateAndKeepOpen(uint32_t aType, int aFlags, uint32_t aPermissions,
|
||||
bool aSkipAncestors, PRFileDesc** aResult);
|
||||
|
||||
nsresult SetLastModifiedTimeImpl(PRTime aLastModTime, bool aFollowLinks);
|
||||
nsresult GetLastModifiedTimeImpl(PRTime* aLastModTime, bool aFollowLinks);
|
||||
enum class TimeField { AccessedTime, ModifiedTime };
|
||||
nsresult SetTimeImpl(PRTime aTime, TimeField aTimeField, bool aFollowLinks);
|
||||
nsresult GetTimeImpl(PRTime* aTime, TimeField aTimeField, bool aFollowLinks);
|
||||
|
||||
nsresult GetCreationTimeImpl(PRTime* aCreationTime, bool aFollowLinks);
|
||||
|
||||
#if defined(USE_LINUX_QUOTACTL)
|
||||
|
|
|
@ -607,7 +607,8 @@ 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, PRFileInfo64* aInfo) {
|
||||
static nsresult GetFileInfo(const nsString& aName,
|
||||
nsLocalFile::FileInfo* aInfo) {
|
||||
if (aName.IsEmpty()) {
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
|
@ -638,8 +639,6 @@ static nsresult GetFileInfo(const nsString& aName, PRFileInfo64* aInfo) {
|
|||
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;
|
||||
|
@ -647,6 +646,9 @@ static nsresult GetFileInfo(const nsString& aName, PRFileInfo64* aInfo) {
|
|||
FileTimeToPRTime(&fileData.ftCreationTime, &aInfo->creationTime);
|
||||
}
|
||||
|
||||
FileTimeToPRTime(&fileData.fLastAccessTime, &aInfo->accessTime);
|
||||
FileTimeToPRTime(&fileData.ftLastWriteTime, &aInfo->modifyTime);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -924,7 +926,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 mFileInfo64 can be used.
|
||||
// the path is guaranteed valid and the members of mFileInfo can be used.
|
||||
nsresult nsLocalFile::ResolveAndStat() {
|
||||
// if we aren't dirty then we are already done
|
||||
if (!mDirty) {
|
||||
|
@ -948,12 +950,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, &mFileInfo64);
|
||||
nsresult rv = GetFileInfo(nsprPath, &mFileInfo);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
if (mFileInfo64.type != PR_FILE_OTHER) {
|
||||
if (mFileInfo.type != PR_FILE_OTHER) {
|
||||
mResolveDirty = false;
|
||||
mDirty = false;
|
||||
return NS_OK;
|
||||
|
@ -970,7 +972,7 @@ nsresult nsLocalFile::ResolveAndStat() {
|
|||
|
||||
mResolveDirty = false;
|
||||
// get the details of the resolved path
|
||||
rv = GetFileInfo(mResolvedPath, &mFileInfo64);
|
||||
rv = GetFileInfo(mResolvedPath, &mFileInfo);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
@ -2356,8 +2358,9 @@ nsLocalFile::Remove(bool aRecursive) {
|
|||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsLocalFile::GetLastModifiedTime(PRTime* aLastModifiedTime) {
|
||||
nsresult nsLocalFile::GetDateImpl(PRTime* aTime,
|
||||
nsLocalFile::TimeField aTimeField,
|
||||
bool aFollowLinks) {
|
||||
// Check we are correctly initialized.
|
||||
CHECK_mWorkingPath();
|
||||
|
||||
|
@ -2365,55 +2368,77 @@ nsLocalFile::GetLastModifiedTime(PRTime* aLastModifiedTime) {
|
|||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
|
||||
// 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)
|
||||
FileInfo symlinkInfo;
|
||||
FileInfo* pInfo;
|
||||
|
||||
nsresult rv = ResolveAndStat();
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
if (aFollowLinks) {
|
||||
if (nsresult rv = GetFileInfo(mWorkingPath, &info); 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_PR_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(aLastModified, TimeField::ModifiedTime,
|
||||
/* aFollowSymlinks = */ true);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsLocalFile::GetLastModifiedTimeOfLink(PRTime* aLastModifiedTime) {
|
||||
// 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;
|
||||
return GetDateImpl(aLastModified, TimeField::ModifiedTime,
|
||||
/* aFollowSymlinks = */ false);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsLocalFile::SetLastModifiedTime(PRTime aLastModifiedTime) {
|
||||
// Check we are correctly initialized.
|
||||
CHECK_mWorkingPath();
|
||||
|
||||
nsresult rv = SetModDate(aLastModifiedTime, mWorkingPath.get());
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
MakeDirty();
|
||||
}
|
||||
|
||||
return rv;
|
||||
return SetDateImpl(aLastModifiedTime, TimeField::ModifiedTime);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
@ -2454,17 +2479,21 @@ nsLocalFile::GetCreationTimeOfLink(PRTime* aCreationTime) {
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult nsLocalFile::SetModDate(PRTime aLastModifiedTime,
|
||||
const wchar_t* aFilePath) {
|
||||
nsresult nsLocalFile::SetDateImpl(PRTime aTime,
|
||||
nsLocalFile::TimeField aTimeField) {
|
||||
// Check we are correctly initialized.
|
||||
CHECK_mWorkingPath();
|
||||
|
||||
// The FILE_FLAG_BACKUP_SEMANTICS is required in order to change the
|
||||
// modification time for directories.
|
||||
HANDLE file = ::CreateFileW(aFilePath, // pointer to name of the file
|
||||
GENERIC_WRITE, // access (write) mode
|
||||
0, // share mode
|
||||
nullptr, // pointer to security attributes
|
||||
OPEN_EXISTING, // how to create
|
||||
FILE_FLAG_BACKUP_SEMANTICS, // file attributes
|
||||
nullptr);
|
||||
HANDLE file =
|
||||
::CreateFileW(mWorkingPath.get(), // pointer to name of the file
|
||||
GENERIC_WRITE, // access (write) mode
|
||||
0, // share mode
|
||||
nullptr, // pointer to security attributes
|
||||
OPEN_EXISTING, // how to create
|
||||
FILE_FLAG_BACKUP_SEMANTICS, // file attributes
|
||||
nullptr);
|
||||
|
||||
if (file == INVALID_HANDLE_VALUE) {
|
||||
return ConvertWinError(GetLastError());
|
||||
|
@ -2474,8 +2503,12 @@ nsresult nsLocalFile::SetModDate(PRTime aLastModifiedTime,
|
|||
SYSTEMTIME st;
|
||||
PRExplodedTime pret;
|
||||
|
||||
if (aTime == 0) {
|
||||
aTime = PR_Now();
|
||||
}
|
||||
|
||||
// PR_ExplodeTime expects usecs...
|
||||
PR_ExplodeTime(aLastModifiedTime * PR_USEC_PER_MSEC, PR_GMTParameters, &pret);
|
||||
PR_ExplodeTime(aTime * 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
|
||||
|
@ -2486,14 +2519,23 @@ nsresult nsLocalFile::SetModDate(PRTime aLastModifiedTime,
|
|||
st.wSecond = pret.tm_sec;
|
||||
st.wMilliseconds = pret.tm_usec / 1000;
|
||||
|
||||
nsresult rv = NS_OK;
|
||||
const FILETIME* accessTime = nullptr;
|
||||
const FILETIME* modifiedTime = nullptr;
|
||||
|
||||
if (aTimeField == TimeField::AccessedTime) {
|
||||
accessTime = &ft;
|
||||
} else {
|
||||
modifiedTime = &ft;
|
||||
}
|
||||
|
||||
// if at least one of these fails...
|
||||
if (!(SystemTimeToFileTime(&st, &ft) != 0 &&
|
||||
SetFileTime(file, nullptr, nullptr, &ft) != 0)) {
|
||||
SetFileTime(file, nullptr, accessTime, modifiedTime) != 0)) {
|
||||
rv = ConvertWinError(GetLastError());
|
||||
}
|
||||
|
||||
CloseHandle(file);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
|
|
@ -53,6 +53,15 @@ 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 {
|
||||
|
@ -81,7 +90,7 @@ class nsLocalFile final : public nsILocalFileWin {
|
|||
// mWorkingPath
|
||||
nsString mShortWorkingPath;
|
||||
|
||||
PRFileInfo64 mFileInfo64;
|
||||
FileInfo mFileInfo;
|
||||
|
||||
void MakeDirty() {
|
||||
mDirty = true;
|
||||
|
@ -103,7 +112,10 @@ class nsLocalFile final : public nsILocalFileWin {
|
|||
nsresult CopySingleFile(nsIFile* aSource, nsIFile* aDest,
|
||||
const nsAString& aNewName, uint32_t aOptions);
|
||||
|
||||
nsresult SetModDate(int64_t aLastModifiedTime, const wchar_t* aFilePath);
|
||||
enum class TimeField { AccessedTime, ModifiedTime };
|
||||
|
||||
nsresult SetDateImpl(int64_t aTime, TimeField aTimeField);
|
||||
nsresult GetDateImpl(PRTime* aTime, TimeField aTimeField, bool aFollowLinks);
|
||||
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(function test_file_modification_time() {
|
||||
var file = do_get_profile();
|
||||
add_task(async function test_file_modification_time() {
|
||||
let file = do_get_profile();
|
||||
file.append("testfile");
|
||||
|
||||
// Should never happen but get rid of it anyway
|
||||
|
@ -47,36 +47,100 @@ add_task(function test_file_modification_time() {
|
|||
file.remove(true);
|
||||
}
|
||||
|
||||
var now = Date.now();
|
||||
const 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.
|
||||
var diff = Math.abs(file.lastModifiedTime - now);
|
||||
let diff = Math.abs(file.lastModifiedTime - now);
|
||||
Assert.ok(diff < MAX_TIME_DIFFERENCE);
|
||||
|
||||
var yesterday = now - MILLIS_PER_DAY;
|
||||
const 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"
|
||||
);
|
||||
|
||||
var tomorrow = now - MILLIS_PER_DAY;
|
||||
const tomorrow = now - MILLIS_PER_DAY;
|
||||
file.lastModifiedTime = tomorrow;
|
||||
|
||||
diff = Math.abs(file.lastModifiedTime - tomorrow);
|
||||
Assert.ok(diff < MAX_TIME_DIFFERENCE);
|
||||
|
||||
var bug377307 = 1172950238000;
|
||||
const 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();
|
||||
|
|
Загрузка…
Ссылка в новой задаче