mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-09 11:25:00 +00:00
Optimize Mac OS X filesystem time methods. Clean up UNIX time methods wrt LL_ macro usage. b=489015 r=mstange sr=roc
This commit is contained in:
parent
9a2bec39e8
commit
d19f83697a
@ -46,6 +46,15 @@
|
||||
|
||||
class nsDirEnumerator;
|
||||
|
||||
// Mac OS X 10.4 does not have stat64/lstat64
|
||||
#if defined(HAVE_STAT64) && defined(HAVE_LSTAT64) && (MAC_OS_X_VERSION_MIN_REQUIRED > MAC_OS_X_VERSION_10_4)
|
||||
#define STAT stat64
|
||||
#define LSTAT lstat64
|
||||
#else
|
||||
#define STAT stat
|
||||
#define LSTAT lstat
|
||||
#endif
|
||||
|
||||
// The native charset of this implementation is UTF-8. The Unicode used by the
|
||||
// Mac OS file system is decomposed, so "Native" versions of these routines will
|
||||
// always use decomposed Unicode (NFD). Their "non-Native" counterparts are
|
||||
@ -92,8 +101,6 @@ protected:
|
||||
const nsAString& newName,
|
||||
PRBool followLinks);
|
||||
|
||||
static PRInt64 HFSPlustoNSPRTime(const UTCDateTime& utcTime);
|
||||
static void NSPRtoHFSPlusTime(PRInt64 nsprTime, UTCDateTime& utcTime);
|
||||
static nsresult CFStringReftoUTF8(CFStringRef aInStrRef, nsACString& aOutStr);
|
||||
|
||||
protected:
|
||||
|
@ -65,6 +65,7 @@
|
||||
#include <unistd.h>
|
||||
#include <sys/stat.h>
|
||||
#include <stdlib.h>
|
||||
#include <utime.h>
|
||||
|
||||
#define CHECK_mBaseURL() \
|
||||
PR_BEGIN_MACRO \
|
||||
@ -283,11 +284,6 @@ NS_IMPL_ISUPPORTS2(nsDirEnumerator, nsISimpleEnumerator, nsIDirectoryEnumerator)
|
||||
|
||||
const char kPathSepChar = '/';
|
||||
|
||||
// The HFS+ epoch is Jan. 1, 1904 GMT - differs from HFS in which times were local
|
||||
// The NSPR epoch is Jan. 1, 1970 GMT
|
||||
// 2082844800 is the difference in seconds between those dates
|
||||
const PRInt64 kJanuaryFirst1970Seconds = 2082844800LL;
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark [CTORs/DTOR]
|
||||
|
||||
@ -816,81 +812,73 @@ NS_IMETHODIMP nsLocalFile::SetPermissionsOfLink(PRUint32 aPermissionsOfLink)
|
||||
|
||||
NS_IMETHODIMP nsLocalFile::GetLastModifiedTime(PRInt64 *aLastModifiedTime)
|
||||
{
|
||||
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
|
||||
|
||||
// Check we are correctly initialized.
|
||||
CHECK_mBaseURL();
|
||||
|
||||
NS_ENSURE_ARG_POINTER(aLastModifiedTime);
|
||||
|
||||
FSRef fsRef;
|
||||
nsresult rv = GetFSRefInternal(fsRef);
|
||||
|
||||
nsCAutoString path;
|
||||
nsresult rv = GetPathInternal(path);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
FSCatalogInfo catalogInfo;
|
||||
OSErr err = ::FSGetCatalogInfo(&fsRef, kFSCatInfoContentMod, &catalogInfo,
|
||||
nsnull, nsnull, nsnull);
|
||||
if (err != noErr)
|
||||
return MacErrorMapper(err);
|
||||
*aLastModifiedTime = HFSPlustoNSPRTime(catalogInfo.contentModDate);
|
||||
return NS_OK;
|
||||
|
||||
NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
|
||||
PRFileInfo64 info;
|
||||
if (PR_GetFileInfo64(path.get(), &info) != PR_SUCCESS)
|
||||
return NSRESULT_FOR_ERRNO();
|
||||
PRInt64 modTime = PRInt64(info.modifyTime);
|
||||
if (modTime == 0)
|
||||
*aLastModifiedTime = 0;
|
||||
else
|
||||
*aLastModifiedTime = modTime / PRInt64(PR_USEC_PER_MSEC);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsLocalFile::SetLastModifiedTime(PRInt64 aLastModifiedTime)
|
||||
{
|
||||
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
|
||||
|
||||
// Check we are correctly initialized.
|
||||
CHECK_mBaseURL();
|
||||
|
||||
OSErr err;
|
||||
nsresult rv;
|
||||
FSRef fsRef;
|
||||
FSCatalogInfo catalogInfo;
|
||||
|
||||
rv = GetFSRefInternal(fsRef);
|
||||
nsCAutoString path;
|
||||
nsresult rv = GetPathInternal(path);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
FSRef parentRef;
|
||||
PRBool notifyParent;
|
||||
int result;
|
||||
if (aLastModifiedTime != 0) {
|
||||
struct STAT statBuf;
|
||||
if (STAT(path.get(), &statBuf) == -1) {
|
||||
// try lstat it may be a symlink
|
||||
if (LSTAT(path.get(), &statBuf) == -1)
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
// Get the node flags, the content modification date and time, and the parent ref
|
||||
err = ::FSGetCatalogInfo(&fsRef, kFSCatInfoNodeFlags + kFSCatInfoContentMod,
|
||||
&catalogInfo, NULL, NULL, &parentRef);
|
||||
if (err != noErr)
|
||||
return MacErrorMapper(err);
|
||||
|
||||
// Notify the parent if this is a file
|
||||
notifyParent = (0 == (catalogInfo.nodeFlags & kFSNodeIsDirectoryMask));
|
||||
struct utimbuf ut;
|
||||
ut.actime = statBuf.st_atime;
|
||||
|
||||
NSPRtoHFSPlusTime(aLastModifiedTime, catalogInfo.contentModDate);
|
||||
err = ::FSSetCatalogInfo(&fsRef, kFSCatInfoContentMod, &catalogInfo);
|
||||
if (err != noErr)
|
||||
return MacErrorMapper(err);
|
||||
|
||||
// Send a notification for the parent of the file, or for the directory
|
||||
err = FNNotify(notifyParent ? &parentRef : &fsRef, kFNDirectoryModifiedMessage, kNilOptions);
|
||||
if (err != noErr)
|
||||
return MacErrorMapper(err);
|
||||
|
||||
return NS_OK;
|
||||
|
||||
NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
|
||||
// convert milliseconds to seconds since the unix epoch
|
||||
ut.modtime = (time_t)(PRFloat64(aLastModifiedTime) / PR_MSEC_PER_SEC);
|
||||
result = utime(path.get(), &ut);
|
||||
} else {
|
||||
result = utime(path.get(), nsnull);
|
||||
}
|
||||
return NSRESULT_FOR_RETURN(result);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsLocalFile::GetLastModifiedTimeOfLink(PRInt64 *aLastModifiedTimeOfLink)
|
||||
{
|
||||
NS_ERROR("NS_ERROR_NOT_IMPLEMENTED");
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
NS_ENSURE_ARG(aLastModifiedTimeOfLink);
|
||||
|
||||
nsCAutoString path;
|
||||
nsresult rv = GetPathInternal(path);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
struct STAT sbuf;
|
||||
if (LSTAT(path.get(), &sbuf) == -1)
|
||||
return NSRESULT_FOR_ERRNO();
|
||||
*aLastModifiedTimeOfLink = PRInt64(sbuf.st_mtime) * PRInt64(PR_MSEC_PER_SEC);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsLocalFile::SetLastModifiedTimeOfLink(PRInt64 aLastModifiedTimeOfLink)
|
||||
{
|
||||
NS_ERROR("NS_ERROR_NOT_IMPLEMENTED");
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
return SetLastModifiedTime(aLastModifiedTimeOfLink);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsLocalFile::GetFileSize(PRInt64 *aFileSize)
|
||||
@ -2190,17 +2178,18 @@ nsresult nsLocalFile::GetPathInternal(nsACString& path)
|
||||
{
|
||||
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
|
||||
|
||||
nsresult rv = NS_ERROR_FAILURE;
|
||||
|
||||
CFURLRef whichURLRef = mFollowLinks ? mTargetURL : mBaseURL;
|
||||
NS_ENSURE_TRUE(whichURLRef, NS_ERROR_NULL_POINTER);
|
||||
|
||||
CFStringRef pathStrRef = ::CFURLCopyFileSystemPath(whichURLRef, kCFURLPOSIXPathStyle);
|
||||
if (pathStrRef) {
|
||||
rv = CFStringReftoUTF8(pathStrRef, path);
|
||||
::CFRelease(pathStrRef);
|
||||
}
|
||||
return rv;
|
||||
if (!whichURLRef)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
path.SetLength(PATH_MAX);
|
||||
if (path.Length() != (unsigned int)PATH_MAX)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
UInt8 *buffer = (UInt8*)path.BeginWriting();
|
||||
if (::CFURLGetFileSystemRepresentation(whichURLRef, true, buffer, PATH_MAX))
|
||||
return NS_OK;
|
||||
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
|
||||
}
|
||||
@ -2268,51 +2257,26 @@ nsresult nsLocalFile::CopyInternal(nsIFile* aParentDir,
|
||||
NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
|
||||
}
|
||||
|
||||
const PRInt64 kMillisecsPerSec = 1000LL;
|
||||
const PRInt64 kUTCDateTimeFractionDivisor = 65535LL;
|
||||
|
||||
PRInt64 nsLocalFile::HFSPlustoNSPRTime(const UTCDateTime& utcTime)
|
||||
{
|
||||
// Start with seconds since Jan. 1, 1904 GMT
|
||||
PRInt64 result = ((PRInt64)utcTime.highSeconds << 32) + (PRInt64)utcTime.lowSeconds;
|
||||
// Subtract to convert to NSPR epoch of 1970
|
||||
result -= kJanuaryFirst1970Seconds;
|
||||
// Convert to millisecs
|
||||
result *= kMillisecsPerSec;
|
||||
// Convert the fraction to millisecs and add it
|
||||
result += ((PRInt64)utcTime.fraction * kMillisecsPerSec) / kUTCDateTimeFractionDivisor;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void nsLocalFile::NSPRtoHFSPlusTime(PRInt64 nsprTime, UTCDateTime& utcTime)
|
||||
{
|
||||
PRInt64 fraction = nsprTime % kMillisecsPerSec;
|
||||
PRInt64 seconds = (nsprTime / kMillisecsPerSec) + kJanuaryFirst1970Seconds;
|
||||
utcTime.highSeconds = (UInt16)((PRUint64)seconds >> 32);
|
||||
utcTime.lowSeconds = (UInt32)seconds;
|
||||
utcTime.fraction = (UInt16)((fraction * kUTCDateTimeFractionDivisor) / kMillisecsPerSec);
|
||||
}
|
||||
|
||||
nsresult nsLocalFile::CFStringReftoUTF8(CFStringRef aInStrRef, nsACString& aOutStr)
|
||||
{
|
||||
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
|
||||
|
||||
nsresult rv = NS_ERROR_FAILURE;
|
||||
// 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, PR_FALSE, nsnull, 0, &usedBufLen);
|
||||
kCFStringEncodingUTF8, 0, PR_FALSE,
|
||||
NULL, 0, &usedBufLen);
|
||||
if (charsConverted == inStrLen) {
|
||||
// all characters converted, do the actual conversion
|
||||
aOutStr.SetLength(usedBufLen);
|
||||
if (aOutStr.Length() != (unsigned int)usedBufLen)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
UInt8 *buffer = (UInt8*) aOutStr.BeginWriting();
|
||||
|
||||
::CFStringGetBytes(aInStrRef, CFRangeMake(0, inStrLen),
|
||||
kCFStringEncodingUTF8, 0, false, buffer, usedBufLen, &usedBufLen);
|
||||
rv = NS_OK;
|
||||
UInt8 *buffer = (UInt8*)aOutStr.BeginWriting();
|
||||
::CFStringGetBytes(aInStrRef, CFRangeMake(0, inStrLen), kCFStringEncodingUTF8,
|
||||
0, false, buffer, usedBufLen, &usedBufLen);
|
||||
return NS_OK;
|
||||
}
|
||||
return rv;
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
|
||||
}
|
||||
|
@ -973,12 +973,12 @@ nsLocalFile::GetLastModifiedTime(PRInt64 *aLastModTime)
|
||||
PRFileInfo64 info;
|
||||
if (PR_GetFileInfo64(mPath.get(), &info) != PR_SUCCESS)
|
||||
return NSRESULT_FOR_ERRNO();
|
||||
PRInt64 modTime = PRInt64(info.modifyTime);
|
||||
if (modTime == 0)
|
||||
*aLastModTime = 0;
|
||||
else
|
||||
*aLastModTime = modTime / PRInt64(PR_USEC_PER_MSEC);
|
||||
|
||||
// PRTime is a 64 bit value
|
||||
// microseconds -> milliseconds
|
||||
PRInt64 usecPerMsec;
|
||||
LL_I2L(usecPerMsec, PR_USEC_PER_MSEC);
|
||||
LL_DIV(*aLastModTime, info.modifyTime, usecPerMsec);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -988,15 +988,13 @@ nsLocalFile::SetLastModifiedTime(PRInt64 aLastModTime)
|
||||
CHECK_mPath();
|
||||
|
||||
int result;
|
||||
if (! LL_IS_ZERO(aLastModTime)) {
|
||||
if (aLastModTime != 0) {
|
||||
ENSURE_STAT_CACHE();
|
||||
struct utimbuf ut;
|
||||
ut.actime = mCachedStat.st_atime;
|
||||
|
||||
// convert milliseconds to seconds since the unix epoch
|
||||
double dTime;
|
||||
LL_L2D(dTime, aLastModTime);
|
||||
ut.modtime = (time_t) (dTime / PR_MSEC_PER_SEC);
|
||||
ut.modtime = (time_t)(PRFloat64(aLastModTime) / PR_MSEC_PER_SEC);
|
||||
result = utime(mPath.get(), &ut);
|
||||
} else {
|
||||
result = utime(mPath.get(), nsnull);
|
||||
@ -1013,12 +1011,7 @@ nsLocalFile::GetLastModifiedTimeOfLink(PRInt64 *aLastModTimeOfLink)
|
||||
struct STAT sbuf;
|
||||
if (LSTAT(mPath.get(), &sbuf) == -1)
|
||||
return NSRESULT_FOR_ERRNO();
|
||||
LL_I2L(*aLastModTimeOfLink, (PRInt32)sbuf.st_mtime);
|
||||
|
||||
// lstat returns st_mtime in seconds
|
||||
PRInt64 msecPerSec;
|
||||
LL_I2L(msecPerSec, PR_MSEC_PER_SEC);
|
||||
LL_MUL(*aLastModTimeOfLink, *aLastModTimeOfLink, msecPerSec);
|
||||
*aLastModTimeOfLink = PRInt64(sbuf.st_mtime) * PRInt64(PR_MSEC_PER_SEC);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
@ -1087,7 +1080,7 @@ NS_IMETHODIMP
|
||||
nsLocalFile::GetFileSize(PRInt64 *aFileSize)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aFileSize);
|
||||
*aFileSize = LL_ZERO;
|
||||
*aFileSize = 0;
|
||||
ENSURE_STAT_CACHE();
|
||||
|
||||
#if defined(VMS)
|
||||
|
Loading…
Reference in New Issue
Block a user