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.

409 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 Header(argv)
  23. char* argv[];
  24. {
  25. time_t t;
  26. PRINT1("\n=========== MAKEDISK =============\n")
  27. PRINT2("Input Layout: %s\n",argv[2])
  28. PRINT2("Source ID: %s\n",argv[3])
  29. PRINT2("Compressed Source Path: %s\n",argv[4])
  30. PRINT2("Uncompressed Source Path: %s\n",argv[5])
  31. PRINT2("Target directory: %s\n",argv[6])
  32. PRINT2("CD Directory: %s\n",argv[7])
  33. PRINT2("Update Only: %s\n",argv[8])
  34. PRINT2("Show Overflows and Undeflows: %s\n",argv[9])
  35. time(&t); PRINT2("Time: %s",ctime(&t))
  36. PRINT1("==================================\n\n");
  37. }
  38. void Usage()
  39. {
  40. printf("PURPOSE: Copy files into disk1, disk2, ... directories.\n");
  41. printf("\n");
  42. printf("PARAMETERS:\n");
  43. printf("\n");
  44. printf("[logFile] - Path to append a log of actions and errors.\n");
  45. printf("[InLayout] - Path of Layout which lists files to copy.\n");
  46. printf("[SourceId] - Specifies the category of files to copy.\n");
  47. printf("[CompressedPath] - Path of compressed files.\n");
  48. printf("[UncompressedPath] - Path of uncompressed files.\n");
  49. printf("[Floppy Dir] - Directory where disk1, disk2, ... dirs should be.\n");
  50. printf("[CD Dir] - Directory where CD files are stored.\n");
  51. printf("[Update Only] - U for update files that have changed. C otherwise.\n");
  52. printf("[Show Overflows/Underflows] - O to show, N to not show, D for dbg-files.\n\n");
  53. }
  54. int __cdecl DiskDirCompare(const void*,const void*);
  55. int __cdecl main(argc,argv)
  56. int argc;
  57. char* argv[];
  58. {
  59. Entry ee;
  60. char sourcePath[MAX_PATH];
  61. char destinPath[MAX_PATH];
  62. int disks[MAX_DISKS];
  63. Entry *e;
  64. char *buf;
  65. int records,i;
  66. BOOL shouldCopy;
  67. BOOL update;
  68. BOOL bCompressedFile;
  69. BOOL bShowOverflows;
  70. BOOL bCopyDbgFiles;
  71. HANDLE hSource,hDestin, hThread;
  72. DWORD actualSize,bomSize, dwThreadID;
  73. WIN32_FIND_DATA fdSource, fdDestin;
  74. if (argc!=10) {Usage(); return (1);}
  75. if ((logFile=fopen(argv[1],"a"))==NULL) {
  76. printf("ERROR Couldn't open log file %s.\n",argv[1]);
  77. return (1);
  78. }
  79. bShowOverflows = (!_stricmp(argv[9],"O"));
  80. bCopyDbgFiles = (!_stricmp(argv[9],"D"));
  81. hActivateCopyThread = CreateEvent( NULL, FALSE, FALSE, NULL );
  82. hCopyThreadIsAvailable = CreateEvent( NULL, FALSE, TRUE, NULL );
  83. hThread = CreateThread( NULL, 0, CopyThread, NULL, 0, &dwThreadID );
  84. CloseHandle( hThread );
  85. Header(argv);
  86. LoadFile(argv[2],&buf,&e,&records,"ALL");
  87. if ((argv[7][strlen(argv[7])-1])=='\\') argv[7][strlen(argv[7])-1]='\0';
  88. if ((argv[6][strlen(argv[6])-1])=='\\') argv[6][strlen(argv[6])-1]='\0';
  89. //
  90. // On the cd all files will be on disk 1. If any files are not
  91. // on disk 1, this must be the floppies.
  92. //
  93. for (cdProduct=1,i=0;i<records;i++)
  94. if (e[i].disk>1) {
  95. cdProduct=0;
  96. break;
  97. }
  98. qsort(e,records,sizeof(ee),DiskDirCompare);
  99. for (i=0;i<MAX_DISKS;i++)
  100. disks[i]=0;
  101. for (i=0;i<records;i++) {
  102. if (e[i].cdpath[strlen(e[i].cdpath)-1]=='\\') e[i].cdpath[strlen(e[i].cdpath)-1]='\0';
  103. if (e[i].path[strlen(e[i].path)-1]=='\\') e[i].path[strlen(e[i].path)-1]='\0';
  104. disks[e[i].disk]++;
  105. }
  106. update = (_stricmp(argv[8],"u")==0);
  107. for (i=0;i<records;i++) {
  108. if (!((records-i)%100))
  109. printf("INFO Files remaining:%5d/%d\n",records-i,records);
  110. ee=e[i];
  111. if (!_stricmp(ee.source,argv[3])) { // if category matches
  112. /***
  113. //
  114. // It's a compressed file IFF platform is x86 AND
  115. // the nocompress flag is NOT set (i.e. null) AND
  116. // we're NOT copying dbg-files.
  117. //
  118. bCompressedFile = (( ! stricmp( ee.platform, "x86" )) &&
  119. ( ! ee.nocompress[ 0 ] ) &&
  120. ( ! bCopyDbgFiles ));
  121. ***/
  122. // It's a compressed file if the nocompress flag is NOT set
  123. // and we're NOT copying dbg-files. That is, we now compress
  124. // for all platforms, even RISC.
  125. //
  126. bCompressedFile = !ee.nocompress[0] && !bCopyDbgFiles;
  127. //printf ( "%s, bCompressedFile = %d\n", ee.name, bCompressedFile );
  128. //
  129. // For floppies, force compression unless nocomp
  130. // has the special value "xfloppy."
  131. //
  132. if (!_stricmp(ee.platform,"x86")
  133. && !cdProduct && !bCompressedFile
  134. && _strnicmp(ee.nocompress,"xfloppy",7)) {
  135. bCompressedFile = TRUE;
  136. }
  137. if ( bCompressedFile ) {
  138. strcpy( sourcePath, argv[ 4 ] ); // use compressed path
  139. bomSize = ee.csize; // and compressed size
  140. } else {
  141. strcpy( sourcePath, argv[ 5 ] ); // uncompressed path
  142. bomSize = ee.size; // uncompressed size
  143. }
  144. strcat(sourcePath,ee.path);
  145. strcat(sourcePath,"\\");
  146. if (bCompressedFile) {
  147. convertName(ee.name,strchr(sourcePath,0));
  148. } else if (bCopyDbgFiles) {
  149. MakeDbgName(ee.name,strchr(sourcePath,0));
  150. } else {
  151. strcat( sourcePath, ee.name );
  152. }
  153. if (cdProduct || !ee.disk) {
  154. //
  155. // File goes on the CD.
  156. //
  157. strcpy(destinPath,argv[7]);
  158. if (!bCopyDbgFiles) {
  159. strcat(destinPath,ee.cdpath);
  160. }
  161. } else {
  162. //
  163. // File goes on a floppy.
  164. //
  165. strcpy(destinPath,argv[6]);
  166. sprintf(&destinPath[strlen(destinPath)],"\\disk%d",ee.disk);
  167. }
  168. strcat(destinPath,"\\");
  169. if (bCopyDbgFiles) {
  170. MakeDbgName(ee.name,strchr(destinPath,0));
  171. } else {
  172. if (ee.medianame[0]) {
  173. if (bCompressedFile) {
  174. convertName(ee.medianame,strchr(destinPath,0));
  175. PRINT2("WARNING: renaming compressed file %s\n",destinPath);
  176. } else {
  177. strcat( destinPath, ee.medianame );
  178. }
  179. } else {
  180. if (bCompressedFile) {
  181. convertName(ee.name,strchr(destinPath,0));
  182. } else {
  183. strcat(destinPath,ee.name);
  184. }
  185. }
  186. }
  187. if (disks[ee.disk] > 1) {
  188. //
  189. // Don't attempt to copy same file twice (target file might
  190. // not yet completely exist since threaded copy might not be
  191. // complete, so can't rely on timestamp equivalence yet).
  192. //
  193. if ( _stricmp( sourcePath, chPreviousSource ) ||
  194. _stricmp( destinPath, chPreviousDestin )) {
  195. hSource=FindFirstFile( sourcePath, &fdSource );
  196. if (hSource==INVALID_HANDLE_VALUE) {
  197. PRINT2("ERROR Source: %s\n",sourcePath)
  198. } else {
  199. FindClose( hSource );
  200. actualSize = ROUNDUP2( fdSource.nFileSizeLow,
  201. ALLOCATION_UNIT );
  202. if ( bShowOverflows ) {
  203. if (bomSize<actualSize)
  204. fprintf(logFile,"ERROR Overflow %d,%s Size: %d BOM: %d Diff: %d\n",ee.disk,ee.name,actualSize,bomSize,actualSize-bomSize);
  205. else if (bomSize>actualSize)
  206. fprintf(logFile,"INFO Underflow %d,%s Size: %d BOM: %d Diff: %d\n",ee.disk,ee.name,actualSize,bomSize,actualSize-bomSize);
  207. }
  208. shouldCopy=TRUE;
  209. if (update) {
  210. hDestin=FindFirstFile( destinPath, &fdDestin );
  211. if (hDestin==INVALID_HANDLE_VALUE) {
  212. PRINT2("New file %s\n", destinPath)
  213. } else {
  214. FindClose( hDestin );
  215. if ( CompareFileTime( &fdSource.ftLastWriteTime,&fdDestin.ftLastWriteTime ) <= 0 ) {
  216. shouldCopy=FALSE;
  217. } else {
  218. PRINT2("Updating %s\n",destinPath)
  219. }
  220. }
  221. }
  222. if (shouldCopy) {
  223. DoThreadedCopy( sourcePath, destinPath );
  224. strcpy( chPreviousSource, sourcePath );
  225. strcpy( chPreviousDestin, destinPath );
  226. }
  227. }
  228. }
  229. } else {
  230. PRINT3("WARNING Skipped Disk %d, File: %s\n",ee.disk,ee.name)
  231. }
  232. }
  233. }
  234. fclose(logFile);
  235. WaitForSingleObject( hCopyThreadIsAvailable, INFINITE );
  236. return 0;
  237. }
  238. int __cdecl DiskDirCompare(const void *v1, const void *v2)
  239. {
  240. Entry *e1 = (Entry *)v1;
  241. Entry *e2 = (Entry *)v2;
  242. //
  243. // If the files are not on the same disk,
  244. // the comparison is easy.
  245. //
  246. if (e1->disk != e2->disk) {
  247. return (e1->disk - e2->disk);
  248. }
  249. //
  250. // If this is a cd-rom, sort by location on the cd.
  251. //
  252. if (cdProduct) {
  253. return (_stricmp(e1->cdpath,e2->cdpath));
  254. }
  255. //
  256. // Floppy product: we know the files are on the same disk
  257. // and files on the floppy are all in the same directory.
  258. //
  259. return (0);
  260. }
  261. void DoThreadedCopy( LPSTR pszSource, LPSTR pszDestin ) {
  262. WaitForSingleObject( hCopyThreadIsAvailable, INFINITE );
  263. strcpy( chCopyThreadSource, pszSource );
  264. strcpy( chCopyThreadDestin, pszDestin );
  265. SetEvent( hActivateCopyThread );
  266. }
  267. #if _MSC_FULL_VER >= 13008827
  268. #pragma warning(push)
  269. #pragma warning(disable:4715) // Not all control paths return (due to infinite loop)
  270. #endif
  271. DWORD CopyThread( LPVOID lpvParam ) {
  272. BOOL bSuccess;
  273. UINT i, len;
  274. for (;;) {
  275. WaitForSingleObject( hActivateCopyThread, INFINITE );
  276. bSuccess = CopyFile( chCopyThreadSource, chCopyThreadDestin, FALSE );
  277. if ( ! bSuccess ) {
  278. SetFileAttributes( chCopyThreadDestin, FILE_ATTRIBUTE_NORMAL );
  279. len = strlen( chCopyThreadDestin );
  280. for ( i = 2; i < len; i++ ) {
  281. if ( chCopyThreadDestin[ i ] == '\\' ) {
  282. chCopyThreadDestin[ i ] = '\0';
  283. CreateDirectory( chCopyThreadDestin, NULL );
  284. chCopyThreadDestin[ i ] = '\\';
  285. }
  286. }
  287. bSuccess = CopyFile( chCopyThreadSource, chCopyThreadDestin, FALSE );
  288. }
  289. if ( ! bSuccess ) {
  290. PRINT4( "ERROR Source: %s\n"
  291. " Destin: %s\n"
  292. " GLE=%d\n",
  293. chCopyThreadSource,
  294. chCopyThreadDestin,
  295. GetLastError() )
  296. }
  297. SetEvent( hCopyThreadIsAvailable );
  298. }
  299. return 0;
  300. }
  301. #if _MSC_FULL_VER >= 13008827
  302. #pragma warning(pop)
  303. #endif
  304. void MakeDbgName( LPCSTR pszSourceName, LPSTR pszTargetName ) {
  305. //
  306. // Converts "filename.ext" into "ext\filename.dbg".
  307. //
  308. const char *p = strchr( pszSourceName, '.' );
  309. if ( p != NULL ) {
  310. strcpy( pszTargetName, p + 1 ); // old extension
  311. strcat( pszTargetName, "\\" ); // path separator
  312. strcat( pszTargetName, pszSourceName ); // base name
  313. strcpy( strchr( pszTargetName, '.' ), ".dbg" ); // new extension
  314. } else
  315. strcpy( pszTargetName, pszSourceName );
  316. }