Archive: FileFunc:GetTime - strange behavior


FileFunc:GetTime - strange behavior
Hello, I wrote a few simple "do not delete if file was modified" macroes today and testing em now (those are quite simple and more like template atm, but they do work),
but there is a problem with seconds return value, in FileFunc::GetTime.
Can someone please test the following code or explain the strange behavior of GetTime in FileFunc.nsh?


!include LogicLib.nsh
!include FileFunc.nsh
!insertmacro GetTime
!insertmacro un.GetTime

!macro AddUninstInfo fullPath fileName
;считать UTC время в переменные
${GetTime} ${fullPath} "MS" $0 $1 $2 $3 $4 $5 $6
;записать в INI
WriteINIStr "$INSTDIR\uninstInfo.ini" ${fileName} "day" $0
WriteINIStr "$INSTDIR\uninstInfo.ini" ${fileName} "month" $1
WriteINIStr "$INSTDIR\uninstInfo.ini" ${fileName} "year" $2
;WriteINIStr "$INSTDIR\uninstInfo.ini" ${fileName} "weekday" $3
WriteINIStr "$INSTDIR\uninstInfo.ini" ${fileName} "hour" $4
WriteINIStr "$INSTDIR\uninstInfo.ini" ${fileName} "minute" $5
WriteINIStr "$INSTDIR\uninstInfo.ini" ${fileName} "second" $6
!macroend

var iniDay
var iniMonth
var iniYear
var iniHour
var iniMinute
var iniSecond ;here - seconds returned are (almost) always differ by one second, so
var iniSecondMin ;here is a workaround
var iniSecondMax ;
!macro UnmodifiedDelete fullPath fileName
;считать UTC время в переменные
${un.GetTime} ${fullPath} "MS" $0 $1 $2 $3 $4 $5 $6
;считать данные из INI по файлу
ReadINIStr $iniDay "$INSTDIR\uninstInfo.ini" ${fileName} "day"
ReadINIStr $iniMonth "$INSTDIR\uninstInfo.ini" ${fileName} "month"
ReadINIStr $iniYear "$INSTDIR\uninstInfo.ini" ${fileName} "year"
ReadINIStr $iniHour "$INSTDIR\uninstInfo.ini" ${fileName} "hour"
ReadINIStr $iniMinute "$INSTDIR\uninstInfo.ini" ${fileName} "minute"
ReadINIStr $iniSecond "$INSTDIR\uninstInfo.ini" ${fileName} "second"
IntOp $iniSecondMin $6 - 3
IntOp $iniSecondMax $6 + 3
MessageBox MB_OK "$0=$iniDay $1=$iniMonth $2=$iniYear $3 $4=$iniHour $5=$iniMinute $6=$iniSecond, $iniSecondMin, $iniSecondMax"
;сравнить данные
${If} $0 == $iniDay
${AndIf} $1 == $iniMonth
${AndIf} $2 == $iniYear
${AndIf} $4 == $iniHour
${AndIf} $5 == $iniMinute
${AndIf} $6 > $iniSecondMin
${AndIf} $6 < $iniSecondMax
;Delete ${fullPath}
MessageBox MB_OK "${fullPath} unmodified - should be deleted"
${EndIf}
!macroend


What it does - writes datetime info into an ini file (that is formed in $INSTDIR) about every installed file (filenames as a tag atm.).
Then, when time X comes, uninstaller can read that info for a file in question, and delete it only if there was no modifications done to it.
Usage:

install section:
File "$%SOME_ROOT%\release\bin\file1.dll"
;add after File
!insertmacro AddUninstInfo "$%SOME_ROOT%\release\bin\file1.dll" "file1.dll"

uninstall section:
;instead of Delete
!insertmacro UnmodifiedDelete "$INSTDIR\bin\file1.dll" "file1.dll"

On my PC and notebook $6 almost always is wrong. For example if file properties say mod. time is 10:15:42, the seconds part returned by GetTime equals 43... Is it my PC or?..

I'm slightly confused by the file location in "fullpath", but I think I can explain the problem. The FAT file system uses a 2 second resolution when the time is stored, and zip and NSIS files do the same. NTFS maintains file times with much greater resolution (100 nsec).

If you are comparing the original time of a file on your build system (NTFS) against a file extracted from NSIS program (FAT style) and stored on a target machine, you must allow for the seconds to be truncated (rounded) to the 2 second precision.

Perhaps you can eliminate the time comparison and use md5 hash values? Uninstall files that have unchanged hash values, keep files with new hash values.


Thank you demiller9, you were completely right about NTFS<->FAT32, so hash is a better idea.
(and ye sorry about fullpath - not the right name for that parameter. Also copy-paste is evil and there have to be
!insertmacro AddUninstInfo "$INSTDIR\bin\file1.dll" "file1.dll"
instead of
!insertmacro AddUninstInfo "$%SOME_ROOT%\release\bin\file1.dll" "file1.dll"
)