Src: ProjectFile.cpp
PATCH: [ 1589438 ] Add read-only info to ProjectFile dialog
Src: MainFrm.cpp
+ PATCH: [ 1589563 ] Fix crash with weird filetimes (and cleanup the code)
+ Src: DiffFileInfo.cpp DiffFileInfo.h DirScan.cpp DirViewColHandler.cpp
+ DirViewColItems.cpp FileInfo.cpp FileInfo.h
2006-11-03 Tim
PATCH: [ 1589601 ] Add "ReDim" keyword to Visual Basic highlighter
#include "unicoder.h"
/**
- * @brief Convert a FILETIME to a long (standard time)
- */
-static __int64 FileTimeToInt64(FILETIME & ft)
-{
- return CTime(ft).GetTime();
-}
-
-/**
- * @brief Update fileinfo from given file
- * @param [in] sFilePath Full path to file/directory to update
- * @return TRUE if file exists
- */
-BOOL DiffFileInfo::Update(LPCTSTR sFilePath)
-{
- // CFileFind doesn't expose the attributes
- // CFileStatus doesn't expose 64 bit size
- BOOL Update = FALSE;
- WIN32_FIND_DATA wfd;
- HANDLE h = FindFirstFile(sFilePath, &wfd);
- __int64 mtime64 = 0;
- size = -1;
- flags.reset();
- mtime = 0;
- if (h != INVALID_HANDLE_VALUE)
- {
- mtime64 = FileTimeToInt64(wfd.ftLastWriteTime);
- flags.attributes = wfd.dwFileAttributes;
-
- // Folders don't have a size (size remains as -1)
- if ((flags.attributes & FILE_ATTRIBUTE_DIRECTORY) == 0)
- size = FileInfo::GetSizeFromFindData(wfd);
- FindClose(h);
- Update = TRUE;
- }
- mtime = mtime64;
- return Update;
-}
-
-/**
* @brief Clears FileInfo data.
*/
void DiffFileInfo::Clear()
m_textStats.clear();
}
-
/**
* @brief Return true if file is in any Unicode encoding
*/
/**
- * @brief Information for file
+ * @brief Information for file.
+ * This class expands FileInfo class with encoding information and
+ * text stats information.
*/
struct DiffFileInfo : public FileInfo
{
// methods
DiffFileInfo() { Clear(); }
- BOOL Update(LPCTSTR sFilePath);
void Clear();
bool IsEditableEncoding() const;
};
#include "stdafx.h"
#include <shlwapi.h>
+#include <sys/types.h>
+#include <sys/stat.h>
#include "DirScan.h"
#include "CompareStats.h"
#include "common/unicoder.h"
*/
struct fentry
{
- CString name;
- // storing __time_t if MSVC6 (__MSC_VER<1300)
- // storing __time64_t if MSVC7 (VC.NET)
+ CString name; /**< Item name */
__int64 mtime; /**< Last modify time */
__int64 ctime; /**< Creation modify time */
- __int64 size;
- int attrs;
+ __int64 size; /**< File size */
+ int attrs; /**< Item attributes */
};
typedef CArray<fentry, fentry&> fentryArray;
*
* @param [in] di DiffItem to compare
* @param [in,out] pCtxt Compare context: contains difflist, encoding info etc.
+ * @todo For date compare, maybe we should use creation date if modification
+ * date is missing?
*/
void CompareDiffItem(DIFFITEM di, CDiffContext * pCtxt)
{
pCtxt->m_nCompMethod == CMP_DATE_SIZE)
{
// Compare by modified date
- __int64 nTimeDiff = di.left.mtime - di.right.mtime;
- // Remove sign
- nTimeDiff = (nTimeDiff > 0 ? nTimeDiff : -nTimeDiff);
- if (pCtxt->m_bIgnoreSmallTimeDiff)
+ // Check that we have both filetimes
+ if (di.left.mtime != 0 && di.right.mtime != 0)
{
- // If option to ignore small timediffs (couple of seconds)
- // is set, decrease absolute difference by allowed diff
- nTimeDiff -= SmallTimeDiff;
+ __int64 nTimeDiff = di.left.mtime - di.right.mtime;
+ // Remove sign
+ nTimeDiff = (nTimeDiff > 0 ? nTimeDiff : -nTimeDiff);
+ if (pCtxt->m_bIgnoreSmallTimeDiff)
+ {
+ // If option to ignore small timediffs (couple of seconds)
+ // is set, decrease absolute difference by allowed diff
+ nTimeDiff -= SmallTimeDiff;
+ }
+ if (nTimeDiff <= 0)
+ di.diffcode |= DIFFCODE::TEXT | DIFFCODE::SAME;
+ else
+ di.diffcode |= DIFFCODE::TEXT | DIFFCODE::DIFF;
}
- if (nTimeDiff <= 0)
- di.diffcode |= DIFFCODE::TEXT | DIFFCODE::SAME;
else
- di.diffcode |= DIFFCODE::TEXT | DIFFCODE::DIFF;
+ {
+ // Filetimes for item(s) could not be read. So we have to
+ // set error status, unless we have DATE_SIZE -compare
+ // when we have still hope for size compare..
+ if (pCtxt->m_nCompMethod == CMP_DATE_SIZE)
+ di.diffcode |= DIFFCODE::TEXT | DIFFCODE::SAME;
+ else
+ di.diffcode |= DIFFCODE::TEXT | DIFFCODE::CMPERR;
+ }
// This is actual CMP_DATE_SIZE method..
// If file sizes differ mark them different
}
/**
- * @brief Load arrays with all directories & files in specified dir
+ * @brief Find files and subfolders from given folder.
+ * This function saves all files and subfolders in given folder to arrays.
+ * We use 64-bit version of stat() to get times since find doesn't return
+ * valid times for very old files (around year 1970). Even stat() seems to
+ * give negative time values but we can live with that. Those around 1970
+ * times can happen when file is created so that it doesn't get valid
+ * creation or modificatio dates.
+ * @param [in] sDir Base folder for files and subfolders.
+ * @param [in, out] dirs Array where subfolders are stored.
+ * @param [in, out] files Array where files are stored.
*/
void LoadFiles(const CString & sDir, fentryArray * dirs, fentryArray * files)
{
DWORD dwIsDirectory = ff.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY;
if (dwIsDirectory && StrStr(_T(".."), ff.cFileName))
continue;
+
fentry ent;
- // Save filetimes as seconds since January 1, 1970
- ent.ctime = CTime(ff.ftCreationTime).GetTime();
- ent.mtime = CTime(ff.ftLastWriteTime).GetTime();
- if (!dwIsDirectory)
- ent.size = FileInfo::GetSizeFromFindData(ff);
- else
- ent.size = -1; // No size for directories
+ CString fullpath = paths_ConcatPath(sDir, ff.cFileName);
+ struct _stati64 fstats;
+ if (_tstati64(fullpath, &fstats) == 0)
+ {
+ // Save filetimes as seconds since January 1, 1970
+ // Note that times can be < 0 if they are around that 1970..
+ // Anyway that is not sensible case for normal files so we can
+ // just use zero for their time.
+ ent.ctime = fstats.st_ctime;
+ if (ent.ctime < 0)
+ ent.ctime = 0;
+ ent.mtime = fstats.st_mtime;
+ if (ent.mtime < 0)
+ ent.mtime = 0;
+
+ if (ff.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
+ ent.size = -1; // No size for directories
+ else
+ ent.size = fstats.st_size;
+ }
ent.name = ff.cFileName;
ent.attrs = ff.dwFileAttributes;
(dwIsDirectory ? dirs : files) -> Add(ent);
int nIdx = pParam->item.iItem;
int i = ColPhysToLog(pParam->item.iSubItem);
POSITION key = GetItemKey(nIdx);
- if (key == (POSITION) SPECIAL_ITEM_POS)
+ if (key == SPECIAL_ITEM_POS)
{
if (IsColName(i))
{
{
CString s = ColGetTextToDisplay(&ctxt, i, di);
// Add '*' to newer time field
- if
- (
- (IsColLmTime(i) && di.left.mtime > di.right.mtime) // Left modification time
- || (IsColRmTime(i) && di.left.mtime < di.right.mtime) // Right modification time
- )
+ if (di.left.mtime != 0 || di.right.mtime != 0)
{
- s.Insert(0, _T("* "));
+ if ((IsColLmTime(i) && di.left.mtime > di.right.mtime) ||
+ (IsColRmTime(i) && di.left.mtime < di.right.mtime))
+ {
+ s.Insert(0, _T("* "));
+ }
}
// Don't show result for folderitems appearing both sides
if ((IsColStatus(i) || IsColStatusAbbr(i)) &&
}
/**
* @brief Function to compare two diffcodes for a sort
+ * @todo How shall we order diff statuses?
*/
static int cmpdiffcode(int diffcode1, int diffcode2)
{
- // TODO: How shall we order these ?
return diffcode1-diffcode2;
}
/**
// $Id$
#include "stdafx.h"
+#include <sys/types.h>
+#include <sys/stat.h>
#include "FileInfo.h"
/**
- * @brief Convert a FILETIME to a long (standard time)
- */
-static __int64 FileTimeToInt64(FILETIME & ft)
-{
- return CTime(ft).GetTime();
-}
-
-/**
* @brief Update fileinfo from given file
* @param [in] sFilePath Full path to file/directory to update
+ * @return TRUE if information was updated (item was found).
*/
-void FileInfo::Update(CString sFilePath)
+BOOL FileInfo::Update(CString sFilePath)
{
- // CFileFind doesn't expose the attributes
- // CFileStatus doesn't expose 64 bit size
-
- WIN32_FIND_DATA wfd;
- HANDLE h = FindFirstFile(sFilePath, &wfd);
+ struct _stati64 fstats;
__int64 mtime64 = 0;
+ BOOL retVal = FALSE;
+
size = -1;
flags.reset();
mtime = 0;
- if (h != INVALID_HANDLE_VALUE)
+
+ if (_tstati64(sFilePath, &fstats) == 0)
{
- mtime64 = FileTimeToInt64(wfd.ftLastWriteTime);
- flags.attributes = wfd.dwFileAttributes;
+ // There can be files without modification date.
+ // Then we must use creation date. Of course we assume
+ // creation date then exists...
+ if (fstats.st_mtime == 0)
+ mtime64 = fstats.st_ctime;
+ else
+ mtime64 = fstats.st_mtime;
- // No size for directory ( size remains as -1)$
+ flags.attributes = GetFileAttributes(sFilePath);
+
+ // No size for directory ( size remains as -1)
if ((flags.attributes & FILE_ATTRIBUTE_DIRECTORY) == 0)
- size = FileInfo::GetSizeFromFindData(wfd);
- FindClose(h);
+ size = fstats.st_size;
+
+ retVal = TRUE;
}
mtime = mtime64;
+ return retVal;
}
/**
version.Empty();
flags.reset();
}
-
-/**
- * @brief Returns 64-bit filesize from Windows Find Data.
- * This function calculates 64-bit filesize from given find-data where
- * filesize is in two variables.
- * @param [in] findData Find-data to get filesize.
- * @return 64-bit filesize.
- */
-__int64 FileInfo::GetSizeFromFindData(const WIN32_FIND_DATA & findData)
-{
- __int64 tmpSize = 0;
- // Get file's size. If more than 31 bits is needed then we need to
- // calculate full 64 bits. Since size is signed variable.
- if (findData.nFileSizeHigh > 0 || findData.nFileSizeLow > INT_MAX)
- {
- tmpSize = findData.nFileSizeHigh;
- tmpSize = tmpSize << 32;
- tmpSize += findData.nFileSizeLow;
- }
- else
- {
- tmpSize = findData.nFileSizeLow;
- }
- return tmpSize;
-}
};
/**
- * @brief Information for file
+ * @brief Information for file.
+ * This class stores basic information from a file or folder.
+ * Information consists of file times, size and attributes.
+ * Also version info can be get for files supporting it.
*/
struct FileInfo
{
- // storing __time_t if MSVC6 (__MSC_VER<1300)
- // storing __time64_t if MSVC7 (VC.NET)
__int64 ctime; /**< time of creation */
__int64 mtime; /**< time of last modify */
__int64 size; /**< file size in bytes, -1 means file does not exist*/
FileFlags flags; /**< file attributes */
FileInfo() { Clear(); }
- void Update(CString sFilePath);
+ BOOL Update(CString sFilePath);
void Clear();
-
- static __int64 GetSizeFromFindData(const WIN32_FIND_DATA & findData);
};
#endif // _FILE_INFO_H_INCLUDED