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.

444 lines
13 KiB

  1. /*
  2. Modifications:
  3. 12.12.95 Joe Holman Added GetLastError() to a FindFirstFile()
  4. error path.
  5. */
  6. #include <stdio.h>
  7. #include <stdlib.h>
  8. #include <string.h>
  9. #include <windows.h>
  10. #include <time.h>
  11. #include "general.h"
  12. #define MAX_DISKS 40
  13. //
  14. // Macro for rounding up any number (x) to multiple of (n) which
  15. // must be a power of 2. For example, ROUNDUP( 2047, 512 ) would
  16. // yield result of 2048.
  17. //
  18. #define ROUNDUP2( x, n ) (((x) + ((n) - 1 )) & ~((n) - 1 ))
  19. FILE* logFile;
  20. int cdProduct;
  21. HANDLE hActivateCopyThread, hCopyThreadIsAvailable;
  22. CHAR chCopyThreadSource[ MAX_PATH ], chCopyThreadDestin[ MAX_PATH ];
  23. CHAR chPreviousSource[ MAX_PATH ], chPreviousDestin[ MAX_PATH ];
  24. void MakeDbgName( LPCSTR pszSourceName, LPSTR pszTargetName );
  25. void DoThreadedCopy( LPSTR pszSource, LPSTR pszDestin );
  26. DWORD CopyThread( LPVOID lpvParam );
  27. void Msg ( const char * szFormat, ... ) {
  28. va_list vaArgs;
  29. va_start ( vaArgs, szFormat );
  30. vprintf ( szFormat, vaArgs );
  31. vfprintf ( logFile, szFormat, vaArgs );
  32. va_end ( vaArgs );
  33. }
  34. void Header(argv)
  35. char* argv[];
  36. {
  37. time_t t;
  38. Msg ("\n=========== MCPYFILE =============\n");
  39. Msg ("logfile : %s\n", argv[1] );
  40. Msg ("Input Layout: %s\n",argv[2]);
  41. Msg ("category : %s\n",argv[3]);
  42. Msg ("Compressed files: %s\n", argv[4]);
  43. Msg ("Uncompressed files : %s\n", argv[5]);
  44. Msg ("Hard drive: %s\n",argv[6]);
  45. Msg ("Copy d-DBG, x-FLOPPY, c-CDROM files: %s\n", argv[7] );
  46. time(&t);
  47. Msg ("Time: %s",ctime(&t));
  48. Msg ("==================================\n\n");
  49. }
  50. void Usage()
  51. {
  52. printf("PURPOSE: Copy files to hardrive or into disk1, disk2, ... dirs.\n");
  53. printf("\n");
  54. printf("PARAMETERS:\n");
  55. printf("\n");
  56. printf("[logFile] - Path to append a log of actions and errors.\n");
  57. printf("[InLayout] - Path of Layout which lists files to copy.\n");
  58. printf("[Category] - Specifies the category of files to copy.\n");
  59. printf("[files share] - location of Compressed files.\n" );
  60. printf("[files share] - location of Uncompressed files\n" );
  61. printf("[Harddrive] - Drive where files are stored.\n");
  62. printf("[copy dbg,floppy,or cd files] - use D for .dbg files or x for floppy files\n" );
  63. }
  64. int __cdecl DiskDirCompare(const void*,const void*);
  65. int __cdecl main(argc,argv)
  66. int argc;
  67. char* argv[];
  68. {
  69. Entry ee;
  70. char sourcePath[MAX_PATH];
  71. char destinPath[MAX_PATH];
  72. int disks[MAX_DISKS];
  73. Entry *e;
  74. char *buf;
  75. int records,i;
  76. BOOL shouldCopy;
  77. BOOL update;
  78. BOOL bCompressedFile;
  79. BOOL bCopyDbgFiles;
  80. HANDLE hSource,hDestin, hThread;
  81. DWORD actualSize,bomSize, dwThreadID;
  82. WIN32_FIND_DATA fdSource, fdDestin;
  83. if ( argc != 8 ) {
  84. Usage();
  85. return (1);
  86. }
  87. if ((logFile=fopen(argv[1],"a"))==NULL) {
  88. printf("ERROR Couldn't open log file %s.\n",argv[1]);
  89. return (1);
  90. }
  91. hActivateCopyThread = CreateEvent( NULL, FALSE, FALSE, NULL );
  92. hCopyThreadIsAvailable = CreateEvent( NULL, FALSE, TRUE, NULL );
  93. hThread = CreateThread( NULL, 0, CopyThread, NULL, 0, &dwThreadID );
  94. CloseHandle( hThread );
  95. Header(argv);
  96. // Load all of the current entries in the layout file
  97. // provided to the program.
  98. //
  99. LoadFile(argv[2],&buf,&e,&records,"ALL");
  100. cdProduct = TRUE;
  101. bCopyDbgFiles = FALSE;
  102. update = TRUE;
  103. if ( !_stricmp ( "ntflop", argv[3] ) || !_stricmp ( "lmflop", argv[3] ) ||
  104. _stricmp ( argv[7], "x" ) == 0 ) {
  105. cdProduct = FALSE;
  106. bCopyDbgFiles = FALSE;
  107. Msg ( "Making X86 Floppies...\n" );
  108. } else {
  109. Msg ( "Making CDs...\n" );
  110. bCopyDbgFiles = !_stricmp( argv[7], "d" );
  111. }
  112. Msg ( "bCopyDbgFiles = %d\n", bCopyDbgFiles );
  113. //qsort(e,records,sizeof(ee),DiskDirCompare);
  114. for (i=0;i<MAX_DISKS;i++) {
  115. disks[i]=0;
  116. }
  117. for (i=0;i<records;i++) {
  118. if (e[i].cdpath[strlen(e[i].cdpath)-1]=='\\') {
  119. e[i].cdpath[strlen(e[i].cdpath)-1]='\0';
  120. }
  121. if (e[i].path[strlen(e[i].path)-1]=='\\') {
  122. e[i].path[strlen(e[i].path)-1]='\0';
  123. }
  124. disks[e[i].disk]++;
  125. }
  126. for (i=0;i<records;i++) {
  127. if (!((records-i)%100)) {
  128. printf("# files remaining:%5d/%d\n",records-i,records);
  129. }
  130. ee=e[i];
  131. if (!_stricmp(ee.source,argv[3])) { // if category matches
  132. if ( cdProduct ) {
  133. // Making CD.
  134. //
  135. //
  136. // It's a compressed file IFF
  137. // the nocompress flag is NOT set (i.e. null) AND
  138. // we're NOT copying dbg-files.
  139. //
  140. bCompressedFile = !ee.nocompress[0] && !bCopyDbgFiles;
  141. } else {
  142. // Making x86 floppies.
  143. //
  144. // NOTE: in Layout.C, we go back to the convention of:
  145. //
  146. // "" == yes, compress this file
  147. // "x" == no don't compress this file
  148. //
  149. bCompressedFile = _stricmp(ee.nocompress, "x" );
  150. //Msg ( "%s, bCompressedFile = %d\n", ee.name, bCompressedFile );
  151. }
  152. //Msg ( "bCompressedFile = %d, %s\n", bCompressedFile, ee.name );
  153. if ( bCompressedFile ) {
  154. strcpy( sourcePath, argv[ 4 ] ); // use compressed path
  155. bomSize = ee.csize; // and compressed size
  156. } else {
  157. strcpy( sourcePath, argv[ 5 ] ); // uncompressed path
  158. bomSize = ee.size; // uncompressed size
  159. }
  160. strcat(sourcePath,ee.path);
  161. strcat(sourcePath,"\\");
  162. if ( bCompressedFile ) {
  163. convertName( ee.name, strchr( sourcePath, 0 ));
  164. } else if ( bCopyDbgFiles ) {
  165. MakeDbgName( ee.name, strchr( sourcePath, 0 ));
  166. } else {
  167. strcat( sourcePath, ee.name );
  168. }
  169. // May have to massage disk1...disk tagfiles...
  170. if ( cdProduct ) {
  171. strcpy(destinPath,argv[6]);
  172. if ( ! bCopyDbgFiles ) {
  173. strcat(destinPath,ee.cdpath);
  174. }
  175. } else {
  176. strcpy(destinPath,argv[6]);
  177. sprintf(&destinPath[strlen(destinPath)],"\\disk%d",ee.disk);
  178. }
  179. strcat(destinPath,"\\");
  180. if ( bCopyDbgFiles ) {
  181. MakeDbgName( ee.name, strchr( destinPath, 0 ));
  182. } else {
  183. if (ee.medianame[0]) {
  184. if ( bCompressedFile ) {
  185. convertName( ee.medianame, strchr( destinPath, 0 ));
  186. // For simplification in the BOM, we no longer
  187. // rename compressed files. I.E, any file that has
  188. // to be renamed, CANNOT be compressed.
  189. //
  190. Msg ( "ERROR: renaming compressed file not supported: %s\n",
  191. destinPath );
  192. } else {
  193. strcat( destinPath, ee.medianame );
  194. }
  195. } else {
  196. if ( bCompressedFile ) {
  197. convertName( ee.name, strchr( destinPath, 0 ));
  198. } else {
  199. strcat( destinPath, ee.name );
  200. }
  201. }
  202. }
  203. if (disks[ee.disk]>1) {
  204. //
  205. // Don't attempt to copy same file twice (target file might
  206. // not yet completely exist since threaded copy might not be
  207. // complete, so can't rely on timestamp equivalence yet).
  208. //
  209. if ( _stricmp( sourcePath, chPreviousSource ) ||
  210. _stricmp( destinPath, chPreviousDestin )) {
  211. hSource=FindFirstFile( sourcePath, &fdSource );
  212. if (hSource==INVALID_HANDLE_VALUE) {
  213. Msg ("ERROR Source: %s, gle()=%d\n",sourcePath, GetLastError());
  214. } else {
  215. FindClose( hSource );
  216. if ( !cdProduct ) {
  217. actualSize = ROUNDUP2( fdSource.nFileSizeLow,
  218. DMF_ALLOCATION_UNIT );
  219. } else {
  220. actualSize = ROUNDUP2( fdSource.nFileSizeLow,
  221. ALLOCATION_UNIT );
  222. }
  223. // Check the size of the file vs. the size in the
  224. // bom just for a verification of file sizes.
  225. // Don't do this for Dbg files, since these sizes are
  226. // never put in the layout.
  227. //
  228. if ( !bCopyDbgFiles && (bomSize < actualSize) ) {
  229. Msg ( "ERROR: disk#%d, %s Size of file: %d > BOM: %d Diff: %d\n",
  230. ee.disk,ee.name,
  231. actualSize,bomSize,actualSize-bomSize);
  232. }
  233. shouldCopy=TRUE;
  234. if (update) {
  235. hDestin=FindFirstFile( destinPath, &fdDestin );
  236. if (hDestin==INVALID_HANDLE_VALUE) {
  237. // Msg ("New file %s\n", destinPath);
  238. } else {
  239. FindClose( hDestin );
  240. if ( CompareFileTime( &fdSource.ftLastWriteTime,
  241. &fdDestin.ftLastWriteTime ) <= 0 ) {
  242. shouldCopy=FALSE;
  243. } else {
  244. //Msg ("Updating %s\n",destinPath);
  245. }
  246. }
  247. }
  248. if (shouldCopy) {
  249. Msg ( "Copy: %s >>> %s\n", sourcePath, destinPath);
  250. DoThreadedCopy( sourcePath, destinPath );
  251. strcpy( chPreviousSource, sourcePath );
  252. strcpy( chPreviousDestin, destinPath );
  253. }
  254. }
  255. }
  256. } else {
  257. Msg ("WARNING Skipped Disk %d, File: %s\n",ee.disk,ee.name);
  258. }
  259. }
  260. }
  261. fclose(logFile);
  262. WaitForSingleObject( hCopyThreadIsAvailable, INFINITE );
  263. return 0;
  264. }
  265. int __cdecl DiskDirCompare(const void *v1, const void *v2)
  266. {
  267. Entry *e1 = (Entry *)v1;
  268. Entry *e2 = (Entry *)v2;
  269. //
  270. // If the files are not on the same disk,
  271. // the comparison is easy.
  272. //
  273. if (e1->disk != e2->disk) {
  274. return (e1->disk - e2->disk);
  275. }
  276. //
  277. // If this is a cd-rom, sort by location on the cd.
  278. //
  279. if (cdProduct) {
  280. return (_stricmp(e1->cdpath,e2->cdpath));
  281. }
  282. //
  283. // Floppy product: we know the files are on the same disk
  284. // and files on the floppy are all in the same directory.
  285. //
  286. return (0);
  287. }
  288. void DoThreadedCopy( LPSTR pszSource, LPSTR pszDestin ) {
  289. WaitForSingleObject( hCopyThreadIsAvailable, INFINITE );
  290. strcpy( chCopyThreadSource, pszSource );
  291. strcpy( chCopyThreadDestin, pszDestin );
  292. SetEvent( hActivateCopyThread );
  293. }
  294. #if _MSC_FULL_VER >= 13008827
  295. #pragma warning(push)
  296. #pragma warning(disable:4715) // Not all control paths return (due to infinite loop)
  297. #endif
  298. DWORD CopyThread( LPVOID lpvParam ) {
  299. BOOL bSuccess;
  300. UINT i, len;
  301. for (;;) {
  302. WaitForSingleObject( hActivateCopyThread, INFINITE );
  303. bSuccess = CopyFile( chCopyThreadSource, chCopyThreadDestin, FALSE );
  304. if ( ! bSuccess ) {
  305. SetFileAttributes( chCopyThreadDestin, FILE_ATTRIBUTE_NORMAL );
  306. len = strlen( chCopyThreadDestin );
  307. for ( i = 2; i < len; i++ ) {
  308. if ( chCopyThreadDestin[ i ] == '\\' ) {
  309. chCopyThreadDestin[ i ] = '\0';
  310. CreateDirectory( chCopyThreadDestin, NULL );
  311. chCopyThreadDestin[ i ] = '\\';
  312. }
  313. }
  314. bSuccess = CopyFile( chCopyThreadSource, chCopyThreadDestin, FALSE );
  315. }
  316. if ( ! bSuccess ) {
  317. Msg ( "ERROR Source: %s\n"
  318. " Destin: %s\n"
  319. " GLE=%d\n",
  320. chCopyThreadSource,
  321. chCopyThreadDestin,
  322. GetLastError() );
  323. }
  324. SetEvent( hCopyThreadIsAvailable );
  325. }
  326. return 0;
  327. }
  328. #if _MSC_FULL_VER >= 13008827
  329. #pragma warning(pop)
  330. #endif
  331. void MakeDbgName( LPCSTR pszSourceName, LPSTR pszTargetName ) {
  332. //
  333. // Converts "filename.ext" into "ext\filename.dbg".
  334. //
  335. const char *p = strchr( pszSourceName, '.' );
  336. if ( p != NULL ) {
  337. strcpy( pszTargetName, p + 1 ); // old extension
  338. strcat( pszTargetName, "\\" ); // path separator
  339. strcat( pszTargetName, pszSourceName ); // base name
  340. strcpy( strchr( pszTargetName, '.' ), ".dbg" ); // new extension
  341. } else {
  342. strcpy( pszTargetName, pszSourceName );
  343. }
  344. }