зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1660841 - Provide file creation time via nsIFile::creationTime{,ofLink} r=nika
Differential Revision: https://phabricator.services.mozilla.com/D96889
This commit is contained in:
Родитель
3ab2f47c1c
Коммит
e0e9d2d31b
|
@ -311,6 +311,16 @@ FileDescriptorFile::SetLastModifiedTimeOfLink(PRTime aLastModTimeOfLink) {
|
|||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
FileDescriptorFile::GetCreationTime(PRTime* aCreationTime) {
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
FileDescriptorFile::GetCreationTimeOfLink(PRTime* aCreationTime) {
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
FileDescriptorFile::GetFileSize(int64_t* aFileSize) {
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
|
|
|
@ -233,6 +233,16 @@ interface nsIFile : nsISupports
|
|||
attribute PRTime lastModifiedTime;
|
||||
attribute PRTime lastModifiedTimeOfLink;
|
||||
|
||||
/**
|
||||
* The creation time of file in milliseconds from midnight, January 1, 1970
|
||||
* GMT, if available.
|
||||
*
|
||||
* This attribute is only implemented on Windows and macOS. Accessing this
|
||||
* on another platform will this will throw NS_ERROR_NOT_IMPLEMENTED.
|
||||
*/
|
||||
readonly attribute PRTime creationTime;
|
||||
readonly attribute PRTime creationTimeOfLink;
|
||||
|
||||
/**
|
||||
* WARNING! On the Mac, getting/setting the file size with nsIFile
|
||||
* only deals with the size of the data fork. If you need to
|
||||
|
|
|
@ -126,6 +126,11 @@ using namespace mozilla;
|
|||
return NS_ERROR_FILE_ACCESS_DENIED; \
|
||||
} while (0)
|
||||
|
||||
static PRTime TimespecToMillis(const struct timespec& aTimeSpec) {
|
||||
return PRTime(aTimeSpec.tv_sec) * PR_MSEC_PER_SEC +
|
||||
PRTime(aTimeSpec.tv_nsec) / PR_NSEC_PER_MSEC;
|
||||
}
|
||||
|
||||
/* directory enumerator */
|
||||
class nsDirEnumeratorUnix final : public nsSimpleEnumerator,
|
||||
public nsIDirectoryEnumerator {
|
||||
|
@ -1134,17 +1139,11 @@ nsresult nsLocalFile::GetLastModifiedTimeImpl(PRTime* aLastModTime,
|
|||
return NSRESULT_FOR_ERRNO();
|
||||
}
|
||||
|
||||
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;
|
||||
*aLastModTime = TimespecToMillis(fileStats.st_mtimespec);
|
||||
#else
|
||||
modSec = fileStats.st_mtim.tv_sec;
|
||||
modNSec = fileStats.st_mtim.tv_nsec;
|
||||
*aLastModTime = TimespecToMillis(fileStats.st_mtim);
|
||||
#endif
|
||||
*aLastModTime =
|
||||
PRTime(modSec * PR_MSEC_PER_SEC) + PRTime(modNSec / PR_NSEC_PER_MSEC);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -1207,6 +1206,39 @@ nsLocalFile::SetLastModifiedTimeOfLink(PRTime aLastModTimeOfLink) {
|
|||
return SetLastModifiedTimeImpl(aLastModTimeOfLink, /* follow links? */ false);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsLocalFile::GetCreationTime(PRTime* aCreationTime) {
|
||||
return GetCreationTimeImpl(aCreationTime, false);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsLocalFile::GetCreationTimeOfLink(PRTime* aCreationTimeOfLink) {
|
||||
return GetCreationTimeImpl(aCreationTimeOfLink, /* aFollowLinks = */ true);
|
||||
}
|
||||
|
||||
nsresult nsLocalFile::GetCreationTimeImpl(PRTime* aCreationTime,
|
||||
bool aFollowLinks) {
|
||||
CHECK_mPath();
|
||||
if (NS_WARN_IF(!aCreationTime)) {
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
|
||||
#if defined(_DARWIN_FEATURE_64_BIT_INODE)
|
||||
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();
|
||||
}
|
||||
|
||||
*aCreationTime = TimespecToMillis(fileStats.st_birthtimespec);
|
||||
return NS_OK;
|
||||
#else
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* Only send back permissions bits: maybe we want to send back the whole
|
||||
* mode_t to permit checks against other file types?
|
||||
|
@ -1600,7 +1632,8 @@ nsLocalFile::IsExecutable(bool* aResult) {
|
|||
static const char* const executableExts[] = {
|
||||
"air", // Adobe AIR installer
|
||||
#ifdef MOZ_WIDGET_COCOA
|
||||
"fileloc", // File location files can be used to point to other files.
|
||||
"fileloc", // File location files can be used to point to other
|
||||
// files.
|
||||
#endif
|
||||
"jar" // java application bundle
|
||||
};
|
||||
|
@ -2238,7 +2271,8 @@ static nsresult MacErrorMapper(OSErr inErr) {
|
|||
}
|
||||
|
||||
static nsresult CFStringReftoUTF8(CFStringRef aInStrRef, nsACString& aOutStr) {
|
||||
// first see if the conversion would succeed and find the length of the result
|
||||
// first see if the conversion would succeed and find the length of the
|
||||
// result
|
||||
CFIndex usedBufLen, inStrLen = ::CFStringGetLength(aInStrRef);
|
||||
CFIndex charsConverted = ::CFStringGetBytes(
|
||||
aInStrRef, CFRangeMake(0, inStrLen), kCFStringEncodingUTF8, 0, false,
|
||||
|
|
|
@ -88,6 +88,7 @@ class nsLocalFile final
|
|||
|
||||
nsresult SetLastModifiedTimeImpl(PRTime aLastModTime, bool aFollowLinks);
|
||||
nsresult GetLastModifiedTimeImpl(PRTime* aLastModTime, bool aFollowLinks);
|
||||
nsresult GetCreationTimeImpl(PRTime* aCreationTime, bool aFollowLinks);
|
||||
};
|
||||
|
||||
#endif /* _nsLocalFileUNIX_H_ */
|
||||
|
|
|
@ -2225,6 +2225,39 @@ nsLocalFile::SetLastModifiedTimeOfLink(PRTime aLastModifiedTime) {
|
|||
return SetLastModifiedTime(aLastModifiedTime);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsLocalFile::GetCreationTime(PRTime* aCreationTime) {
|
||||
CHECK_mWorkingPath();
|
||||
|
||||
if (NS_WARN_IF(!aCreationTime)) {
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
|
||||
nsresult rv = ResolveAndStat();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
*aCreationTime = mFileInfo64.creationTime / PR_USEC_PER_MSEC;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsLocalFile::GetCreationTimeOfLink(PRTime* aCreationTime) {
|
||||
CHECK_mWorkingPath();
|
||||
|
||||
if (NS_WARN_IF(!aCreationTime)) {
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
|
||||
PRFileInfo64 info;
|
||||
nsresult rv = GetFileInfo(mWorkingPath, &info);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
*aCreationTime = info.creationTime / PR_USEC_PER_MSEC;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult nsLocalFile::SetModDate(PRTime aLastModifiedTime,
|
||||
const wchar_t* aFilePath) {
|
||||
// The FILE_FLAG_BACKUP_SEMANTICS is required in order to change the
|
||||
|
|
|
@ -134,3 +134,40 @@ function test_diskSpaceAvailable() {
|
|||
|
||||
file.remove(true);
|
||||
}
|
||||
|
||||
function test_file_creation_time() {
|
||||
const file = do_get_profile();
|
||||
file.append("testfile");
|
||||
|
||||
if (file.exists()) {
|
||||
file.remove(true);
|
||||
}
|
||||
|
||||
const now = Date.now();
|
||||
|
||||
file.create(Ci.nsIFile.NORMAL_FILE_TYPE, 0o644);
|
||||
Assert.ok(file.exists());
|
||||
|
||||
let creationTime;
|
||||
try {
|
||||
creationTime = file.creationTime;
|
||||
} catch (e) {
|
||||
if (e.name === "NS_ERROR_NOT_AVAILABLE") {
|
||||
// Creation time is not supported on this platform.
|
||||
file.remove(true);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
const diff = Math.abs(creationTime - now);
|
||||
Assert.ok(diff < MAX_TIME_DIFFERENCE);
|
||||
|
||||
Assert.ok(creationTime === file.lastModifiedTime);
|
||||
|
||||
file.lastModifiedTime = now + MILLIS_PER_DAY;
|
||||
|
||||
Assert.ok(creationTime !== file.lastModifiedTime);
|
||||
Assert.ok(creationTime === file.creationTime);
|
||||
|
||||
file.remove(true);
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче