1

Context:

I have an application that searches files in a directory(s)and copies specific files.

Problem:

Using FileCopyExW, I copy the file(s) successfully to the new location, however the file's date and time to not match, it may be off by a second or more as shown in the example below.

Attempting to modify overwrite the destination file's QDateTime with that of the source file (sometimes) fails to write the correct date as shown in my example below.

Screenshot of debugger

enter image description here

Output from log for this file

09:34:50.731 Warning: File times do not match
09:34:50.731 Warning: Birth time differene:  0
09:34:50.731 Warning: Last Access time differene:  483
09:42:02.660 Warning: Last Modified time differene:  483
09:42:02.660 Debug: 

Output for a random other file that failed

09:43:48.831 Warning: File times do not match
09:43:48.831 Warning: Birth time differene:  -7
09:43:48.831 Warning: Last Access time differene:  1462
09:44:53.602 Warning: Last Modified time differene:  0
09:44:53.602 Debug: 

Any ideas why this would happen and how I can fix it?


Code Sample:

 // File copied successfully at this point, now adjust file times as these may not be accurate (why?)

 QFile newFile(destination);
 if (newFile.open(QIODevice::OpenModeFlag::WriteOnly | QIODevice::OpenModeFlag::Append)) {

      // set file attributes, create, last write and last modified dates the same as original file
      QFileInfo srcFi(storageFile.location);

      // Set last modified date - most important
      QDateTime localLastModified = srcFi.lastModified().toLocalTime();
      if (!newFile.setFileTime(localLastModified, QFileDevice::FileModificationTime)) {
           printWarningFileError(TAG, QString("Failed to set lastModified date for file at [%1]").arg(destination), &newFile);
      }

      // Set last accessed date
      QDateTime localLastRead = srcFi.lastRead().toLocalTime();
      if (!newFile.setFileTime(localLastRead, QFileDevice::FileAccessTime)) {
           printWarningFileError(TAG, QString("Failed to set lastAccessed date for file at [%1]").arg(destination), &newFile);
      }

      // Set created date
      QDateTime localBirthTime = srcFi.birthTime().toLocalTime();
      if (!newFile.setFileTime(localBirthTime, QFileDevice::FileBirthTime)) {
           printWarningFileError(TAG, QString("Failed to set created date for file at [%1]").arg(destination), &newFile);
      }

      // Ensure we write out content before closing file (not really necessary due to close() )
      newFile.flush();
      newFile.close();

      // Read file & refresh meta data for checking
      QFileInfo fiDest(destination);
      fiDest.refresh();

      // Read destination file date data
      QDateTime destFileBirth = fiDest.birthTime();
      QDateTime destFileAccess = fiDest.lastRead();
      QDateTime destFileModified = fiDest.lastModified();

      // Compare dates
      bool birthTimeMatch = (destFileBirth != localBirthTime);
      bool accessTimeMatch = (destFileAccess != localLastRead);
      bool modifiedTimeMatch = (destFileModified != localLastModified);

      if (!(birthTimeMatch && accessTimeMatch && modifiedTimeMatch)) {
           qWarning() << "File times do not match";
           qWarning() << "Birth time differene: " << (destFileBirth.toMSecsSinceEpoch() - localBirthTime.toMSecsSinceEpoch());
           qWarning() << "Last Access time differene: " << (destFileAccess.toMSecsSinceEpoch() - localLastRead.toMSecsSinceEpoch());
           qWarning() << "Last Modified time differene: " << (destFileModified.toMSecsSinceEpoch() - localLastModified.toMSecsSinceEpoch());
           qDebug() << "";
      }
      else {
           qDebug() << "All good";
      }
 }
 else {
      printWarningFileError(TAG, QString("Failed to open file for adjust dates [%1]").arg(destination), &newFile);
 }
CybeX
  • 2,060
  • 3
  • 48
  • 115
  • 1
    [File Times](https://docs.microsoft.com/en-us/windows/win32/sysinfo/file-times): *"Time stamps are updated at various times and for various reasons. The only guarantee about a file time stamp is that the file time is correctly reflected when the handle that makes the change is closed."* Also note: *"Not all file systems can record creation and last access times, and not all file systems record them in the same manner. For example, the resolution of create time on FAT is 10 milliseconds, while write time has a resolution of 2 seconds and access time has a resolution of 1 day, \[...\]."* – IInspectable Aug 12 '20 at 08:13
  • @IInspectable Sorry, I should have mentioned, I am using this on NTFS only – CybeX Aug 12 '20 at 08:14
  • The first quote still applies. You are checking file times before they are guaranteed to have been reflected in the file system. – IInspectable Aug 12 '20 at 08:16
  • @IInspectable right - so if I need to use date & time in a file comparison i.e. check if a file was modified (src vs dest), what would be the best course of action (if you have a suggestion)? – CybeX Aug 12 '20 at 08:17
  • It seems that there is a time deviation in `newFile.setFileTime`. For C++, using [SetFileTime](https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-setfiletime) on NTFS can set the time accurately. – Strive Sun Aug 12 '20 at 09:54

0 Answers0