mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-24 05:11:16 +00:00
Bug 1657663: Improve timestamp precision for nsLocalFileUnix r=froydnj,barret
This change updates the unix implementation of nsLocalFile Set/GetLastModifiedTime methods to improve the precision of file modification times from a 1 second resolution to a 1 millisecond resolution. Differential Revision: https://phabricator.services.mozilla.com/D86238
This commit is contained in:
parent
e51e603b3c
commit
53c14a2428
@ -1128,7 +1128,7 @@ fi
|
||||
|
||||
dnl Checks for library functions.
|
||||
dnl ========================================================
|
||||
AC_CHECK_FUNCS(stat64 lstat64 truncate64 statvfs64 statvfs statfs64 statfs getpagesize gmtime_r localtime_r arc4random arc4random_buf mallinfo gettid lchown setpriority strerror syscall)
|
||||
AC_CHECK_FUNCS(stat64 lstat64 truncate64 statvfs64 statvfs statfs64 statfs getpagesize gmtime_r localtime_r arc4random arc4random_buf mallinfo gettid lchown setpriority strerror syscall lutimes)
|
||||
|
||||
dnl check for clock_gettime(), the CLOCK_MONOTONIC clock
|
||||
AC_CACHE_CHECK(for clock_gettime(CLOCK_MONOTONIC),
|
||||
|
@ -13,9 +13,13 @@
|
||||
#include "mozilla/DebugOnly.h"
|
||||
#include "mozilla/Sprintf.h"
|
||||
#include "mozilla/FilePreferences.h"
|
||||
#include "prtime.h"
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/fcntl.h>
|
||||
#include <sys/select.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
@ -1073,68 +1077,92 @@ nsLocalFile::Remove(bool aRecursive) {
|
||||
return NSRESULT_FOR_RETURN(rmdir(mPath.get()));
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsLocalFile::GetLastModifiedTime(PRTime* aLastModTime) {
|
||||
nsresult nsLocalFile::GetLastModifiedTimeImpl(PRTime* aLastModTime,
|
||||
bool aFollowLinks) {
|
||||
CHECK_mPath();
|
||||
if (NS_WARN_IF(!aLastModTime)) {
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
|
||||
PRFileInfo64 info;
|
||||
if (PR_GetFileInfo64(mPath.get(), &info) != PR_SUCCESS) {
|
||||
using StatFn = int (*)(const char*, struct STAT*);
|
||||
StatFn statFn = aFollowLinks ? &STAT : &LSTAT;
|
||||
|
||||
struct STAT fileStats {};
|
||||
if (statFn(mPath.get(), &fileStats) < 0) {
|
||||
return NSRESULT_FOR_ERRNO();
|
||||
}
|
||||
PRTime modTime = info.modifyTime;
|
||||
if (modTime == 0) {
|
||||
*aLastModTime = 0;
|
||||
} else {
|
||||
*aLastModTime = modTime / PR_USEC_PER_MSEC;
|
||||
}
|
||||
|
||||
int64_t modSec = 0;
|
||||
int64_t modNSec = 0;
|
||||
#if (defined(__APPLE__) && defined(__MACH__))
|
||||
modSec = fileStats.st_mtimespec.tv_sec;
|
||||
modNSec = fileStats.st_mtimespec.tv_nsec;
|
||||
#else
|
||||
modSec = fileStats.st_mtim.tv_sec;
|
||||
modNSec = fileStats.st_mtim.tv_nsec;
|
||||
#endif
|
||||
*aLastModTime =
|
||||
PRTime(modSec * PR_MSEC_PER_SEC) + PRTime(modNSec / PR_NSEC_PER_MSEC);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsLocalFile::SetLastModifiedTime(PRTime aLastModTime) {
|
||||
nsresult nsLocalFile::SetLastModifiedTimeImpl(PRTime aLastModTime,
|
||||
bool aFollowLinks) {
|
||||
CHECK_mPath();
|
||||
|
||||
using UtimesFn = int (*)(const char*, const timeval*);
|
||||
UtimesFn utimesFn = &utimes;
|
||||
|
||||
#if HAVE_LUTIMES
|
||||
if (!aFollowLinks) {
|
||||
utimesFn = &lutimes;
|
||||
}
|
||||
#endif
|
||||
|
||||
int result;
|
||||
if (aLastModTime != 0) {
|
||||
ENSURE_STAT_CACHE();
|
||||
struct utimbuf ut;
|
||||
ut.actime = mCachedStat.st_atime;
|
||||
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;
|
||||
|
||||
// convert milliseconds to seconds since the unix epoch
|
||||
ut.modtime = (time_t)(aLastModTime / PR_MSEC_PER_SEC);
|
||||
result = utime(mPath.get(), &ut);
|
||||
timeval times[2];
|
||||
times[0] = access;
|
||||
times[1] = modification;
|
||||
result = utimesFn(mPath.get(), times);
|
||||
} else {
|
||||
result = utime(mPath.get(), nullptr);
|
||||
result = utimesFn(mPath.get(), nullptr);
|
||||
}
|
||||
return NSRESULT_FOR_RETURN(result);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsLocalFile::GetLastModifiedTimeOfLink(PRTime* aLastModTimeOfLink) {
|
||||
CHECK_mPath();
|
||||
if (NS_WARN_IF(!aLastModTimeOfLink)) {
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
|
||||
struct STAT sbuf;
|
||||
if (LSTAT(mPath.get(), &sbuf) == -1) {
|
||||
return NSRESULT_FOR_ERRNO();
|
||||
}
|
||||
*aLastModTimeOfLink = PRTime(sbuf.st_mtime) * PR_MSEC_PER_SEC;
|
||||
|
||||
return NS_OK;
|
||||
nsLocalFile::GetLastModifiedTime(PRTime* aLastModTime) {
|
||||
return GetLastModifiedTimeImpl(aLastModTime, /* follow links? */ true);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsLocalFile::SetLastModifiedTime(PRTime aLastModTime) {
|
||||
return SetLastModifiedTimeImpl(aLastModTime, /* follow links ? */ true);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsLocalFile::GetLastModifiedTimeOfLink(PRTime* aLastModTimeOfLink) {
|
||||
return GetLastModifiedTimeImpl(aLastModTimeOfLink, /* follow link? */ false);
|
||||
}
|
||||
|
||||
/*
|
||||
* utime(2) may or may not dereference symlinks, joy.
|
||||
*/
|
||||
NS_IMETHODIMP
|
||||
nsLocalFile::SetLastModifiedTimeOfLink(PRTime aLastModTimeOfLink) {
|
||||
return SetLastModifiedTime(aLastModTimeOfLink);
|
||||
return SetLastModifiedTimeImpl(aLastModTimeOfLink, /* follow links? */ false);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -122,6 +122,9 @@ class nsLocalFile final
|
||||
|
||||
nsresult CreateAndKeepOpen(uint32_t aType, int aFlags, uint32_t aPermissions,
|
||||
PRFileDesc** aResult);
|
||||
|
||||
nsresult SetLastModifiedTimeImpl(PRTime aLastModTime, bool aFollowLinks);
|
||||
nsresult GetLastModifiedTimeImpl(PRTime* aLastModTime, bool aFollowLinks);
|
||||
};
|
||||
|
||||
#endif /* _nsLocalFileUNIX_H_ */
|
||||
|
Loading…
Reference in New Issue
Block a user