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:
Josh Aas 2009-04-23 22:22:20 -04:00
Родитель 9a2bec39e8
Коммит d19f83697a
3 изменённых файлов: 86 добавлений и 122 удалений

Просмотреть файл

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