Wiki Home

Udf Touch


Namespace: People
Many people will remember the Unix utility (which also had a life in some versions of DOS) called "touch" that simply sets a file's date/time to the current date/time.

An enhanced version would let you specify the date and time on the command line that would be set, instead of using the current date/time.

This can be useful for many situations:
Also, it seems that the ability to "touch" a folder's attributes is much less common among utilities than for files.

This routine works for both files and folders, and for any of the 3 date/times (creation, last access, last write) that are supported by the hard drive format.

FUNCTION Touch( tcFName, tdt_Creation, tdt_Access, tdt_Write )

DECLARE INTEGER CloseHandle IN Kernel32.dll ;
  INTEGER HANDLE_hObject

* New function (handles longer path names):
DECLARE INTEGER CreateFile IN Kernel32.dll as apiCreateFile ;
  STRING @ LPCTSTR_lpFileName, ;
  LONG DWORD_dwDesiredAccess, ;
  LONG DWORD_dwShareMode, ;
  STRING @ LPSECURITY_ATTRIBUTES_lpSecurityAttributes, ;
  LONG DWORD_dwCreationDisposition, ;
  LONG DWORD_dwFlagsAndAttributes, ;
  INTEGER HANDLE_hTemplateFile


DECLARE integer SetFileTime IN Kernel32.dll ;
  long HANDLE_hFile, ;
  string @ const_FILETIME_ptr_lpCreationTime,   ;
  string @ const_FILETIME_ptr_lpLastAccessTime,  ;
  string @ const_FILETIME_ptr_lpLastWriteTime

*!*	typedef struct STRUCT tagFILETIME {
*!*	    DWORD dwLowDateTime;
*!*	    DWORD dwHighDateTime;
*!*	} FILETIME


* Use this to find the original date/time if we only want to change the date:
*!*	Declare Long FindFirstFile in Win32API ;
*!*	  String cFileName, String @cFindFileData
*!*	Declare FindClose in Win32API Long hFindFile

*!*	Local lcFileName, lcBuffer, lcCreated, lcAccessed, lcModified,  lnhFindFile
*!*	lcBuffer = replicate(chr(0), 318)
*!*	hFindFile = FindFirstFile('C:\My Temp\MyFile.DBF', @lcBuffer)
*!*	If !inlist(hFindFile, 0, -1)
*!*	  lcFileName = substr(lcBuffer, 45)
*!*	  lcFileName = left(lcFileName, at(chr(0), lcFileName)-1)
*!*	  lcCreated  = substr(lcBuffer, 5, 8)
*!*	  lcAccessed = substr(lcBuffer, 13, 8)
*!*	  lcModified = substr(lcBuffer, 21, 8)

*!*	  ? 'File: ', lcFileName
*!*	  ? 'Created: ', GetDateTime(lcCreated, 1)
*!*	  ? 'Modified: ', GetDateTime(lcModified, 1)
*!*	  ? 'Accessed: ', GetDateTime(lcAccessed, 2)
*!*	  FindClose(hFindFile)
*!*	endif

*!*	typedef struct _OFSTRUCT {
*!*	 1      1 BYTE cBytes;
*!*	 2      1 BYTE fFixedDisk;
*!*	 4      2 WORD nErrCode;
*!*	 6      2 WORD Reserved1;
*!*	 8      2 WORD Reserved2;
*!*	 136  128 CHAR szPathName[OFS_MAXPATHNAME (currently, 128) ]

#define OFS_MAXPATHNAME 128
#define OF_SHARE_DENY_NONE  0x00000040

  #define GENERIC_READ                     0x80000000
  #define GENERIC_WRITE                    0x40000000
  #define GENERIC_EXECUTE                  0x20000000
  #define GENERIC_ALL                      0x10000000

  #define FILE_READ_ATTRIBUTES      0x0080

  #define FILE_WRITE_ATTRIBUTES     0x0100

  *#define SYNCHRONIZE                      (0x00100000L)
  *#define STANDARD_RIGHTS_REQUIRED         (0x000F0000L)
  *#define FILE_ALL_ACCESS (STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | 0x3FF)
  #define FILE_ALL_ACCESS 0x001F03FF

  * Delete not supported Win95/98
  #define FILE_SHARE_READ                 0x00000001
  #define FILE_SHARE_WRITE                0x00000002
  #define FILE_SHARE_DELETE               0x00000004
  #define FILE_SHARE_all 0x07
  #define OPEN_EXISTING       3
  #define FILE_FLAG_BACKUP_SEMANTICS      0x02000000

*  lnFile = CreateFile( tcFName, FILE_ALL_ACCESS, FILE_SHARE_all, 0, ;
*                       OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 )
  lnFile = apiCreateFile( tcFName, BITOR(GENERIC_READ,FILE_WRITE_ATTRIBUTES), ;
                          BITOR(FILE_SHARE_READ,FILE_SHARE_DELETE), ;
                          0, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 )
  IF lnFile<0
    RETURN .F.
  ENDIF


lcCreation = IIF( NOT EMPTY(tdt_Creation) and VARTYPE(tdt_Creation)='T', SetDateTime(tdt_Creation), '' )
lcAccess   = IIF( NOT EMPTY(tdt_Access  ) and VARTYPE(tdt_Access  )='T', SetDateTime(tdt_Access  ), '' )
lcWrite    = IIF( NOT EMPTY(tdt_Write   ) and VARTYPE(tdt_Write   )='T', SetDateTime(tdt_Write   ), '' )

lnRes = SetFileTime( lnFile, @lcCreation, @lcAccess, @lcWrite )
CloseHandle( lnFile )

RETURN ( lnRes<>0 )


Function GetDateTime(tcFileTime, tnOption)
  Local lnYear, lnMonth, lnDayWeek, ;
        lnDay, lnHour, lnMinute, lnSecond, ;
        lcSystemTime, lcLocalFileTime, ;
        ltDateTime

  Store 0 to lnYear, lnMonth, lnDayWeek, ;
     lnDay, lnHour, lnMinute, lnSecond
  lcLocalFileTime = replicate(chr(0), 8)
  lcSystemTime    = replicate(chr(0), 16)

  Declare Integer FileTimeToLocalFileTime in Kernel32.dll ;
    String @lpFileTime, String @lpLocalTime
  Declare Integer FileTimeToSystemTime in Kernel32.dll ;
    String @lpFileTime, String @lpSystemTime


  FileTimeToLocalFileTime(tcFileTime, @lcLocalFileTime)
  FileTimeToSystemTime(lcLocalFileTime, @lcSystemTime)

  lnYear    = Word2Num(substr(lcSystemTime,  1, 2))
  lnMonth   = Word2Num(substr(lcSystemTime,  3, 2))
  lnDayWeek = Word2Num(substr(lcSystemTime,  5, 2))
  lnDay     = Word2Num(substr(lcSystemTime,  7, 2))
  lnHour    = Word2Num(substr(lcSystemTime,  9, 2))
  lnMinute  = Word2Num(substr(lcSystemTime, 11, 2))
  lnSecond  = Word2Num(substr(lcSystemTime, 13, 2))

  If (tnOption == 1)
     ltDate = datetime(lnYear, lnMonth, lnDay, ;
       lnHour, lnMinute, lnSecond)
  else
     ltDate = date(lnYear, lnMonth, lnDay)
  endif

  Return ltDate
EndFunc

Function SetDateTime(ttFileTime)
  Local lnYear, lnMonth, lnDayWeek, ;
        lnDay, lnHour, lnMinute, lnSecond, ;
        lcSystemTime, lcLocalFileTime, ;
        ltDateTime

  Declare Integer SystemTimeToFileTime in Kernel32.dll ;
    String @lpSystemTime, String @lpFileTime
  Declare Integer LocalFileTimeToFileTime in Kernel32.dll ;
    String @lpLocalTime, String @lpFileTime

  Store 0 to lnYear, lnMonth, lnDayWeek, ;
     lnDay, lnHour, lnMinute, lnSecond

  lcSystemTime = Num2Word( YEAR(ttFileTime)    ) ;
               + Num2Word( MONTH(ttFileTime)   ) ;
               + Num2Word( DOW(ttFileTime,1)-1 ) ;
               + Num2Word( DAY(ttFileTime)     ) ;
               + Num2Word( Hour(ttFileTime)    ) ;
               + Num2Word( Minute(ttFileTime)  ) ;
               + Num2Word( Sec(ttFileTime)     ) ;
               + Num2Word( 0                   )

  lcLocalFileTime = replicate(chr(0), 8)
  lcFileTime      = replicate(chr(0), 8)

  SystemTimeToFileTime(    lcSystemTime,    @lcLocalFileTime )
  LocalFileTimeToFileTime( lcLocalFileTime, @lcFileTime      )

  Return lcFileTime
EndFunc

Function Word2Num(tcBuffer)
  Return asc(substr(tcBuffer, 1,1)) + ;
    asc(substr(tcBuffer, 2,1)) * 256
EndFunc

FUNCTION num2word (lnValue)
  RETURN Chr(MOD(m.lnValue,256)) + CHR(INT(m.lnValue/256))
ENDFUNC  



Contributors: wgcs
( Topic last updated: 2005.08.04 02:48:20 PM )