Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

3029 lines
96 KiB

  1. /************************************************************************
  2. * Compdir: compare directories
  3. *
  4. ************************************************************************/
  5. #define IF_GET_ATTR_FAILS( FileName, Attributes) GET_ATTRIBUTES( FileName, Attributes); if ( Attributes == GetFileAttributeError)
  6. #define FIND_FIRST( String, Buff) FindFirstFile( String, &Buff)
  7. #define FIND_NEXT( handle, Buff) !FindNextFile( handle, &Buff)
  8. #define FREE( memory)
  9. #define MYSTRCAT( FirstString, SecondString) strcat( strcpy( _alloca( strlen( FirstString) + strlen( SecondString) + 1), FirstString), SecondString)
  10. #define COMBINETHREESTRINGS( FirstString, SecondString, ThirdString) strcat( strcat( strcpy( _alloca( strlen( FirstString) + strlen( SecondString) + strlen( ThirdString) + 1), FirstString), SecondString), ThirdString)
  11. #include "compdir.h"
  12. #include "imagehlp.h"
  13. int Mymemcmp( const void *buf1, const void *buf2, size_t count );
  14. LinkedFileList MatchList = NULL;
  15. LinkedFileList MStarList = NULL;
  16. LinkedFileList ExcludeList = NULL;
  17. LinkedFileList EStarList = NULL;
  18. DWORD Granularity = 0; // used in ParseArgs
  19. ATTRIBUTE_TYPE CompareAttribute, NegativeCompareAttribute; // used as file compare criteria
  20. BOOL CompareAttributeSet = FALSE;
  21. BOOL NegativeCompareAttributeSet = FALSE;
  22. BOOL Excludes = FALSE;
  23. BOOL Matches = FALSE;
  24. BOOL RunningOnNT = FALSE;
  25. BOOL DealingWithDirectories;
  26. fSpecAttribs = FALSE;
  27. fBreakLinks = FALSE;
  28. fCheckAttribs = FALSE;
  29. fCheckBits = FALSE;
  30. fChecking = FALSE;
  31. fCheckSize = FALSE;
  32. fCheckTime = FALSE;
  33. fCreateNew = FALSE;
  34. fCreateLink = FALSE;
  35. fDoNotDelete = FALSE;
  36. fDoNotRecurse = FALSE;
  37. fDontCopyAttribs = FALSE;
  38. fDontLowerCase = FALSE;
  39. fExclude = FALSE;
  40. fExecute = FALSE;
  41. fForce = FALSE;
  42. fIgnoreRs = FALSE;
  43. fIgnoreSlmFiles = FALSE;
  44. fMatching = FALSE;
  45. fMultiThread = FALSE;
  46. fOnlyIfExists = FALSE;
  47. fOpposite = FALSE;
  48. fScript = FALSE;
  49. fTrySis = FALSE;
  50. fVerbose = FALSE;
  51. void __cdecl main( int argc, char **argv)
  52. {
  53. ATTRIBUTE_TYPE Attributes1, Attributes2;
  54. char *Path1, *Path2;
  55. OSVERSIONINFO VersionInformation;
  56. SYSTEM_INFO SystemInformation;
  57. ExitValue = 0;
  58. Attributes1 = GetFileAttributeError;
  59. Attributes2 = GetFileAttributeError;
  60. ProcessModeDefault = TRUE; // Used by opposite mode
  61. ParseEnvArgs( ); // Parse COMPDIRCMD environment variable
  62. ParseArgs( argc, argv); // Check argument validity.
  63. //
  64. // Check existence of first path.
  65. //
  66. IF_GET_ATTR_FAILS( argv[argc - 2], Attributes1)
  67. {
  68. fprintf( stderr, "Could not find %s (error = %d)\n", argv[argc - 2], GetLastError());
  69. exit( 1);
  70. }
  71. IF_GET_ATTR_FAILS( argv[argc - 1], Attributes2)
  72. {
  73. if ( !fCreateNew)
  74. {
  75. fprintf( stderr, "Could not find %s (error = %d)\n", argv[argc - 1], GetLastError());
  76. exit( 1);
  77. }
  78. }
  79. //
  80. // If second directory is a drive letter append path of first directory
  81. // to it
  82. //
  83. if (
  84. ( strlen( argv[argc-1]) == 2)
  85. &&
  86. ( *( argv[argc-1] + 1) == ':')
  87. )
  88. {
  89. if ( ( Path2 = _fullpath( NULL, argv[argc-2], 0)) == NULL)
  90. {
  91. Path2 = argv[argc-1];
  92. } else
  93. {
  94. Path2[0] = *( argv[argc-1]);
  95. IF_GET_ATTR_FAILS( Path2, Attributes2)
  96. {
  97. if ( !fCreateNew)
  98. {
  99. fprintf( stderr, "Could not find %s (error = %d)\n", Path2, GetLastError());
  100. exit( 1);
  101. }
  102. }
  103. }
  104. } else if ( ( Path2 = _fullpath( NULL, argv[argc-1], 0)) == NULL)
  105. {
  106. Path2 = argv[argc-1];
  107. }
  108. if ( ( Path1 = _fullpath( NULL, argv[argc-2], 0)) == NULL)
  109. {
  110. Path1 = argv[argc-2];
  111. }
  112. if ( !fDontLowerCase)
  113. {
  114. _strlwr( Path1);
  115. _strlwr( Path2);
  116. }
  117. if ( fVerbose)
  118. {
  119. fprintf( stdout, "Compare criterion: existence" );
  120. if ( fCheckSize)
  121. {
  122. fprintf( stdout, ", size" );
  123. }
  124. if ( fCheckTime)
  125. {
  126. fprintf( stdout, ", date/time" );
  127. }
  128. if ( fCheckBits)
  129. {
  130. fprintf( stdout, ", contents" );
  131. }
  132. fprintf( stdout, "\n" );
  133. fprintf( stdout, "Path1: %s\n", Path1);
  134. fprintf( stdout, "Path2: %s\n", Path2);
  135. }
  136. VersionInformation.dwOSVersionInfoSize = sizeof( OSVERSIONINFO);
  137. if ( GetVersionEx( &VersionInformation) )
  138. {
  139. if ( VersionInformation.dwPlatformId == VER_PLATFORM_WIN32_NT )
  140. {
  141. RunningOnNT = TRUE;
  142. }
  143. }
  144. if ( ( fCreateLink) || ( fBreakLinks) || ( fTrySis))
  145. {
  146. if ( RunningOnNT)
  147. {
  148. NtDll = LoadLibrary( "ntdll.dll");
  149. if ( !NtDll)
  150. {
  151. fprintf( stderr, "Could not find ntdll.dll. Can't perform /l or /$\n");
  152. fCreateLink = FALSE;
  153. fTrySis = FALSE;
  154. ExitValue = 1;
  155. } else
  156. {
  157. if ( !InitializeNtDllFunctions())
  158. {
  159. fprintf( stderr, "Could not load ntdll.dll. Can't perform /l or /$\n");
  160. fCreateLink = FALSE;
  161. fTrySis = FALSE;
  162. ExitValue = 1;
  163. }
  164. }
  165. } else
  166. {
  167. fprintf( stderr, "/l and /$ only work on NT. Can't perform /l or /$\n");
  168. fCreateLink = FALSE;
  169. fTrySis = FALSE;
  170. ExitValue = 1;
  171. }
  172. }
  173. if ( fMultiThread)
  174. {
  175. //
  176. // Query the number of processors from the system and
  177. // default the number of worker threads to 4 times that.
  178. //
  179. GetSystemInfo( &SystemInformation );
  180. NumberOfWorkerThreads = SystemInformation.dwNumberOfProcessors * 4;
  181. if ( fVerbose)
  182. {
  183. fprintf( stdout, "Processors: %d\n", SystemInformation.dwNumberOfProcessors );
  184. }
  185. //
  186. // Allocate a thread local storage slot for use by our worker
  187. // thread routine ( ProcessRequest). This call reserves a
  188. // 32-bit slot in the thread local storage array for every
  189. // thread in this process. Remember the slot index in a global
  190. // variable for use by our worker thread routine.
  191. //
  192. TlsIndex = TlsAlloc();
  193. if ( TlsIndex == 0xFFFFFFFF)
  194. {
  195. fprintf( stderr, "Unable to allocate thread local storage.\n" );
  196. fMultiThread = FALSE;
  197. ExitValue = 1;
  198. }
  199. //
  200. // Create a work queue, which will create the specified number of threads
  201. // to process.
  202. //
  203. CDWorkQueue = CreateWorkQueue( NumberOfWorkerThreads, ProcessRequest );
  204. if ( CDWorkQueue == NULL)
  205. {
  206. fprintf( stderr, "Unable to create %u worker threads.\n", NumberOfWorkerThreads );
  207. fMultiThread = FALSE;
  208. ExitValue = 1;
  209. }
  210. //
  211. // Mutual exclusion between and requests that are creating paths
  212. // is done with a critical section.
  213. //
  214. InitializeCriticalSection( &CreatePathCriticalSection );
  215. }
  216. if ( Attributes1 & FILE_ATTRIBUTE_DIRECTORY)
  217. {
  218. DealingWithDirectories = TRUE;
  219. } else
  220. {
  221. DealingWithDirectories = FALSE;
  222. }
  223. if ( Matches)
  224. {
  225. SparseTree = TRUE;
  226. } else
  227. {
  228. SparseTree = FALSE;
  229. }
  230. if ( fCreateNew)
  231. {
  232. IF_GET_ATTR_FAILS( Path2, Attributes2)
  233. {
  234. fprintf ( stdout, "Making %s\t", Path2);
  235. if ( !MyCreatePath( Path2, DealingWithDirectories))
  236. {
  237. fprintf ( stderr, "Unable to create path %s\n", Path2);
  238. fprintf ( stdout, "\n");
  239. ExitValue = 1;
  240. } else
  241. {
  242. fprintf( stdout, "[OK]\n");
  243. CompDir( Path1, Path2);
  244. }
  245. } else
  246. {
  247. CompDir( Path1, Path2);
  248. }
  249. } else
  250. {
  251. CompDir( Path1, Path2);
  252. }
  253. free( Path1);
  254. free( Path2);
  255. if ( fMultiThread)
  256. {
  257. //
  258. // This will wait for the work queues to empty before terminating the
  259. // worker threads and destroying the queue.
  260. //
  261. DestroyWorkQueue( CDWorkQueue );
  262. DeleteCriticalSection( &CreatePathCriticalSection );
  263. }
  264. if ( fCreateLink)
  265. {
  266. FreeLibrary( NtDll);
  267. }
  268. exit( ExitValue);
  269. } // main
  270. BOOL NoMapBinaryCompare ( char *file1, char *file2)
  271. {
  272. register int char1, char2;
  273. FILE *filehandle1, *filehandle2;
  274. if ( ( filehandle1 = fopen ( file1, "rb")) == NULL)
  275. {
  276. fprintf ( stderr, "cannot open %s\n", file1);
  277. ExitValue = 1;
  278. return ( FALSE);
  279. }
  280. if ( ( filehandle2 = fopen( file2, "rb")) == NULL)
  281. {
  282. fprintf( stderr, "cannot open %s\n", file2);
  283. fclose( filehandle1);
  284. ExitValue = 1;
  285. return( FALSE);
  286. }
  287. while ( TRUE)
  288. {
  289. if ( ( char1 = getc( filehandle1)) != EOF)
  290. {
  291. if ( ( char2 = getc( filehandle2)) != EOF)
  292. {
  293. if ( char1 != char2)
  294. {
  295. fclose( filehandle1);
  296. fclose( filehandle2);
  297. return( FALSE);
  298. }
  299. } else
  300. {
  301. fclose( filehandle1);
  302. fclose( filehandle2);
  303. return( FALSE);
  304. }
  305. } else
  306. {
  307. if ( ( char2 = getc( filehandle2)) == EOF)
  308. {
  309. fclose( filehandle1);
  310. fclose( filehandle2);
  311. return( TRUE);
  312. } else
  313. {
  314. fclose( filehandle1);
  315. fclose( filehandle2);
  316. return( FALSE);
  317. }
  318. }
  319. }
  320. }
  321. BOOL BinaryCompare( char *file1, char *file2)
  322. {
  323. char String[MAX_PATH];
  324. char RebasedFile[MAX_PATH]; // used in BinaryCompares with /i switch
  325. char *RebasedFile2 = NULL; // used in BinaryCompares with /i switch
  326. HANDLE hFile1, hFile2;
  327. HANDLE hMappedFile1, hMappedFile2;
  328. BOOL IsNTImage = FALSE;
  329. LPVOID MappedAddr1, MappedAddr2;
  330. PIMAGE_NT_HEADERS32 NtHeader1, NtHeader2;
  331. ULONG OldImageSize, NewImageSize;
  332. ULONG_PTR OldImageBase, NewImageBase;
  333. // fprintf( stdout, "file1: %s, file2: %s\n", file1, file2);
  334. //
  335. // File1 Mapping
  336. //
  337. if ( ( hFile1 = CreateFile(
  338. file1,
  339. GENERIC_READ,
  340. FILE_SHARE_READ,
  341. NULL,
  342. OPEN_EXISTING,
  343. 0,
  344. NULL
  345. )) == (HANDLE)-1)
  346. {
  347. fprintf( stderr, "Unable to open %s, error code %d\n", file1, GetLastError() );
  348. if ( hFile1 != INVALID_HANDLE_VALUE)
  349. {
  350. CloseHandle( hFile1 );
  351. }
  352. return FALSE;
  353. }
  354. hMappedFile1 = CreateFileMapping(
  355. hFile1,
  356. NULL,
  357. PAGE_WRITECOPY,
  358. 0,
  359. 0,
  360. NULL
  361. );
  362. if ( hMappedFile1 == NULL)
  363. {
  364. fprintf( stderr, "Unable to map %s, error code %d\n", file1, GetLastError() );
  365. CloseHandle( hFile1);
  366. return FALSE;
  367. }
  368. MappedAddr1 = MapViewOfFile(
  369. hMappedFile1,
  370. FILE_MAP_COPY,
  371. 0,
  372. 0,
  373. 0
  374. );
  375. if ( MappedAddr1 == NULL)
  376. {
  377. fprintf( stderr, "Unable to get mapped view of %s, error code %d\n", file1, GetLastError() );
  378. CloseHandle( hFile1 );
  379. return FALSE;
  380. }
  381. CloseHandle( hMappedFile1);
  382. //
  383. // File2 rebasing and mapping
  384. //
  385. if ( fIgnoreRs)
  386. {
  387. GetTempPath( MAX_PATH, String);
  388. RebasedFile2 = RebasedFile;
  389. GetTempFileName( String, NULL, 0, RebasedFile2);
  390. if ( ( ( PIMAGE_DOS_HEADER)MappedAddr1)->e_magic == IMAGE_DOS_SIGNATURE)
  391. {
  392. try
  393. {
  394. NtHeader1 = ( PIMAGE_NT_HEADERS32)( (PCHAR)MappedAddr1 + ( (PIMAGE_DOS_HEADER)MappedAddr1)->e_lfanew);
  395. if ( NtHeader1->Signature == IMAGE_NT_SIGNATURE)
  396. {
  397. NewImageBase = ( NtHeader1->OptionalHeader.ImageBase);
  398. if (
  399. ( RebasedFile2 != NULL)
  400. &&
  401. ( CopyFile ( file2, RebasedFile2, FALSE))
  402. &&
  403. ( ReBaseImage(
  404. RebasedFile2,
  405. NULL,
  406. TRUE,
  407. FALSE,
  408. FALSE,
  409. 0,
  410. &OldImageSize,
  411. &OldImageBase,
  412. &NewImageSize,
  413. &NewImageBase,
  414. 0
  415. ))
  416. )
  417. {
  418. IsNTImage = TRUE;
  419. }
  420. }
  421. }
  422. except( EXCEPTION_EXECUTE_HANDLER ) {}
  423. }
  424. }
  425. if ( IsNTImage)
  426. {
  427. if ( ( hFile2 = CreateFile(
  428. RebasedFile2,
  429. GENERIC_READ,
  430. FILE_SHARE_READ,
  431. NULL,
  432. OPEN_EXISTING,
  433. 0,
  434. NULL
  435. )) == (HANDLE)-1)
  436. {
  437. fprintf( stderr, "Unable to open %s, error code %d\n", RebasedFile2, GetLastError() );
  438. if ( hFile2 != INVALID_HANDLE_VALUE)
  439. {
  440. CloseHandle( hFile2 );
  441. }
  442. return FALSE;
  443. }
  444. } else
  445. {
  446. if ( ( hFile2 = CreateFile(
  447. file2,
  448. GENERIC_READ,
  449. FILE_SHARE_READ,
  450. NULL,
  451. OPEN_EXISTING,
  452. 0,
  453. NULL
  454. )) == (HANDLE)-1 )
  455. {
  456. fprintf( stderr, "Unable to open %s, error code %d\n", file2, GetLastError() );
  457. if ( hFile2 != INVALID_HANDLE_VALUE)
  458. {
  459. CloseHandle( hFile2 );
  460. }
  461. return FALSE;
  462. }
  463. }
  464. hMappedFile2 = CreateFileMapping(
  465. hFile2,
  466. NULL,
  467. PAGE_WRITECOPY,
  468. 0,
  469. 0,
  470. NULL
  471. );
  472. if ( hMappedFile2 == NULL)
  473. {
  474. fprintf( stderr, "Unable to map %s, error code %d\n", file2, GetLastError() );
  475. CloseHandle( hFile2);
  476. return FALSE;
  477. }
  478. MappedAddr2 = MapViewOfFile(
  479. hMappedFile2,
  480. FILE_MAP_COPY,
  481. 0,
  482. 0,
  483. 0
  484. );
  485. if ( MappedAddr2 == NULL)
  486. {
  487. fprintf( stderr, "Unable to get mapped view of %s, error code %d\n", file1, GetLastError() );
  488. UnmapViewOfFile( MappedAddr1 );
  489. CloseHandle( hFile1 );
  490. return FALSE;
  491. }
  492. CloseHandle( hMappedFile2);
  493. if ( fIgnoreRs & IsNTImage)
  494. {
  495. if ( ( (PIMAGE_DOS_HEADER)MappedAddr2)->e_magic == IMAGE_DOS_SIGNATURE)
  496. {
  497. try
  498. {
  499. NtHeader2 = (PIMAGE_NT_HEADERS32)( (PCHAR)MappedAddr2 + ( (PIMAGE_DOS_HEADER)MappedAddr2)->e_lfanew);
  500. if ( NtHeader2->Signature == IMAGE_NT_SIGNATURE)
  501. {
  502. IsNTImage = IsNTImage & TRUE;
  503. }
  504. }
  505. except( EXCEPTION_EXECUTE_HANDLER ) {}
  506. }
  507. }
  508. //
  509. // Main compare block
  510. //
  511. if ( fIgnoreRs)
  512. {
  513. if ( IsNTImage)
  514. {
  515. try
  516. {
  517. ULONG i, c;
  518. ULONG DirectoryAddressA;
  519. ULONG DirectoryAddressB;
  520. ULONG DirectoryAddressD;
  521. ULONG DirectoryAddressE;
  522. ULONG DirectoryAddressI;
  523. ULONG DirectoryAddressR;
  524. ULONG SizetoEndofFile1 = 0;
  525. ULONG SizetoResource1 = 0;
  526. ULONG SizeZeroedOut1 = 0;
  527. ULONG SizetoEndofFile2 = 0;
  528. ULONG SizetoResource2 = 0;
  529. ULONG SizeZeroedOut2 = 0;
  530. PIMAGE_SECTION_HEADER NtSection;
  531. PIMAGE_DEBUG_DIRECTORY Debug;
  532. PIMAGE_EXPORT_DIRECTORY Export;
  533. BOOL DeleteHeader, AfterResource;
  534. //
  535. // Set up virtual addresses of sections of interest
  536. //
  537. DirectoryAddressA = NtHeader1->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IAT].VirtualAddress;
  538. DirectoryAddressB = NtHeader1->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT].VirtualAddress;
  539. DirectoryAddressD = NtHeader1->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress;
  540. DirectoryAddressI = NtHeader1->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress;
  541. DirectoryAddressE = NtHeader1->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;
  542. DirectoryAddressR = NtHeader1->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress;
  543. //
  544. // Zero out Binding Info
  545. //
  546. if ( ( DirectoryAddressB < NtHeader1->OptionalHeader.SizeOfHeaders) && ( 0 < DirectoryAddressB))
  547. {
  548. // fprintf( stdout, "ZeroMemoryBa %lx\n", DirectoryAddressB );
  549. ZeroMemory( (PVOID)( (ULONG_PTR)MappedAddr1 + DirectoryAddressB) ,
  550. NtHeader1->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT].Size);
  551. }
  552. NtSection = (PIMAGE_SECTION_HEADER)(
  553. (ULONG_PTR)NtHeader1 +
  554. sizeof( ULONG) +
  555. sizeof( IMAGE_FILE_HEADER) +
  556. NtHeader1->FileHeader.SizeOfOptionalHeader
  557. );
  558. AfterResource = FALSE; // Initialize
  559. //
  560. // Loop through file1 mapping zeroing out ignore sections
  561. //
  562. for ( i=0; i<NtHeader1->FileHeader.NumberOfSections; i++)
  563. {
  564. DeleteHeader = FALSE; // Initialize
  565. //
  566. // Deal with IAT
  567. //
  568. if ( DirectoryAddressA >= NtSection->VirtualAddress &&
  569. DirectoryAddressA < NtSection->VirtualAddress + NtSection->SizeOfRawData)
  570. {
  571. // fprintf ( stdout, "ZeroMemoryA1 start %lx and length %lx\n", ( ( DirectoryAddressA - NtSection->VirtualAddress) + NtSection->PointerToRawData),
  572. // NtHeader1->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IAT].Size);
  573. ZeroMemory( (PVOID)( (ULONG_PTR)MappedAddr1 + ( DirectoryAddressA - NtSection->VirtualAddress) + NtSection->PointerToRawData),
  574. NtHeader1->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IAT].Size);
  575. DeleteHeader = TRUE;
  576. }
  577. //
  578. // Deal with Import
  579. //
  580. if ( DirectoryAddressI >= NtSection->VirtualAddress &&
  581. DirectoryAddressI < NtSection->VirtualAddress + NtSection->SizeOfRawData)
  582. {
  583. // fprintf ( stdout, "ZeroMemoryI1 start %lx and length %lx\n", ( ( DirectoryAddressI - NtSection->VirtualAddress) + NtSection->PointerToRawData),
  584. // NtHeader1->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size);
  585. ZeroMemory( (PVOID)( (ULONG_PTR)MappedAddr1 + ( DirectoryAddressI - NtSection->VirtualAddress) + NtSection->PointerToRawData),
  586. NtHeader1->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size);
  587. DeleteHeader = TRUE;
  588. }
  589. //
  590. // Deal with Export
  591. //
  592. if ( DirectoryAddressE >= NtSection->VirtualAddress &&
  593. DirectoryAddressE < NtSection->VirtualAddress + NtSection->SizeOfRawData)
  594. {
  595. ULONG NumberOfExportDirectories;
  596. NumberOfExportDirectories = NtHeader1->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size / sizeof( IMAGE_EXPORT_DIRECTORY );
  597. Export = (PIMAGE_EXPORT_DIRECTORY)( (ULONG_PTR)MappedAddr1 + ( DirectoryAddressE - NtSection->VirtualAddress) + NtSection->PointerToRawData);
  598. for ( c=0; c<NumberOfExportDirectories; c++)
  599. {
  600. // fprintf ( stdout, "ZeroMemoryE1 start %lx and length %lx\n", ( ( DirectoryAddressE - NtSection->VirtualAddress) + NtSection->PointerToRawData),
  601. // NtHeader1->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size);
  602. Export->TimeDateStamp = 0;
  603. Export++;
  604. }
  605. }
  606. //
  607. // Deal with Debug
  608. //
  609. if ( DirectoryAddressD >= NtSection->VirtualAddress &&
  610. DirectoryAddressD < NtSection->VirtualAddress + NtSection->SizeOfRawData)
  611. {
  612. DWORD TimeDate;
  613. ULONG NumberOfDebugDirectories;
  614. NumberOfDebugDirectories = NtHeader1->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].Size / sizeof( IMAGE_DEBUG_DIRECTORY );
  615. Debug = (PIMAGE_DEBUG_DIRECTORY)( (ULONG_PTR)MappedAddr1 + ( DirectoryAddressD - NtSection->VirtualAddress) + NtSection->PointerToRawData);
  616. for ( c=0; c<NumberOfDebugDirectories; c++)
  617. {
  618. // fprintf ( stdout, "ZeroMemoryD1 start %lx and length %lx\n", ( ( DirectoryAddressD - NtSection->VirtualAddress) + NtSection->PointerToRawData),
  619. // NtHeader1->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].Size);
  620. if (Debug->PointerToRawData && Debug->SizeOfData)
  621. {
  622. ZeroMemory((PVOID)((ULONG_PTR)MappedAddr1 + Debug->PointerToRawData),
  623. Debug->SizeOfData);
  624. }
  625. Debug->PointerToRawData = 0;
  626. if (c == 0)
  627. {
  628. TimeDate = Debug->TimeDateStamp;
  629. }
  630. Debug->TimeDateStamp = 0;
  631. Debug++;
  632. }
  633. while ( Debug->TimeDateStamp == TimeDate)
  634. {
  635. Debug->TimeDateStamp = 0;
  636. Debug++;
  637. }
  638. }
  639. //
  640. // Deal with Resource
  641. //
  642. if ( DirectoryAddressR >= NtSection->VirtualAddress &&
  643. DirectoryAddressR < NtSection->VirtualAddress + NtSection->SizeOfRawData)
  644. {
  645. SizetoResource1 = ( ( DirectoryAddressR - NtSection->VirtualAddress) + NtSection->PointerToRawData);
  646. SizeZeroedOut1 = NtSection->SizeOfRawData;
  647. // fprintf ( stdout, "ZeroMemoryR1 start %lx and length %lx\n", SizetoResource1,
  648. // SizeZeroedOut1);
  649. ZeroMemory( (PVOID)( (ULONG_PTR)MappedAddr1 + SizetoResource1),
  650. SizeZeroedOut1);
  651. DeleteHeader = TRUE;
  652. AfterResource = TRUE;
  653. }
  654. //
  655. // Deal with Header
  656. //
  657. if ( DeleteHeader || AfterResource)
  658. {
  659. // fprintf ( stdout, "ZeroMemoryH1 start %lx and length %lx\n", (PUCHAR)NtSection - (PUCHAR)MappedAddr1, sizeof( IMAGE_SECTION_HEADER));
  660. ZeroMemory( NtSection, sizeof( IMAGE_SECTION_HEADER));
  661. }
  662. ++NtSection;
  663. }
  664. //
  665. // Set up virtual addresses of sections of interest
  666. //
  667. DirectoryAddressA = NtHeader2->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IAT].VirtualAddress;
  668. DirectoryAddressB = NtHeader2->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT].VirtualAddress;
  669. DirectoryAddressI = NtHeader2->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress;
  670. DirectoryAddressE = NtHeader2->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;
  671. DirectoryAddressD = NtHeader2->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress;
  672. DirectoryAddressR = NtHeader2->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress;
  673. NtSection = (PIMAGE_SECTION_HEADER)(
  674. (ULONG_PTR)NtHeader2 +
  675. sizeof( ULONG) +
  676. sizeof( IMAGE_FILE_HEADER) +
  677. NtHeader2->FileHeader.SizeOfOptionalHeader
  678. );
  679. //
  680. // Zero out Binding Info
  681. //
  682. if ( ( DirectoryAddressB < NtHeader2->OptionalHeader.SizeOfHeaders) && ( 0 < DirectoryAddressB))
  683. {
  684. // fprintf( stdout, "ZeroMemoryBb %lx\n", DirectoryAddressB );
  685. ZeroMemory( (PVOID)( (ULONG_PTR)MappedAddr2 + DirectoryAddressB) ,
  686. NtHeader2->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT].Size);
  687. }
  688. AfterResource = FALSE; //Initialize
  689. //
  690. // Loop through file2 mapping zeroing out ignore sections
  691. //
  692. for ( i=0; i<NtHeader2->FileHeader.NumberOfSections; i++)
  693. {
  694. DeleteHeader = FALSE; // Initialize
  695. //
  696. // Deal with IAT
  697. //
  698. if ( DirectoryAddressA >= NtSection->VirtualAddress &&
  699. DirectoryAddressA < NtSection->VirtualAddress + NtSection->SizeOfRawData)
  700. {
  701. // fprintf ( stdout, "ZeroMemoryA2 start %lx and length %lx\n", ( ( DirectoryAddressA - NtSection->VirtualAddress) + NtSection->PointerToRawData),
  702. // NtHeader2->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IAT].Size);
  703. ZeroMemory( (PVOID)( (ULONG_PTR)MappedAddr2 + ( DirectoryAddressA - NtSection->VirtualAddress) + NtSection->PointerToRawData),
  704. NtHeader2->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IAT].Size);
  705. DeleteHeader = TRUE;
  706. }
  707. //
  708. // Deal with Import
  709. //
  710. if ( DirectoryAddressI >= NtSection->VirtualAddress &&
  711. DirectoryAddressI < NtSection->VirtualAddress + NtSection->SizeOfRawData)
  712. {
  713. // fprintf ( stdout, "ZeroMemoryI2 start %lx and length %lx\n", ( ( DirectoryAddressI - NtSection->VirtualAddress) + NtSection->PointerToRawData),
  714. // NtHeader2->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size);
  715. ZeroMemory( (PVOID)( (ULONG_PTR)MappedAddr2 + ( DirectoryAddressI - NtSection->VirtualAddress) + NtSection->PointerToRawData),
  716. NtHeader2->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size);
  717. DeleteHeader = TRUE;
  718. }
  719. //
  720. // Deal with Export
  721. //
  722. if ( DirectoryAddressE >= NtSection->VirtualAddress &&
  723. DirectoryAddressE < NtSection->VirtualAddress + NtSection->SizeOfRawData)
  724. {
  725. ULONG NumberOfExportDirectories;
  726. NumberOfExportDirectories = NtHeader2->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size / sizeof( IMAGE_EXPORT_DIRECTORY );
  727. Export = (PIMAGE_EXPORT_DIRECTORY)( (ULONG_PTR)MappedAddr2 + ( DirectoryAddressE - NtSection->VirtualAddress) + NtSection->PointerToRawData);
  728. for ( c=0; c<NumberOfExportDirectories; c++)
  729. {
  730. // fprintf ( stdout, "ZeroMemoryE2 start %lx and length %lx\n", ( ( DirectoryAddressE - NtSection->VirtualAddress) + NtSection->PointerToRawData),
  731. // NtHeader2->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size);
  732. Export->TimeDateStamp = 0;
  733. Export++;
  734. }
  735. }
  736. //
  737. // Deal with Debug
  738. //
  739. if ( DirectoryAddressD >= NtSection->VirtualAddress &&
  740. DirectoryAddressD < NtSection->VirtualAddress + NtSection->SizeOfRawData)
  741. {
  742. DWORD TimeDate;
  743. ULONG NumberOfDebugDirectories;
  744. NumberOfDebugDirectories = NtHeader2->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].Size / sizeof( IMAGE_DEBUG_DIRECTORY );
  745. Debug = (PIMAGE_DEBUG_DIRECTORY)( (ULONG_PTR)MappedAddr2 + ( DirectoryAddressD - NtSection->VirtualAddress) + NtSection->PointerToRawData);
  746. for ( c=0; c<NumberOfDebugDirectories; c++)
  747. {
  748. // fprintf ( stdout, "ZeroMemoryD2 start %lx and length %lx\n", ( ( DirectoryAddressD - NtSection->VirtualAddress) + NtSection->PointerToRawData),
  749. // NtHeader2->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].Size);
  750. if (Debug->PointerToRawData && Debug->SizeOfData)
  751. {
  752. ZeroMemory((PVOID)((ULONG_PTR)MappedAddr2 + Debug->PointerToRawData),
  753. Debug->SizeOfData);
  754. }
  755. Debug->PointerToRawData = 0;
  756. if (c == 0)
  757. {
  758. TimeDate = Debug->TimeDateStamp;
  759. }
  760. Debug->TimeDateStamp = 0;
  761. Debug++;
  762. }
  763. while ( Debug->TimeDateStamp == TimeDate)
  764. {
  765. Debug->TimeDateStamp = 0;
  766. Debug++;
  767. }
  768. }
  769. //
  770. // Deal with Resource
  771. //
  772. if ( DirectoryAddressR >= NtSection->VirtualAddress &&
  773. DirectoryAddressR < NtSection->VirtualAddress + NtSection->SizeOfRawData)
  774. {
  775. SizetoResource2 = ( ( DirectoryAddressR - NtSection->VirtualAddress) + NtSection->PointerToRawData);
  776. SizeZeroedOut2 = NtSection->SizeOfRawData;
  777. // fprintf ( stdout, "ZeroMemoryR2 start %lx and length %lx\n", SizetoResource2,
  778. // SizeZeroedOut2);
  779. ZeroMemory( (PVOID)( (ULONG_PTR)MappedAddr2 + SizetoResource2),
  780. SizeZeroedOut2);
  781. DeleteHeader = TRUE;
  782. AfterResource = TRUE;
  783. }
  784. //
  785. // Deal with Header
  786. //
  787. if ( DeleteHeader || AfterResource)
  788. {
  789. // fprintf( stdout, "ZeroMemoryH2 start %lx and length %lx\n", (PUCHAR)NtSection - (PUCHAR)MappedAddr2, sizeof( IMAGE_SECTION_HEADER));
  790. ZeroMemory( NtSection, sizeof( IMAGE_SECTION_HEADER));
  791. }
  792. ++NtSection;
  793. }
  794. //
  795. // Zero out header info
  796. //
  797. NtHeader1->FileHeader.TimeDateStamp = 0;
  798. NtHeader2->FileHeader.TimeDateStamp = 0;
  799. NtHeader1->OptionalHeader.CheckSum = 0;
  800. NtHeader2->OptionalHeader.CheckSum = 0;
  801. NtHeader1->OptionalHeader.SizeOfInitializedData = 0;
  802. NtHeader2->OptionalHeader.SizeOfInitializedData = 0;
  803. NtHeader1->OptionalHeader.SizeOfImage = 0;
  804. NtHeader2->OptionalHeader.SizeOfImage = 0;
  805. NtHeader1->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE].Size = 0;
  806. NtHeader2->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE].Size = 0;
  807. NtHeader1->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT].Size = 0;
  808. NtHeader2->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT].Size = 0;
  809. NtHeader1->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT].VirtualAddress = 0;
  810. NtHeader2->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT].VirtualAddress = 0;
  811. NtHeader1->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress = 0;
  812. NtHeader2->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress = 0;
  813. //
  814. // Do compares here
  815. //
  816. if ( SizetoResource1 == SizetoResource2)
  817. {
  818. if ( memcmp( MappedAddr1, MappedAddr2, SizetoResource1) == 0)
  819. {
  820. SizetoEndofFile1 = GetFileSize( hFile1, NULL) - ( SizetoResource1 + SizeZeroedOut1);
  821. SizetoEndofFile2 = GetFileSize( hFile2, NULL) - ( SizetoResource2 + SizeZeroedOut2);
  822. if ( SizetoEndofFile1 == SizetoEndofFile2)
  823. {
  824. if ( memcmp( (PVOID)( (ULONG_PTR)MappedAddr1 + SizetoResource1 + SizeZeroedOut1), (PVOID)( ( ULONG_PTR)MappedAddr2 + SizetoResource2 + SizeZeroedOut2), SizetoEndofFile1) == 0)
  825. {
  826. UnmapViewOfFile( MappedAddr1 );
  827. UnmapViewOfFile( MappedAddr2 );
  828. CloseHandle( hFile1 );
  829. CloseHandle( hFile2 );
  830. return TRUE;
  831. }
  832. }
  833. }
  834. }
  835. UnmapViewOfFile( MappedAddr1 );
  836. UnmapViewOfFile( MappedAddr2 );
  837. CloseHandle( hFile1 );
  838. CloseHandle( hFile2 );
  839. return FALSE;
  840. }
  841. except( EXCEPTION_EXECUTE_HANDLER )
  842. {
  843. UnmapViewOfFile( MappedAddr1 );
  844. UnmapViewOfFile( MappedAddr2 );
  845. CloseHandle( hFile1 );
  846. CloseHandle( hFile2 );
  847. if ( !NoMapBinaryCompare( file1, file2))
  848. {
  849. return FALSE;
  850. } else
  851. {
  852. return TRUE;
  853. }
  854. }
  855. }
  856. _unlink( RebasedFile2); // Delete RebasedFile that might have been created
  857. }
  858. if ( GetFileSize( hFile1, NULL) == GetFileSize( hFile2, NULL) )
  859. {
  860. try
  861. {
  862. if ( memcmp( MappedAddr1, MappedAddr2, GetFileSize( hFile1, NULL)) == 0)
  863. {
  864. UnmapViewOfFile( MappedAddr1 );
  865. UnmapViewOfFile( MappedAddr2 );
  866. CloseHandle( hFile1 );
  867. CloseHandle( hFile2 );
  868. return TRUE;
  869. }
  870. }
  871. except( EXCEPTION_EXECUTE_HANDLER )
  872. {
  873. UnmapViewOfFile( MappedAddr1 );
  874. UnmapViewOfFile( MappedAddr2 );
  875. CloseHandle( hFile1 );
  876. CloseHandle( hFile2 );
  877. if ( !NoMapBinaryCompare( file1, file2))
  878. {
  879. return FALSE;
  880. } else
  881. {
  882. return TRUE;
  883. }
  884. }
  885. }
  886. UnmapViewOfFile( MappedAddr1 );
  887. UnmapViewOfFile( MappedAddr2 );
  888. CloseHandle( hFile1 );
  889. CloseHandle( hFile2 );
  890. return FALSE;
  891. }
  892. int Mymemcmp( const void *buf1, const void *buf2, size_t count )
  893. {
  894. size_t memoffset = 0;
  895. int retval = FALSE;
  896. do
  897. {
  898. try
  899. {
  900. if ( memcmp( (PVOID)( (PCHAR)buf1 + memoffset), (PVOID)( (PCHAR)buf2 + memoffset), sizeof( size_t)) != 0)
  901. {
  902. fprintf( stdout, "Offset is %Lx ", memoffset);
  903. fprintf( stdout, "Contents are %Lx and %Lx\n", *( (PULONG)( (PCHAR)buf1 + memoffset)), *( (PULONG)( (PCHAR)buf2 + memoffset)) );
  904. retval = TRUE;
  905. }
  906. }
  907. except( EXCEPTION_EXECUTE_HANDLER )
  908. {
  909. fprintf( stdout, "Memory not allocated\n");
  910. }
  911. } while ( ( memoffset = memoffset + sizeof( size_t)) < count);
  912. return retval;
  913. }
  914. //
  915. // CompDir turns Path1 and Path2 into:
  916. //
  917. // AddList - Files that exist in Path1 but not in Path2
  918. //
  919. // DelList - Files that do not exist in Path1 but exist in Path2
  920. //
  921. // DifList - Files that are different between Path1 and Path2 based
  922. // on criteria provided by flags passed to CompDir
  923. //
  924. // It then passes these lists to CompLists and processes the result.
  925. //
  926. void CompDir( char *Path1, char *Path2)
  927. {
  928. LinkedFileList AddList, DelList, DifList;
  929. struct CFLStruct Parameter1, Parameter2;
  930. DWORD Id;
  931. HANDLE Threads[2];
  932. DWORD CFReturn;
  933. AddList = NULL; //
  934. DelList = NULL; // Start with empty lists
  935. DifList = NULL; //
  936. Parameter1.List = &AddList;
  937. Parameter1.Path = Path1;
  938. if ( fMultiThread)
  939. {
  940. Threads[0] = CreateThread(
  941. NULL,
  942. 0,
  943. CreateFileList,
  944. &Parameter1,
  945. 0,
  946. &Id
  947. );
  948. if ( Threads[0] == NULL)
  949. {
  950. fprintf( stderr, "CreateThread1Failed, error code %d\n", GetLastError() );
  951. CreateFileList( &Parameter1);
  952. fMultiThread = FALSE;
  953. }
  954. } else
  955. {
  956. CreateFileList( &Parameter1);
  957. }
  958. Parameter2.List = &DelList;
  959. Parameter2.Path = Path2;
  960. if ( fMultiThread)
  961. {
  962. Threads[1] = CreateThread(
  963. NULL,
  964. 0,
  965. CreateFileList,
  966. &Parameter2,
  967. 0,
  968. &Id
  969. );
  970. if ( Threads[1] == NULL)
  971. {
  972. fprintf( stderr, "CreateThread2Failed, error code %d\n", GetLastError() );
  973. CFReturn = CreateFileList( &Parameter2);
  974. fMultiThread = FALSE;
  975. }
  976. } else
  977. {
  978. CFReturn = CreateFileList( &Parameter2);
  979. }
  980. if ( fMultiThread)
  981. {
  982. Id = WaitForMultipleObjects(
  983. 2,
  984. Threads,
  985. TRUE,
  986. (DWORD)-1
  987. );
  988. GetExitCodeThread( Threads[1], &CFReturn);
  989. CloseHandle( Threads[0]);
  990. CloseHandle( Threads[1]);
  991. }
  992. if ( CFReturn == 0)
  993. {
  994. CompLists( &AddList, &DelList, &DifList, Path1, Path2);
  995. ProcessLists( AddList, DelList, DifList, Path1, Path2);
  996. }
  997. FreeList( &DifList);
  998. FreeList( &DelList);
  999. FreeList( &AddList);
  1000. } // CompDir
  1001. BOOL FilesDiffer( LinkedFileList File1, LinkedFileList File2, char *Path1, char *Path2)
  1002. {
  1003. DWORD High1, High2, Low1, Low2; // Used in comparing times
  1004. BOOL Differ = FALSE;
  1005. char *FullPath1, *FullPath2;
  1006. //
  1007. // Check if same name is a directory under Path1
  1008. // and a file under Path2 or vice-versa
  1009. //
  1010. if (
  1011. ( (*File1).Attributes & FILE_ATTRIBUTE_DIRECTORY)
  1012. ||
  1013. ( (*File2).Attributes & FILE_ATTRIBUTE_DIRECTORY)
  1014. )
  1015. {
  1016. if ( ( (*File1).Attributes & FILE_ATTRIBUTE_DIRECTORY) && ( (*File2).Attributes & FILE_ATTRIBUTE_DIRECTORY))
  1017. {
  1018. if ( !fDoNotRecurse)
  1019. {
  1020. //
  1021. // Create Full Path Strings
  1022. //
  1023. _strrev( (*File1).Name);
  1024. _strrev( (*File2).Name);
  1025. if ( DealingWithDirectories)
  1026. {
  1027. ( Path1[strlen( Path1) - 1] == '\\') ? ( FullPath1 = MYSTRCAT( Path1, (*File1).Name)) :
  1028. ( FullPath1 = COMBINETHREESTRINGS( Path1, "\\", (*File1).Name));
  1029. ( Path2[strlen( Path2) - 1] == '\\') ? ( FullPath2 = MYSTRCAT( Path2, (*File1).Name)) :
  1030. ( FullPath2 = COMBINETHREESTRINGS( Path2, "\\", (*File1).Name));
  1031. } else
  1032. {
  1033. FullPath1 = MYSTRCAT( Path1, "");
  1034. FullPath2 = MYSTRCAT( Path2, "");
  1035. }
  1036. _strrev( (*File1).Name);
  1037. _strrev( (*File2).Name);
  1038. CompDir( FullPath1, FullPath2);
  1039. FREE( FullPath1);
  1040. FREE( FullPath2);
  1041. }
  1042. } else
  1043. {
  1044. if( ! ( (*File1).Attributes & FILE_ATTRIBUTE_DIRECTORY))
  1045. {
  1046. strcat( (*File1).Flag, "@");
  1047. } else
  1048. {
  1049. strcat( (*File2).Flag, "@");
  1050. }
  1051. Differ = TRUE;
  1052. }
  1053. } else
  1054. {
  1055. if ( fCheckTime)
  1056. {
  1057. if ( Granularity)
  1058. {
  1059. //
  1060. // Bit manipulation to deal with large integers.
  1061. //
  1062. High1 = (*File1).Time.dwHighDateTime>>23;
  1063. High2 = (*File2).Time.dwHighDateTime>>23;
  1064. if ( High1 == High2)
  1065. {
  1066. Low1 = ( (*File1).Time.dwHighDateTime<<9) |
  1067. ( (*File1).Time.dwLowDateTime>>23);
  1068. Low2 = ( (*File2).Time.dwHighDateTime<<9) |
  1069. ( (*File2).Time.dwLowDateTime>>23);
  1070. if ( ( ( Low1 > Low2) ? ( Low1 - Low2) : ( Low2 - Low1))
  1071. > Granularity)
  1072. {
  1073. strcat( (*File1).Flag, "T");
  1074. Differ = TRUE;
  1075. }
  1076. } else
  1077. {
  1078. Differ = TRUE;
  1079. }
  1080. } else if ( CompareFileTime( &( (*File1).Time),
  1081. &( (*File2).Time)) != 0)
  1082. {
  1083. strcat( (*File1).Flag, "T");
  1084. Differ = TRUE;
  1085. }
  1086. }
  1087. if ( fCheckSize &&
  1088. (
  1089. ( (*File1).SizeLow != (*File2).SizeLow)
  1090. ||
  1091. ( (*File1).SizeHigh != (*File2).SizeHigh)
  1092. )
  1093. )
  1094. {
  1095. strcat( (*File1).Flag, "S");
  1096. Differ = TRUE;
  1097. }
  1098. if ( fCheckAttribs)
  1099. {
  1100. if ( ((*File1).Attributes ^ (*File2).Attributes) & NORMAL_ATTRIBUTES)
  1101. {
  1102. strcat( (*File1).Flag, "A");
  1103. Differ = TRUE;
  1104. }
  1105. }
  1106. if ( fCheckBits)
  1107. {
  1108. //
  1109. // Create Full Path Strings
  1110. //
  1111. _strrev( (*File1).Name);
  1112. _strrev( (*File2).Name);
  1113. if ( DealingWithDirectories)
  1114. {
  1115. ( Path1[strlen( Path1) - 1] == '\\') ? ( FullPath1 = MYSTRCAT( Path1, (*File1).Name)) :
  1116. ( FullPath1 = COMBINETHREESTRINGS( Path1, "\\", (*File1).Name));
  1117. ( Path2[strlen( Path2) - 1] == '\\') ? ( FullPath2 = MYSTRCAT( Path2, (*File1).Name)) :
  1118. ( FullPath2 = COMBINETHREESTRINGS( Path2, "\\", (*File1).Name));
  1119. } else
  1120. {
  1121. FullPath1 = MYSTRCAT( Path1, "");
  1122. FullPath2 = MYSTRCAT( Path2, "");
  1123. }
  1124. _strrev( (*File1).Name);
  1125. _strrev( (*File2).Name);
  1126. if ( fIgnoreRs)
  1127. {
  1128. if (
  1129. (
  1130. (*File1).SizeLow != 0
  1131. ||
  1132. (*File1).SizeHigh != 0)
  1133. &&
  1134. ( !BinaryCompare( FullPath1, FullPath2)
  1135. )
  1136. )
  1137. {
  1138. strcat( (*File1).Flag, "B");
  1139. Differ = TRUE;
  1140. }
  1141. } else
  1142. {
  1143. if (
  1144. ( (*File1).SizeLow != (*File2).SizeLow)
  1145. ||
  1146. ( (*File1).SizeHigh != (*File2).SizeHigh)
  1147. ||
  1148. (
  1149. (
  1150. (*File1).SizeLow != 0
  1151. ||
  1152. (*File1).SizeHigh != 0
  1153. )
  1154. &&
  1155. ( !BinaryCompare( FullPath1, FullPath2))
  1156. )
  1157. )
  1158. {
  1159. strcat( (*File1).Flag, "B");
  1160. Differ = TRUE;
  1161. }
  1162. }
  1163. FREE( FullPath1);
  1164. FREE( FullPath2);
  1165. }
  1166. if ( fForce)
  1167. {
  1168. Differ = TRUE;
  1169. }
  1170. }
  1171. return Differ;
  1172. } // FilesDiffer
  1173. //
  1174. // CompLists Does the dirty work for CompDir
  1175. //
  1176. void CompLists( LinkedFileList *AddList, LinkedFileList *DelList, LinkedFileList *DifList, char *Path1, char *Path2)
  1177. {
  1178. LinkedFileList *TmpAdd, *TmpDel, TmpNode;
  1179. char *FullPath1, *FullPath2;
  1180. if ( ( DelList == NULL) || ( *DelList == NULL) || ( AddList == NULL) || ( *AddList == NULL))
  1181. {
  1182. return;
  1183. }
  1184. TmpAdd = AddList; // pointer to keep track of position in addlist
  1185. if ( *TmpAdd != NULL)
  1186. {
  1187. TmpAdd = &( **TmpAdd).First;
  1188. }
  1189. do
  1190. {
  1191. if ( DealingWithDirectories)
  1192. {
  1193. TmpDel = FindInList( ( **TmpAdd).Name, DelList);
  1194. } else
  1195. {
  1196. TmpDel = DelList;
  1197. }
  1198. if ( TmpDel != NULL)
  1199. {
  1200. if ( FilesDiffer( *TmpAdd, *TmpDel, Path1, Path2))
  1201. {
  1202. //
  1203. // Combine Both Nodes together so they
  1204. // can be printed out together
  1205. //
  1206. DuplicateNode( *TmpAdd, &TmpNode);
  1207. DuplicateNode( *TmpDel, &( *TmpNode).DiffNode);
  1208. AddToList( TmpNode, DifList);
  1209. ( **TmpDel).Process = FALSE;
  1210. ( **TmpAdd).Process = FALSE;
  1211. } else
  1212. {
  1213. ( **TmpDel).Process = FALSE;
  1214. ( **TmpAdd).Process = !ProcessModeDefault;
  1215. }
  1216. } else if ( SparseTree && ( ( **TmpAdd).Attributes & FILE_ATTRIBUTE_DIRECTORY))
  1217. {
  1218. if ( !fDoNotRecurse)
  1219. {
  1220. _strrev( ( **TmpAdd).Name);
  1221. ( Path1[strlen( Path1) - 1] == '\\') ? ( FullPath1 = MYSTRCAT( Path1, ( **TmpAdd).Name)) :
  1222. ( FullPath1 = COMBINETHREESTRINGS( Path1, "\\", ( **TmpAdd).Name));
  1223. ( Path2[strlen( Path2) - 1] == '\\') ? ( FullPath2 = MYSTRCAT( Path2, ( **TmpAdd).Name)) :
  1224. ( FullPath2 = COMBINETHREESTRINGS( Path2, "\\", ( **TmpAdd).Name));
  1225. _strrev( ( **TmpAdd).Name);
  1226. CompDir( FullPath1, FullPath2);
  1227. }
  1228. } // if ( *TmpDel != NULL)
  1229. TmpAdd = &( ( **TmpAdd).Next);
  1230. } while ( *TmpAdd != NULL);
  1231. } // CompLists
  1232. //
  1233. // CopyNode walks the source node and its children ( recursively)
  1234. // and creats the appropriate parts on the destination node
  1235. //
  1236. void CopyNode ( char *Destination, LinkedFileList Source, char *FullPathSrc)
  1237. {
  1238. BOOL pend, CanDetectFreeSpace = TRUE;
  1239. int i;
  1240. DWORD sizeround;
  1241. DWORD BytesPerCluster;
  1242. ATTRIBUTE_TYPE Attributes;
  1243. int LastErrorGot;
  1244. __int64 freespac;
  1245. char root[5] = {*Destination,':','\\','\0'};
  1246. DWORD cSecsPerClus, cBytesPerSec, cFreeClus, cTotalClus;
  1247. if ( !GetDiskFreeSpace( root, &cSecsPerClus, &cBytesPerSec, &cFreeClus, &cTotalClus ) )
  1248. {
  1249. CanDetectFreeSpace = FALSE;
  1250. } else
  1251. {
  1252. freespac = ( (__int64)cBytesPerSec * (__int64)cSecsPerClus * (__int64)cFreeClus );
  1253. BytesPerCluster = cSecsPerClus * cBytesPerSec;
  1254. }
  1255. fprintf( stdout, "%s => %s\t", FullPathSrc, Destination);
  1256. if ( CanDetectFreeSpace)
  1257. {
  1258. sizeround = (*Source).SizeLow;
  1259. sizeround += BytesPerCluster - 1;
  1260. sizeround /= BytesPerCluster;
  1261. sizeround *= BytesPerCluster;
  1262. if ( freespac < sizeround)
  1263. {
  1264. fprintf( stderr, "not enough space\n");
  1265. return;
  1266. }
  1267. }
  1268. GET_ATTRIBUTES( Destination, Attributes);
  1269. i = SET_ATTRIBUTES( Destination, Attributes & NONREADONLYSYSTEMHIDDEN );
  1270. i = 1;
  1271. do
  1272. {
  1273. if ( !fCreateLink)
  1274. {
  1275. if ( !fBreakLinks)
  1276. {
  1277. pend = MyCopyFile( FullPathSrc, Destination, FALSE);
  1278. } else
  1279. {
  1280. _unlink( Destination);
  1281. pend = MyCopyFile( FullPathSrc, Destination, FALSE);
  1282. }
  1283. } else
  1284. {
  1285. if ( i == 1)
  1286. {
  1287. pend = MakeLink( FullPathSrc, Destination, FALSE);
  1288. } else
  1289. {
  1290. pend = MakeLink( FullPathSrc, Destination, TRUE);
  1291. }
  1292. }
  1293. if ( SparseTree && !pend)
  1294. {
  1295. if ( !MyCreatePath( Destination, FALSE))
  1296. {
  1297. fprintf( stderr, "Unable to create path %s", Destination);
  1298. ExitValue = 1;
  1299. }
  1300. }
  1301. } while ( ( i++ < 2) && ( !pend) );
  1302. if ( !pend)
  1303. {
  1304. LastErrorGot = GetLastError ();
  1305. if ( ( fCreateLink) && ( LastErrorGot == 1))
  1306. {
  1307. fprintf( stderr, "Can only make links on NTFS and OFS");
  1308. } else if ( fCreateLink)
  1309. {
  1310. fprintf( stderr, "(error = %d)", LastErrorGot);
  1311. } else
  1312. {
  1313. fprintf( stderr, "Copy Error (error = %d)", LastErrorGot);
  1314. }
  1315. ExitValue = 1;
  1316. }
  1317. if ( pend)
  1318. {
  1319. fprintf( stdout, "[OK]\n");
  1320. } else
  1321. {
  1322. fprintf( stderr, "\n");
  1323. }
  1324. //
  1325. // Copy attributes from Source to Destination
  1326. //
  1327. // GET_ATTRIBUTES( FullPathSrc, Attributes);
  1328. if ( !fDontCopyAttribs)
  1329. {
  1330. i = SET_ATTRIBUTES( Destination, Source->Attributes);
  1331. }
  1332. else
  1333. {
  1334. i = SET_ATTRIBUTES( Destination, FILE_ATTRIBUTE_ARCHIVE);
  1335. }
  1336. } // CopyNode
  1337. //
  1338. // CreateFileList walks down list adding files as they are found
  1339. //
  1340. DWORD CreateFileList( LPVOID ThreadParameter)
  1341. {
  1342. PCFLStruct Parameter = ( PCFLStruct)ThreadParameter;
  1343. LinkedFileList *List = Parameter->List;
  1344. char *Path = Parameter->Path;
  1345. char *String;
  1346. LinkedFileList Node;
  1347. ATTRIBUTE_TYPE Attributes;
  1348. HANDLE handle;
  1349. WIN32_FIND_DATA Buff;
  1350. IF_GET_ATTR_FAILS( Path, Attributes)
  1351. {
  1352. return 0;
  1353. }
  1354. if ( Attributes & FILE_ATTRIBUTE_DIRECTORY)
  1355. {
  1356. ( Path[strlen( Path) - 1] != '\\') ? ( String = MYSTRCAT( Path,"\\*.*")) :
  1357. ( String = MYSTRCAT( Path,"*.*"));
  1358. handle = FIND_FIRST( String, Buff);
  1359. } else
  1360. {
  1361. handle = FIND_FIRST( Path, Buff);
  1362. }
  1363. FREE( String);
  1364. if ( handle != INVALID_HANDLE_VALUE)
  1365. {
  1366. //
  1367. // Need to find the '.' or '..' directories and get them out of the way
  1368. //
  1369. do
  1370. {
  1371. if (
  1372. ( strcmp( Buff.cFileName, ".") != 0)
  1373. &&
  1374. ( strcmp( Buff.cFileName, "..") != 0)
  1375. &&
  1376. ( ((Buff.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0) ||
  1377. !fDoNotRecurse)
  1378. )
  1379. {
  1380. //
  1381. // If extensions are defined we match them here
  1382. //
  1383. if (
  1384. ( !Excludes )
  1385. ||
  1386. ( Excludes && ( !Excluded( Buff.cFileName, Path)) )
  1387. )
  1388. {
  1389. if (
  1390. ( !Matches )
  1391. ||
  1392. ( ( Buff.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) )
  1393. ||
  1394. ( Matches && ( Matched( Buff.cFileName, Path)) )
  1395. )
  1396. {
  1397. if ( !fIgnoreSlmFiles
  1398. ||
  1399. (
  1400. (_stricmp( Buff.cFileName, "slm.ini") != 0)
  1401. &&
  1402. (_stricmp( Buff.cFileName, "slm.dif") != 0)
  1403. &&
  1404. (_stricmp( Buff.cFileName, "iedcache.slm.v6") != 0)
  1405. )
  1406. )
  1407. {
  1408. if ( fSpecAttribs)
  1409. {
  1410. if ( Buff.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
  1411. {
  1412. CreateNode( &Node, &Buff);
  1413. AddToList( Node, List);
  1414. } else if ( NegativeCompareAttributeSet && CompareAttributeSet)
  1415. {
  1416. if (
  1417. !( Buff.dwFileAttributes & NegativeCompareAttribute)
  1418. &&
  1419. ( ( Buff.dwFileAttributes & CompareAttribute) == CompareAttribute)
  1420. )
  1421. {
  1422. CreateNode( &Node, &Buff);
  1423. AddToList( Node, List);
  1424. }
  1425. } else if ( CompareAttributeSet )
  1426. {
  1427. if ( ( Buff.dwFileAttributes & CompareAttribute) == CompareAttribute)
  1428. {
  1429. CreateNode( &Node, &Buff);
  1430. AddToList( Node, List);
  1431. }
  1432. } else if ( NegativeCompareAttributeSet )
  1433. {
  1434. if ( !( Buff.dwFileAttributes & NegativeCompareAttribute) )
  1435. {
  1436. CreateNode( &Node, &Buff);
  1437. AddToList( Node, List);
  1438. }
  1439. }
  1440. } else
  1441. {
  1442. CreateNode( &Node, &Buff);
  1443. AddToList( Node, List);
  1444. }
  1445. }
  1446. }
  1447. }
  1448. }
  1449. } while ( FIND_NEXT( handle, Buff) == 0);
  1450. } // ( handle != INVALID_HANDLE_VALUE)
  1451. FindClose( handle);
  1452. return 0; // This will exit this thread
  1453. } // CreateFileList
  1454. BOOL DelNode ( char *Path)
  1455. {
  1456. char *String;
  1457. ATTRIBUTE_TYPE Attributes;
  1458. HANDLE handle;
  1459. WIN32_FIND_DATA Buff;
  1460. IF_GET_ATTR_FAILS( Path, Attributes)
  1461. return TRUE;
  1462. if ( Attributes & FILE_ATTRIBUTE_DIRECTORY)
  1463. {
  1464. ( Path[strlen( Path) - 1] != '\\') ? ( String = MYSTRCAT( Path,"\\*.*")) :
  1465. ( String = MYSTRCAT( Path,"*.*"));
  1466. handle = FIND_FIRST( String, Buff);
  1467. if ( handle == INVALID_HANDLE_VALUE)
  1468. {
  1469. fprintf( stderr, "%s is inaccesible\n", Path);
  1470. ExitValue = 1;
  1471. return FALSE;
  1472. }
  1473. FREE( String);
  1474. do
  1475. {
  1476. //
  1477. // Need to find the '.' or '..' directories and get them out of the way
  1478. //
  1479. if (
  1480. ( strcmp( Buff.cFileName, ".") != 0)
  1481. &&
  1482. ( strcmp( Buff.cFileName, "..") != 0)
  1483. )
  1484. {
  1485. //
  1486. // if directory is read-only, make it writable
  1487. //
  1488. if ( Attributes & FILE_ATTRIBUTE_READONLY)
  1489. {
  1490. if ( SET_ATTRIBUTES( Path, Attributes & ~FILE_ATTRIBUTE_READONLY) != 0)
  1491. {
  1492. break;
  1493. }
  1494. }
  1495. String = COMBINETHREESTRINGS( Path, "\\", Buff.cFileName);
  1496. if ( !DelNode( String))
  1497. {
  1498. FREE( String);
  1499. return FALSE;
  1500. } else
  1501. {
  1502. FREE( String);
  1503. }
  1504. }
  1505. } while ( FIND_NEXT( handle, Buff) == 0);
  1506. FindClose( handle);
  1507. if ( _rmdir( Path) != 0)
  1508. {
  1509. return FALSE;
  1510. }
  1511. } else
  1512. {
  1513. //
  1514. // if file is read-only, make it writable
  1515. //
  1516. if ( Attributes & FILE_ATTRIBUTE_READONLY)
  1517. {
  1518. if ( SET_ATTRIBUTES( Path, Attributes & ~FILE_ATTRIBUTE_READONLY) != 0)
  1519. {
  1520. return FALSE;
  1521. }
  1522. }
  1523. if ( _unlink( Path) != 0)
  1524. {
  1525. return FALSE;
  1526. }
  1527. }
  1528. return TRUE;
  1529. } // DelNode
  1530. BOOL IsFlag( char *argv)
  1531. {
  1532. char String[MAX_PATH];
  1533. char *String1, *String2;
  1534. char *TmpArg;
  1535. char *ExcludeFile, *MatchFile;
  1536. FILE *FileHandle;
  1537. LinkedFileList Node;
  1538. BOOL NegationFlagSet = FALSE;
  1539. if ( ( *argv == '/') || ( *argv == '-'))
  1540. {
  1541. fMatching = FALSE; // If there's a new flag then that's the
  1542. fExclude = FALSE; // end of the match/exclude list
  1543. if ( strchr( argv, '?'))
  1544. {
  1545. Usage();
  1546. }
  1547. TmpArg = _strlwr( argv);
  1548. while ( *++TmpArg != '\0')
  1549. {
  1550. switch ( *TmpArg)
  1551. {
  1552. case 'a' :
  1553. fCheckAttribs = !NegationFlagSet;
  1554. NegationFlagSet = FALSE;
  1555. break;
  1556. case 'b' :
  1557. fCheckBits = !NegationFlagSet;
  1558. NegationFlagSet = FALSE;
  1559. break;
  1560. case 'c' :
  1561. fScript = !NegationFlagSet;
  1562. NegationFlagSet = FALSE;
  1563. break;
  1564. case 'd' :
  1565. fDoNotDelete = !NegationFlagSet;
  1566. NegationFlagSet = FALSE;
  1567. break;
  1568. case 'e' :
  1569. fExecute = !NegationFlagSet;
  1570. NegationFlagSet = FALSE;
  1571. break;
  1572. case 'f' :
  1573. fOnlyIfExists = !NegationFlagSet;
  1574. NegationFlagSet = FALSE;
  1575. break;
  1576. case 'g' :
  1577. fIgnoreSlmFiles = !NegationFlagSet;
  1578. NegationFlagSet = FALSE;
  1579. break;
  1580. case 'h' :
  1581. fDontCopyAttribs = !NegationFlagSet;
  1582. NegationFlagSet = FALSE;
  1583. break;
  1584. case 'i' :
  1585. fIgnoreRs = !NegationFlagSet;
  1586. NegationFlagSet = FALSE;
  1587. break;
  1588. case 'k' :
  1589. fBreakLinks = !NegationFlagSet;
  1590. NegationFlagSet = FALSE;
  1591. break;
  1592. case 'l' :
  1593. fCreateLink = !NegationFlagSet;
  1594. NegationFlagSet = FALSE;
  1595. break;
  1596. case 'm' :
  1597. if ( NegationFlagSet) {
  1598. fprintf ( stderr, "can't use - on /m option\n");
  1599. Usage();
  1600. }
  1601. if (
  1602. ( *( TmpArg + 1) == ':')
  1603. &&
  1604. ( *( TmpArg + 2) != '\0')
  1605. )
  1606. {
  1607. ( MatchFile = TmpArg + 2);
  1608. while (isgraph( *( ++TmpArg + 1))) {}
  1609. if ( ( FileHandle = fopen( MatchFile, "r")) == NULL)
  1610. {
  1611. fprintf( stderr, "cannot open %s\n", MatchFile);
  1612. Usage();
  1613. } else
  1614. {
  1615. while ( fgets( String1 = String, MAX_PATH, FileHandle) != NULL)
  1616. {
  1617. while ( *( String2 = &( String1[ strspn( String1, " \n\r") ])))
  1618. {
  1619. if ( *( String1 = &( String2[ strcspn( String2, " \n\r") ])))
  1620. {
  1621. *String1++ = 0;
  1622. CreateNameNode( &Node, String2);
  1623. if ( strchr( String2, '*') != NULL)
  1624. {
  1625. AddToList( Node, &MStarList);
  1626. } else
  1627. {
  1628. AddToList( Node, &MatchList);
  1629. }
  1630. }
  1631. }
  1632. }
  1633. fclose( FileHandle) ;
  1634. }
  1635. }
  1636. fMatching = TRUE;
  1637. Matches = TRUE;
  1638. break;
  1639. case 'n' :
  1640. fCreateNew = !NegationFlagSet;
  1641. NegationFlagSet = FALSE;
  1642. break;
  1643. case 'o' :
  1644. fOpposite = !NegationFlagSet;
  1645. ProcessModeDefault = !fOpposite;
  1646. NegationFlagSet = FALSE;
  1647. break;
  1648. case 'p' :
  1649. if ( NegationFlagSet) {
  1650. fprintf ( stderr, "can't use - on /p option\n");
  1651. Usage();
  1652. }
  1653. if ( *( TmpArg + 1) != '{')
  1654. {
  1655. fprintf ( stderr, "/p option improperly formatted\n");
  1656. Usage();
  1657. }
  1658. TmpArg++;
  1659. while ( *++TmpArg != '}')
  1660. {
  1661. switch ( *TmpArg)
  1662. {
  1663. case 'a' :
  1664. if ( NegationFlagSet)
  1665. {
  1666. if ( !NegativeCompareAttributeSet)
  1667. {
  1668. NegativeCompareAttribute = FILE_ATTRIBUTE_ARCHIVE;
  1669. NegativeCompareAttributeSet = TRUE;
  1670. } else
  1671. {
  1672. NegativeCompareAttribute = NegativeCompareAttribute | FILE_ATTRIBUTE_ARCHIVE;
  1673. }
  1674. } else
  1675. {
  1676. if ( !CompareAttributeSet)
  1677. {
  1678. CompareAttribute = FILE_ATTRIBUTE_ARCHIVE;
  1679. CompareAttributeSet = TRUE;
  1680. } else
  1681. {
  1682. CompareAttribute = CompareAttribute | FILE_ATTRIBUTE_ARCHIVE;
  1683. }
  1684. }
  1685. NegationFlagSet = FALSE;
  1686. break;
  1687. case 'r' :
  1688. if ( NegationFlagSet)
  1689. {
  1690. if ( !NegativeCompareAttributeSet)
  1691. {
  1692. NegativeCompareAttribute = FILE_ATTRIBUTE_READONLY;
  1693. NegativeCompareAttributeSet = TRUE;
  1694. } else
  1695. {
  1696. NegativeCompareAttribute = NegativeCompareAttribute | FILE_ATTRIBUTE_READONLY;
  1697. }
  1698. } else
  1699. {
  1700. if ( !CompareAttributeSet)
  1701. {
  1702. CompareAttribute = FILE_ATTRIBUTE_READONLY;
  1703. CompareAttributeSet = TRUE;
  1704. } else
  1705. {
  1706. CompareAttribute = CompareAttribute | FILE_ATTRIBUTE_READONLY;
  1707. }
  1708. }
  1709. NegationFlagSet = FALSE;
  1710. break;
  1711. case 'h' :
  1712. if ( NegationFlagSet)
  1713. {
  1714. if ( !NegativeCompareAttributeSet)
  1715. {
  1716. NegativeCompareAttribute = FILE_ATTRIBUTE_HIDDEN;
  1717. NegativeCompareAttributeSet = TRUE;
  1718. } else
  1719. {
  1720. NegativeCompareAttribute = NegativeCompareAttribute | FILE_ATTRIBUTE_HIDDEN;
  1721. }
  1722. } else
  1723. {
  1724. if ( !CompareAttributeSet)
  1725. {
  1726. CompareAttribute = FILE_ATTRIBUTE_HIDDEN;
  1727. CompareAttributeSet = TRUE;
  1728. } else
  1729. {
  1730. CompareAttribute = CompareAttribute | FILE_ATTRIBUTE_HIDDEN;
  1731. }
  1732. }
  1733. NegationFlagSet = FALSE;
  1734. break;
  1735. case 's' :
  1736. if ( NegationFlagSet)
  1737. {
  1738. if ( !NegativeCompareAttributeSet)
  1739. {
  1740. NegativeCompareAttribute = FILE_ATTRIBUTE_SYSTEM;
  1741. NegativeCompareAttributeSet = TRUE;
  1742. } else
  1743. {
  1744. NegativeCompareAttribute = NegativeCompareAttribute | FILE_ATTRIBUTE_SYSTEM;
  1745. }
  1746. } else
  1747. {
  1748. if ( !CompareAttributeSet)
  1749. {
  1750. CompareAttribute = FILE_ATTRIBUTE_SYSTEM;
  1751. CompareAttributeSet = TRUE;
  1752. } else
  1753. {
  1754. CompareAttribute = CompareAttribute | FILE_ATTRIBUTE_SYSTEM;
  1755. }
  1756. }
  1757. NegationFlagSet = FALSE;
  1758. break;
  1759. case '-' :
  1760. NegationFlagSet = TRUE;
  1761. break;
  1762. default :
  1763. fprintf( stderr, "/p option improperly formatted\n");
  1764. Usage();
  1765. }
  1766. }
  1767. if ( !CompareAttributeSet && !NegativeCompareAttributeSet)
  1768. {
  1769. fprintf( stderr, "no compare attributes not set\n");
  1770. Usage();
  1771. }
  1772. fSpecAttribs = TRUE;
  1773. NegationFlagSet = FALSE;
  1774. break;
  1775. case 'r' :
  1776. fDoNotRecurse = !NegationFlagSet;
  1777. NegationFlagSet = FALSE;
  1778. break;
  1779. case 's' :
  1780. fCheckSize = !NegationFlagSet;
  1781. NegationFlagSet = FALSE;
  1782. break;
  1783. case 't' :
  1784. //
  1785. // Get Granularity parameter
  1786. //
  1787. if (
  1788. ( *( TmpArg + 1) == ':')
  1789. &&
  1790. ( *( TmpArg + 2) != '\0')
  1791. )
  1792. {
  1793. sscanf( ( TmpArg + 2), "%d", &Granularity);
  1794. Granularity = Granularity*78125/65536;
  1795. // Conversion to seconds ^^^^^^^
  1796. // 10^7/2^23
  1797. while (isdigit( *( ++TmpArg + 1))) {}
  1798. }
  1799. fCheckTime = !NegationFlagSet;
  1800. NegationFlagSet = FALSE;
  1801. break;
  1802. case 'u' :
  1803. fMultiThread = !NegationFlagSet;
  1804. NegationFlagSet = FALSE;
  1805. break;
  1806. case 'v' :
  1807. fVerbose = !NegationFlagSet;
  1808. NegationFlagSet = FALSE;
  1809. break;
  1810. case 'w' :
  1811. fDontLowerCase = !NegationFlagSet;
  1812. NegationFlagSet = FALSE;
  1813. break;
  1814. case 'x' :
  1815. if ( NegationFlagSet) {
  1816. fprintf ( stderr, "can't use - on /x option\n");
  1817. Usage();
  1818. }
  1819. if (
  1820. ( *( TmpArg + 1) == ':')
  1821. &&
  1822. ( *( TmpArg + 2) != '\0')
  1823. )
  1824. {
  1825. ( ExcludeFile = TmpArg + 2);
  1826. while (isgraph( *( ++TmpArg + 1))) {}
  1827. if ( ( FileHandle = fopen( ExcludeFile, "r")) == NULL)
  1828. {
  1829. fprintf( stderr, "cannot open %s\n", ExcludeFile);
  1830. Usage();
  1831. } else
  1832. {
  1833. while ( fgets( String1 = String, MAX_PATH, FileHandle) != NULL)
  1834. {
  1835. while ( *( String2 = &( String1[ strspn( String1, "\n\r") ])))
  1836. {
  1837. if ( *( String1 = &( String2[ strcspn ( String2, "\n\r") ])))
  1838. {
  1839. *String1++ = 0;
  1840. CreateNameNode( &Node, String2);
  1841. if ( strchr( String2, '*') != NULL)
  1842. {
  1843. AddToList( Node, &EStarList);
  1844. } else
  1845. {
  1846. AddToList( Node, &ExcludeList);
  1847. }
  1848. }
  1849. }
  1850. }
  1851. fclose( FileHandle) ;
  1852. }
  1853. }
  1854. fExclude = TRUE;
  1855. Excludes = TRUE;
  1856. break;
  1857. case 'z' :
  1858. fForce = !NegationFlagSet;
  1859. NegationFlagSet = FALSE;
  1860. break;
  1861. case '$' :
  1862. fTrySis = !NegationFlagSet;
  1863. NegationFlagSet = FALSE;
  1864. break;
  1865. case '/' :
  1866. NegationFlagSet = FALSE;
  1867. break;
  1868. case '-' :
  1869. NegationFlagSet = TRUE;
  1870. break;
  1871. default :
  1872. fprintf( stderr, "Don't know flag(s) %s\n", argv);
  1873. Usage();
  1874. }
  1875. }
  1876. } else
  1877. {
  1878. return FALSE;
  1879. }
  1880. return TRUE;
  1881. } // IsFlag
  1882. BOOL Excluded( char *FileName, char *Path)
  1883. {
  1884. char *PathPlusName;
  1885. PathPlusName = COMBINETHREESTRINGS( Path, "\\", FileName);
  1886. if (
  1887. ( FindInMatchListTop( FileName, &ExcludeList))
  1888. ||
  1889. ( FindInMatchListTop( PathPlusName, &ExcludeList))
  1890. ||
  1891. ( FindInMatchListFront( FileName, &EStarList))
  1892. ||
  1893. ( FindInMatchListFront( PathPlusName, &EStarList))
  1894. )
  1895. {
  1896. FREE( PathPlusName);
  1897. return TRUE;
  1898. } else
  1899. {
  1900. FREE( PathPlusName);
  1901. return FALSE;
  1902. }
  1903. } // Excluded
  1904. BOOL Matched( char *FileName, char *Path)
  1905. {
  1906. char *PathPlusName;
  1907. PathPlusName = COMBINETHREESTRINGS( Path, "\\", FileName);
  1908. if (
  1909. ( FindInMatchListTop( FileName, &MatchList))
  1910. ||
  1911. ( FindInMatchListTop( PathPlusName, &MatchList))
  1912. ||
  1913. ( FindInMatchListFront( FileName, &MStarList))
  1914. ||
  1915. ( FindInMatchListFront( PathPlusName, &MStarList))
  1916. )
  1917. {
  1918. FREE( PathPlusName);
  1919. return TRUE;
  1920. } else
  1921. {
  1922. FREE( PathPlusName);
  1923. return FALSE;
  1924. }
  1925. } // Matched
  1926. BOOL MyCreatePath( char *Path, BOOL IsDirectory)
  1927. {
  1928. char *ShorterPath, *LastSlash;
  1929. ATTRIBUTE_TYPE Attributes;
  1930. IF_GET_ATTR_FAILS( Path, Attributes)
  1931. {
  1932. if ( !IsDirectory || ( ( _mkdir( Path)) != 0) )
  1933. {
  1934. ShorterPath = MYSTRCAT( Path, "");
  1935. LastSlash = strrchr( ShorterPath, '\\');
  1936. if (
  1937. ( LastSlash != NULL)
  1938. &&
  1939. ( LastSlash != strchr( ShorterPath, '\\'))
  1940. )
  1941. {
  1942. *LastSlash = '\0';
  1943. } else
  1944. {
  1945. FREE( ShorterPath);
  1946. return FALSE;
  1947. }
  1948. if ( MyCreatePath( ShorterPath, TRUE))
  1949. {
  1950. FREE( ShorterPath);
  1951. if ( IsDirectory)
  1952. {
  1953. return( ( _mkdir( Path)) == 0);
  1954. } else
  1955. {
  1956. return TRUE;
  1957. }
  1958. } else
  1959. {
  1960. _rmdir( ShorterPath);
  1961. FREE( ShorterPath);
  1962. return FALSE;
  1963. }
  1964. } else
  1965. {
  1966. return TRUE;
  1967. }
  1968. } else
  1969. {
  1970. return TRUE;
  1971. }
  1972. } // MyCreatePath
  1973. BOOL
  1974. MyCopyFile(
  1975. LPCSTR lpExistingFileName,
  1976. LPCSTR lpNewFileName,
  1977. BOOL bFailIfExists
  1978. )
  1979. {
  1980. BOOL ok;
  1981. if (fTrySis) {
  1982. ok = SisCopyFile( lpExistingFileName, lpNewFileName, bFailIfExists, &fTrySis);
  1983. if (ok) {
  1984. return TRUE;
  1985. }
  1986. }
  1987. return CopyFile( lpExistingFileName, lpNewFileName, bFailIfExists);
  1988. }
  1989. int ParseArgsSub( int argc, char *argv[])
  1990. {
  1991. int ArgCount, FlagCount;
  1992. LinkedFileList Node;
  1993. ArgCount = 1;
  1994. FlagCount = 0;
  1995. fMatching = FALSE;
  1996. fExclude = FALSE;
  1997. do
  1998. {
  1999. if ( IsFlag( argv[ArgCount] ))
  2000. {
  2001. FlagCount++;
  2002. } else // ( IsFlag( argv[ArgCount] ))
  2003. {
  2004. if ( ArgCount + 2 < argc)
  2005. {
  2006. if ( fMatching)
  2007. {
  2008. CreateNameNode( &Node, argv[ArgCount]);
  2009. if ( strchr( argv[ArgCount], '*') != NULL)
  2010. {
  2011. AddToList( Node, &MStarList);
  2012. } else
  2013. {
  2014. AddToList( Node, &MatchList);
  2015. }
  2016. }
  2017. if ( fExclude)
  2018. {
  2019. CreateNameNode( &Node, argv[ArgCount]);
  2020. if ( strchr( argv[ArgCount], '*') != NULL)
  2021. {
  2022. AddToList( Node, &EStarList);
  2023. } else
  2024. {
  2025. AddToList( Node, &ExcludeList);
  2026. }
  2027. }
  2028. if ( ( !fMatching) && ( !fExclude))
  2029. {
  2030. fprintf( stderr, "Don't know option %s\n", argv[ArgCount]);
  2031. Usage();
  2032. }
  2033. }
  2034. }
  2035. } while ( ArgCount++ < argc - 1);
  2036. return FlagCount;
  2037. } // ParseArgsSub
  2038. void ParseEnvArgs( void)
  2039. {
  2040. int argc;
  2041. char *argv[128];
  2042. char env[MAX_PATH+2];
  2043. char *p;
  2044. int ArgCount, FlagCount;
  2045. LinkedFileList Node;
  2046. if ( !GetEnvironmentVariable( "COMPDIRCMD", env, MAX_PATH+2)) {
  2047. return;
  2048. }
  2049. argc = 1;
  2050. p = env;
  2051. while ( (*p != 0) && isspace(*p)) {
  2052. p++;
  2053. }
  2054. while ( *p) {
  2055. argv[argc++] = p++;
  2056. while ( (*p != 0) && !isspace(*p)) {
  2057. p++;
  2058. }
  2059. if ( *p != 0) {
  2060. *p++ = 0;
  2061. while ( (*p != 0) && isspace(*p)) {
  2062. p++;
  2063. }
  2064. }
  2065. }
  2066. ParseArgsSub( argc, argv);
  2067. } // ParseEnvArgs
  2068. void ParseArgs( int argc, char *argv[])
  2069. {
  2070. int FlagCount;
  2071. //
  2072. // Check that number of arguments is three or more
  2073. //
  2074. if ( argc < 3)
  2075. {
  2076. fprintf( stderr, "Too few arguments\n");
  2077. Usage();
  2078. }
  2079. FlagCount = ParseArgsSub( argc, argv);
  2080. if ( ( fScript) && ( fVerbose))
  2081. {
  2082. fprintf( stderr, "Cannot do both script and verbose\n");
  2083. Usage();
  2084. }
  2085. if ( ( fVerbose) && ( fExecute))
  2086. {
  2087. fprintf( stderr, "Cannot do both verbose and execute\n");
  2088. Usage();
  2089. }
  2090. if ( ( fScript) && ( fExecute))
  2091. {
  2092. fprintf( stderr, "Cannot do both script and execute\n");
  2093. Usage();
  2094. }
  2095. if ( ( fExclude) && ( fMatching))
  2096. {
  2097. fprintf( stderr, "Cannot do both match and exclude\n");
  2098. Usage();
  2099. }
  2100. if ( ( fCreateNew) && ( !fExecute))
  2101. {
  2102. fprintf( stderr, "Cannot create new without execute\n");
  2103. Usage();
  2104. }
  2105. if ( ( fCreateLink) && ( !fExecute))
  2106. {
  2107. fprintf( stderr, "Cannot do link without execute flag\n");
  2108. Usage();
  2109. }
  2110. if ( ( fForce) && ( !fExecute))
  2111. {
  2112. fprintf( stderr, "Cannot do force without execute flag\n");
  2113. Usage();
  2114. }
  2115. if ( ( fIgnoreRs) && ( !fCheckBits))
  2116. {
  2117. fprintf( stderr, "Cannot ignore rebase info w/o b flag\n");
  2118. Usage();
  2119. }
  2120. if ( ( fBreakLinks) && ( !fExecute))
  2121. {
  2122. fprintf( stderr, "Cannot break links without execute flag\n");
  2123. Usage();
  2124. }
  2125. if ( ( argc - FlagCount) < 3)
  2126. {
  2127. fprintf( stderr, "Too few arguments\n");
  2128. Usage();
  2129. }
  2130. fChecking = fCheckAttribs | fCheckBits | fCheckSize | fCheckTime;
  2131. } // ParseArgs
  2132. void PrintFile( LinkedFileList File, char *Path, char *DiffPath)
  2133. {
  2134. SYSTEMTIME SysTime;
  2135. FILETIME LocalTime;
  2136. if ( File != NULL)
  2137. {
  2138. if ( fVerbose)
  2139. {
  2140. FileTimeToLocalFileTime( &( *File).Time, &LocalTime);
  2141. FileTimeToSystemTime( &LocalTime, &SysTime);
  2142. fprintf ( stdout, "%-4s % 9ld %2d-%02d-%d %2d:%02d.%02d.%03d%c %s\n",
  2143. ( *File).Flag,
  2144. ( *File).SizeLow,
  2145. SysTime.wMonth, SysTime.wDay, SysTime.wYear,
  2146. ( SysTime.wHour > 12 ? ( SysTime.wHour)-12 : SysTime.wHour ),
  2147. SysTime.wMinute,
  2148. SysTime.wSecond,
  2149. SysTime.wMilliseconds,
  2150. ( SysTime.wHour >= 12 ? 'p' : 'a' ),
  2151. Path);
  2152. } else
  2153. {
  2154. fprintf( stdout, "%-4s %s\n", ( *File).Flag, Path);
  2155. }
  2156. PrintFile( ( *File).DiffNode, DiffPath, NULL);
  2157. }
  2158. } // PrintFile
  2159. void ProcessAdd( LinkedFileList List, char *String1, char *String2)
  2160. {
  2161. PCOPY_REQUEST CopyRequest;
  2162. LPSTR NewString1, NewString2;
  2163. if ( fMultiThread)
  2164. {
  2165. NewString1 = _strdup( String1);
  2166. NewString2 = _strdup( String2);
  2167. }
  2168. if ( fScript)
  2169. {
  2170. if ( ( (*List).Attributes & FILE_ATTRIBUTE_DIRECTORY))
  2171. {
  2172. if ( !fOpposite)
  2173. {
  2174. fprintf( stdout, "echo d | xcopy /cehikr \"%s\" \"%s\"\n", String1, String2);
  2175. }
  2176. } else
  2177. {
  2178. fprintf( stdout, "echo f | xcopy /chikr \"%s\" \"%s\"\n", String1, String2);
  2179. }
  2180. }
  2181. else if ( fExecute)
  2182. {
  2183. if ( List->Attributes & FILE_ATTRIBUTE_DIRECTORY)
  2184. {
  2185. if ( ( !fDoNotRecurse) && ( !fOpposite))
  2186. {
  2187. if ( !SparseTree)
  2188. {
  2189. fprintf( stdout, "Making %s\t", String2);
  2190. if ( !MyCreatePath( String2, TRUE))
  2191. {
  2192. fprintf( stderr, "Unable to create path %s\n", String2);
  2193. fprintf( stdout, "\n");
  2194. ExitValue = 1;
  2195. } else
  2196. {
  2197. fprintf( stdout, "[OK]\n");
  2198. CompDir( String1, String2);
  2199. }
  2200. } else
  2201. {
  2202. CompDir( String1, String2);
  2203. }
  2204. }
  2205. } else
  2206. {
  2207. if ( fMultiThread)
  2208. {
  2209. CopyRequest = LocalAlloc( LMEM_ZEROINIT, sizeof( *CopyRequest ));
  2210. if ( CopyRequest == NULL)
  2211. {
  2212. OutOfMem ();
  2213. }
  2214. CopyRequest->WorkItem.Reason = WORK_ITEM;
  2215. CopyRequest->Destination = NewString2;
  2216. CopyRequest->FullPathSrc = NewString1;
  2217. CopyRequest->Attributes = List->Attributes;
  2218. CopyRequest->SizeLow = List->SizeLow;
  2219. QueueWorkItem( CDWorkQueue, &CopyRequest->WorkItem );
  2220. } else
  2221. {
  2222. CopyNode( String2, List, String1);
  2223. }
  2224. }
  2225. } else
  2226. {
  2227. if ( ( !fOpposite) || ( !( (*List).Attributes & FILE_ATTRIBUTE_DIRECTORY)))
  2228. {
  2229. PrintFile( List, String1, NULL);
  2230. }
  2231. }
  2232. } // ProcessAdd
  2233. void ProcessDel( LinkedFileList List, char *String)
  2234. {
  2235. if ( fScript)
  2236. {
  2237. ( ( (*List).Attributes & FILE_ATTRIBUTE_DIRECTORY)) ?
  2238. fprintf( stdout, "echo y | rd /s %s\n", String) :
  2239. fprintf( stdout, "del /f %s\n", String);
  2240. } else if ( fExecute)
  2241. {
  2242. fprintf( stdout, "Removing %s\t", String);
  2243. if ( !DelNode( String))
  2244. {
  2245. fprintf( stderr, "Unable to remove %s\n", String);
  2246. fprintf( stdout, "\n");
  2247. ExitValue = 1;
  2248. } else
  2249. {
  2250. fprintf( stdout, "[OK]\n");
  2251. }
  2252. } else
  2253. {
  2254. PrintFile( List, String, NULL);
  2255. }
  2256. } // ProcessDel
  2257. void ProcessDiff( LinkedFileList List, char *String1, char *String2)
  2258. {
  2259. PCOPY_REQUEST CopyRequest;
  2260. LPSTR NewString1, NewString2;
  2261. if ( fMultiThread)
  2262. {
  2263. NewString1 = _strdup( String1);
  2264. NewString2 = _strdup( String2);
  2265. }
  2266. if ( strchr ( (*List).Flag, '@'))
  2267. {
  2268. if ( fScript)
  2269. {
  2270. if ( ( (*List).Attributes & FILE_ATTRIBUTE_DIRECTORY))
  2271. {
  2272. fprintf( stdout, "echo y | rd /s %s\n", String2);
  2273. } else
  2274. {
  2275. fprintf( stdout, "del /f %s\n", String2);
  2276. }
  2277. }
  2278. if ( fExecute)
  2279. {
  2280. fprintf( stdout, "Removing %s\t", String2);
  2281. if ( !DelNode( String2))
  2282. {
  2283. fprintf( stderr, "Unable to remove %s\n", String2);
  2284. fprintf( stdout, "\n");
  2285. ExitValue = 1;
  2286. } else
  2287. {
  2288. fprintf( stdout, "[OK]\n");
  2289. }
  2290. }
  2291. }
  2292. if ( fScript)
  2293. {
  2294. ( ( (*List).Attributes & FILE_ATTRIBUTE_DIRECTORY)) ?
  2295. fprintf( stdout, "echo d | xcopy /cehikr \"%s\" \"%s\"\n", String1, String2) :
  2296. fprintf( stdout, "echo f | xcopy /chikr \"%s\" \"%s\"\n", String1, String2);
  2297. } else if ( fExecute)
  2298. {
  2299. if ( List->Attributes & FILE_ATTRIBUTE_DIRECTORY)
  2300. {
  2301. CompDir( String1, String2);
  2302. } else
  2303. {
  2304. if ( fMultiThread)
  2305. {
  2306. CopyRequest = LocalAlloc( LMEM_ZEROINIT, sizeof( *CopyRequest ) );
  2307. if ( CopyRequest == NULL)
  2308. {
  2309. OutOfMem ();
  2310. }
  2311. CopyRequest->WorkItem.Reason = WORK_ITEM;
  2312. CopyRequest->Destination = NewString2;
  2313. CopyRequest->FullPathSrc = NewString1;
  2314. CopyRequest->Attributes = List->Attributes;
  2315. CopyRequest->SizeLow = List->SizeLow;
  2316. QueueWorkItem( CDWorkQueue, &CopyRequest->WorkItem );
  2317. } else
  2318. {
  2319. CopyNode( String2, List, String1);
  2320. }
  2321. }
  2322. } else
  2323. {
  2324. PrintFile( List, String1, String2);
  2325. }
  2326. } // ProcessDiff
  2327. void ProcessLists( LinkedFileList AddList, LinkedFileList DelList, LinkedFileList DifList,
  2328. char *Path1, char *Path2 )
  2329. {
  2330. LinkedFileList PlaceKeeper;
  2331. char *String1 = NULL;
  2332. char *String2 = NULL;
  2333. char *PathWithSlash1, *PathWithSlash2;
  2334. ( Path1[strlen( Path1) - 1] == '\\') ? ( PathWithSlash1 = MYSTRCAT( Path1, "")) :
  2335. ( PathWithSlash1 = MYSTRCAT( Path1, "\\"));
  2336. ( Path2[strlen( Path2) - 1] == '\\') ? ( PathWithSlash2 = MYSTRCAT( Path2, "")) :
  2337. ( PathWithSlash2 = MYSTRCAT( Path2, "\\"));
  2338. String1 = LocalAlloc( LMEM_ZEROINIT, MAX_PATH);
  2339. String2 = LocalAlloc( LMEM_ZEROINIT, MAX_PATH);
  2340. if ( String1 == NULL)
  2341. {
  2342. OutOfMem();
  2343. }
  2344. if ( String2 == NULL)
  2345. {
  2346. OutOfMem();
  2347. }
  2348. if ( !fOnlyIfExists)
  2349. {
  2350. if ( AddList != NULL)
  2351. {
  2352. PlaceKeeper = ( *AddList).First;
  2353. } else
  2354. {
  2355. PlaceKeeper = NULL;
  2356. }
  2357. while ( PlaceKeeper != NULL)
  2358. {
  2359. if ( ( *PlaceKeeper).Process)
  2360. {
  2361. if ( ExitValue == 0)
  2362. {
  2363. if ( !fExecute)
  2364. {
  2365. ExitValue = 1;
  2366. }
  2367. }
  2368. _strrev( ( *PlaceKeeper).Name);
  2369. strcat( strcpy( String1, PathWithSlash1), ( *PlaceKeeper).Name);
  2370. strcat( strcpy( String2, PathWithSlash2), ( *PlaceKeeper).Name);
  2371. if ( DealingWithDirectories)
  2372. {
  2373. ProcessAdd( PlaceKeeper, String1, String2);
  2374. } else
  2375. {
  2376. ProcessAdd( PlaceKeeper, Path1, Path2);
  2377. }
  2378. }
  2379. PlaceKeeper = ( *PlaceKeeper).Next;
  2380. }
  2381. }
  2382. if ( ( !fDoNotDelete) && ( !fOnlyIfExists))
  2383. {
  2384. if ( DelList != NULL)
  2385. {
  2386. PlaceKeeper = ( *DelList).First;
  2387. } else
  2388. {
  2389. PlaceKeeper = NULL;
  2390. }
  2391. while ( PlaceKeeper != NULL)
  2392. {
  2393. if ( ( *PlaceKeeper).Process)
  2394. {
  2395. if ( ExitValue == 0)
  2396. {
  2397. if ( !fExecute)
  2398. {
  2399. ExitValue = 1;
  2400. }
  2401. }
  2402. _strrev( ( *PlaceKeeper).Name);
  2403. strcat( strcpy( String2, PathWithSlash2), ( *PlaceKeeper).Name);
  2404. ProcessDel( PlaceKeeper, String2);
  2405. }
  2406. PlaceKeeper = ( *PlaceKeeper).Next;
  2407. }
  2408. }
  2409. if ( DifList != NULL)
  2410. {
  2411. PlaceKeeper = ( *DifList).First;
  2412. } else
  2413. {
  2414. PlaceKeeper = NULL;
  2415. }
  2416. while ( PlaceKeeper != NULL)
  2417. {
  2418. if ( ( *PlaceKeeper).Process)
  2419. {
  2420. if ( ExitValue == 0)
  2421. {
  2422. if ( !fExecute)
  2423. {
  2424. ExitValue = 1;
  2425. }
  2426. }
  2427. _strrev( ( *PlaceKeeper).Name);
  2428. strcat( strcpy( String1, PathWithSlash1), ( *PlaceKeeper).Name);
  2429. strcat( strcpy( String2, PathWithSlash2), ( *PlaceKeeper).Name);
  2430. if ( DealingWithDirectories)
  2431. {
  2432. ProcessDiff( PlaceKeeper, String1, String2);
  2433. } else
  2434. {
  2435. ProcessDiff( PlaceKeeper, Path1, Path2);
  2436. }
  2437. }
  2438. PlaceKeeper = ( *PlaceKeeper).Next;
  2439. }
  2440. LocalFree( String1);
  2441. LocalFree( String2);
  2442. FREE( PathWithSlash1);
  2443. FREE( PathWithSlash2);
  2444. } // ProcessLists
  2445. void Usage( void)
  2446. {
  2447. fputs( "Usage: compdir [/abcdefghiklnoprstuvwz$] [/m {wildcard specs}] [/x {wildcard specs}] Path1 Path2 \n"
  2448. " /a checks for attribute difference \n"
  2449. " /b checks for binary difference \n"
  2450. " /c prints out script to make \n"
  2451. " directory2 look like directory1 \n"
  2452. " /d do not perform or denote deletions \n"
  2453. " /e execution of tree duplication \n"
  2454. " /f only update files that already exist \n"
  2455. " /g ignore slm files, i.e slm.ini, slm.dif\n"
  2456. " /h don't copy attributes \n"
  2457. " /i ignore rebase and resource differences\n"
  2458. " /k break links if copying files (NT only)\n"
  2459. " /l use links instead of copies (NT only)\n"
  2460. " /m[:f] marks start of match list. f is a \n"
  2461. " match file \n"
  2462. " /n create second path if it doesn't exist\n"
  2463. " /o print files that are the same \n"
  2464. " /p{A} only compare files with attribute A \n"
  2465. " where A is any combination of ahsr & -\n"
  2466. " /r do not recurse into subdirectories \n"
  2467. " /s checks for size difference \n"
  2468. " /t[:#] checks for time-date difference; \n"
  2469. " takes margin-of-error parameter \n"
  2470. " in number of seconds. \n"
  2471. " /u uses multiple threads (Win32 only) \n"
  2472. " /v prints verbose output \n"
  2473. " /w preserves case - not just lower case \n"
  2474. " /x[:f] marks start of exclude list. f is an \n"
  2475. " exclude file \n"
  2476. " /z forces copy or link without checking \n"
  2477. " criteria \n"
  2478. " /$ create SIS links if possible \n"
  2479. " /? prints this message \n",
  2480. stderr);
  2481. exit(1);
  2482. } // Usage