Source code of Windows XP (NT5)
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.

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