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.

443 lines
12 KiB

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