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.

560 lines
12 KiB

  1. /*
  2. * 10.25.94 Joe Holman TC-like program changed to perform
  3. * logging ERRORs for media.
  4. * 01.17.95 Joe Holman Every file that is copied gets NORMAL attrs.
  5. * 02.01.95 Joe Holman Revamped algorithm and allow empty dirs
  6. * to be copied.
  7. *
  8. */
  9. #include <direct.h>
  10. #include <sys\types.h>
  11. #include <sys\stat.h>
  12. #include <io.h>
  13. #include <conio.h>
  14. #include <errno.h>
  15. #include <string.h>
  16. #include <stdio.h>
  17. #include <process.h>
  18. #include <ctype.h>
  19. #include <windows.h>
  20. #include <time.h>
  21. // Forward Function Declartions...
  22. BOOL CopyNode( char * );
  23. void __cdecl main( int, char ** );
  24. void MyMakeDir ( char * );
  25. void MyCopyFile ( const char * , const char * );
  26. ULONG numFilesCopied=0;
  27. char gSource[MAX_PATH];
  28. char gDest[MAX_PATH];
  29. char realDest[MAX_PATH];
  30. char tempdir[MAX_PATH];
  31. char tempfile[MAX_PATH];
  32. //int drv;
  33. int srclen, dstlen;
  34. FILE * logFile;
  35. void Msg ( const char * szFormat, ... ) {
  36. va_list vaArgs;
  37. va_start ( vaArgs, szFormat );
  38. vprintf ( szFormat, vaArgs );
  39. vfprintf ( logFile, szFormat, vaArgs );
  40. va_end ( vaArgs );
  41. }
  42. void Usage( void ) {
  43. printf ( "Usage: mTC logFile src-tree dst-tree" );
  44. exit (1);
  45. }
  46. char fPathChr ( int c ) {
  47. return (char) ( c == '\\' || c == '/' );
  48. }
  49. void Header(argv)
  50. char* argv[];
  51. {
  52. time_t t;
  53. Msg ("\n=========== MTC =============\n");
  54. Msg ("LogFile : %s\n",argv[1]);
  55. Msg ("Source : %s\n",argv[2]);
  56. Msg ("Destination: %s\n",argv[3]);
  57. time(&t);
  58. Msg ("Time : %s",ctime(&t));
  59. Msg ("================================\n\n");
  60. }
  61. /* ExpandPath - construct a path from the root to the specified file
  62. * correctly handling ., .. and current directory/drive references.
  63. *
  64. * src source path for input
  65. * dst destination buffer
  66. * returns TRUE if error detected
  67. */
  68. ExpandPath (src, dst)
  69. char *src, *dst;
  70. {
  71. LPSTR FilePart;
  72. LPSTR p;
  73. BOOL Ok;
  74. Ok = (!GetFullPathName( (LPSTR) src,
  75. (DWORD) MAX_PATH,
  76. (LPSTR) dst,
  77. &FilePart ));
  78. if ( !Ok ) {
  79. p = src + strlen( src ) - 1;
  80. if ( *p == '.' ) {
  81. if ( p > src ) {
  82. p--;
  83. if ( *p != '.' && *p != ':' && !fPathChr(*p) ) {
  84. strcat( dst, "." );
  85. }
  86. }
  87. }
  88. }
  89. return Ok;
  90. }
  91. BOOL RecurseSrcDir ( const char * gSource, const char * gDest ) {
  92. WIN32_FIND_DATA wfd;
  93. HANDLE fHandle;
  94. BOOL bRC=TRUE;
  95. ULONG gle;
  96. char szSrc[MAX_PATH];
  97. char szDst[MAX_PATH];
  98. char szPath[MAX_PATH];
  99. char szDest[MAX_PATH];
  100. char szFind[MAX_PATH];
  101. char szSrcFile[MAX_PATH];
  102. char szDstFile[MAX_PATH];
  103. // Get rid of any trailing forward slashes.
  104. //
  105. strcpy ( szSrc, gSource );
  106. strcpy ( szDst, gDest );
  107. if ( szSrc[strlen(szSrc)-1] == '\\' ) {
  108. szSrc[strlen(szSrc)-1] = '\0';
  109. }
  110. if ( szDst[strlen(szDst)-1] == '\\' ) {
  111. szDst[strlen(szDst)-1] = '\0';
  112. }
  113. //Msg ( "entered: szSrc = %s, szDst = %s\n", szSrc, szDst );
  114. sprintf ( szFind, "%s\\*.*", szSrc );
  115. fHandle = FindFirstFile ( szFind, &wfd );
  116. if ( fHandle == INVALID_HANDLE_VALUE ) {
  117. // An error occurred finding a directory.
  118. //
  119. Msg ( "ERROR R FindFirstFile FAILED, szFind = %s, GLE = %ld\n",
  120. szFind, GetLastError() );
  121. return (FALSE);
  122. }
  123. else {
  124. // Since this is the first time finding a directory,
  125. // go to the loops code that makes the same directory on the
  126. // destination.
  127. //
  128. goto DIR_LOOP_ENTRY;
  129. }
  130. do {
  131. DIR_CONTINUE:;
  132. bRC = FindNextFile ( fHandle, &wfd );
  133. if ( !bRC ) {
  134. // An error occurred with FindNextFile.
  135. //
  136. gle = GetLastError();
  137. if ( gle == ERROR_NO_MORE_FILES ) {
  138. //Msg ( "ERROR_NO_MORE_FILES...\n" );
  139. FindClose ( fHandle );
  140. return (TRUE);
  141. }
  142. else {
  143. Msg ( "ERROR R FindNextFile FAILED, GLE = %ld\n",
  144. GetLastError() );
  145. FindClose ( fHandle );
  146. exit ( 1 );
  147. }
  148. }
  149. else {
  150. DIR_LOOP_ENTRY:;
  151. // Msg ( "wfd.cFileName = %s\n", wfd.cFileName );
  152. // If not directory, don't just continue.
  153. //
  154. if ( (wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0 ) {
  155. sprintf ( szSrcFile, "%s\\%s", szSrc, wfd.cFileName );
  156. sprintf ( szDstFile, "%s\\%s", szDst, wfd.cFileName );
  157. MyCopyFile ( szSrcFile, szDstFile );
  158. goto DIR_CONTINUE;
  159. }
  160. // Don't do anything with . and .. directory entries.
  161. //
  162. if (!strcmp ( wfd.cFileName, "." ) ||
  163. !strcmp ( wfd.cFileName, "..") ) {
  164. //Msg ( "Don't do anything with . or .. dirs.\n" );
  165. goto DIR_CONTINUE;
  166. }
  167. // Don't do anything with HIDDEN directory entries.
  168. //
  169. if ( wfd.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN ) {
  170. //Msg ( "Don't do anything with HIDDEN dirs.\n" );
  171. goto DIR_CONTINUE;
  172. }
  173. sprintf ( szPath, "%s\\%s", szSrc, wfd.cFileName );
  174. sprintf ( szDest, "%s\\%s", szDst, wfd.cFileName );
  175. //Msg ( "szPath = %s\n", szPath );
  176. //Msg ( "md szDest = %s\n", szDest );
  177. MyMakeDir ( szDest );
  178. // Keep recursing down the directories.
  179. //
  180. RecurseSrcDir ( szPath, szDest );
  181. }
  182. } while ( bRC );
  183. return ( TRUE );
  184. }
  185. BOOL MakeCommandDir ( const char * dest ) {
  186. char szDest[MAX_PATH];
  187. char szLast[MAX_PATH]; // contains last directory made
  188. char * blah;
  189. int i;
  190. strcpy ( szLast, dest );
  191. // Exception case - if the specified directory is just the root, then
  192. // just ignore this code, since the root directory exists by default.
  193. if ( szLast[1] == ':' &&
  194. szLast[2] == '\\' &&
  195. szLast[3] == '\0' ) {
  196. return ( TRUE );
  197. }
  198. // Clean-up any trailing slashes.
  199. //
  200. if ( szLast[strlen(szLast)-1] == '\\' ) {
  201. szLast[strlen(szLast)-1] = '\0';
  202. }
  203. //Msg ( "MakeCommandDir, %s\n", szLast );
  204. // Copy and skip the D:\ chars.
  205. //
  206. szDest[0] = szLast[0];
  207. szDest[1] = szLast[1];
  208. szDest[2] = szLast[2];
  209. blah = szLast;
  210. blah += 3;
  211. i = 3;
  212. while ( 1 ) {
  213. if ( *blah == '\0' ) {
  214. szDest[i] = *blah;
  215. MyMakeDir ( szDest ); // make the directory...
  216. break;
  217. }
  218. else if ( *blah == '\\' ) {
  219. szDest[i] = '\0';
  220. MyMakeDir ( szDest ); // make the directory...
  221. szDest[i] = *blah; // now, since the dir exists, put the slash
  222. // back in.
  223. }
  224. else {
  225. szDest[i] = *blah;
  226. }
  227. ++blah; ++i;
  228. }
  229. return ( TRUE );
  230. }
  231. void __cdecl main ( int argc, char * argv[] ) {
  232. if ( argc != 4) {
  233. Usage();
  234. exit(1);
  235. }
  236. if ((logFile=fopen(argv[1],"a"))==NULL) {
  237. printf("ERROR Couldn't open logFile: %s\n",argv[1]);
  238. exit(1);
  239. }
  240. Header(argv);
  241. Msg ( "%s %s %s %s\n", argv[0], argv[1], argv[2], argv[3] );
  242. if ( ExpandPath (argv[2], gSource) ) {
  243. Msg ( "ERROR Invalid source: %s\n", argv[2] );
  244. exit(1);
  245. }
  246. if ( ExpandPath (argv[3], gDest) ) {
  247. Msg ( "ERROR Invalid destination: %s\n", argv[3] );
  248. exit(1);
  249. }
  250. Msg ( "gSource = %s\n", gSource );
  251. Msg ( "gDest = %s\n", gDest );
  252. srclen = strlen (gSource);
  253. dstlen = strlen (gDest);
  254. if (!strcmp(gSource, gDest)) {
  255. Msg ("ERROR gSource == gDest\n" );
  256. exit(1);
  257. }
  258. // Make any destination directories specified on the command line.
  259. //
  260. MakeCommandDir ( gDest );
  261. // Make the src directory structure on the destination.
  262. //
  263. RecurseSrcDir ( gSource, gDest );
  264. Msg ( "\nnumFilesCopied: %ld\n", numFilesCopied );
  265. exit(0);
  266. }
  267. /***************************************************************************\
  268. MEMBER: strbscan
  269. SYNOPSIS: Returns pointer to first character from string in set
  270. ALGORITHM:
  271. ARGUMENTS: const LPSTR - search string
  272. const LPSTR - set of characters
  273. RETURNS: LPSTR - pointer to first matching character
  274. NOTES:
  275. HISTORY: davegi 28-Jul-90
  276. Rewritten from 286 MASM
  277. KEYWORDS:
  278. SEEALSO:
  279. \***************************************************************************/
  280. #include <assert.h>
  281. #include <process.h>
  282. #include <stdio.h>
  283. #include <string.h>
  284. #include <stdlib.h>
  285. #include <windows.h>
  286. LPSTR
  287. strbscan (
  288. const LPSTR pszStr,
  289. const LPSTR pszSet
  290. ) {
  291. assert( pszStr );
  292. assert( pszSet );
  293. return pszStr + strcspn( pszStr, pszSet );
  294. }
  295. static char szDot[] = ".";
  296. static char szDotDot[] = "..";
  297. static char szColon[] = ":";
  298. static char szPathSep[] = "\\/:";
  299. /** FindFilename - find filename in string
  300. *
  301. * Find last /\:-separated component in string
  302. *
  303. * psz pointer to string to search
  304. *
  305. * returns pointer to filename
  306. */
  307. static char *FindFilename (char *psz)
  308. {
  309. char *p;
  310. while (TRUE) {
  311. p = strbscan (psz, szPathSep);
  312. if (*p == 0) {
  313. return psz;
  314. }
  315. psz = p + 1;
  316. }
  317. }
  318. void MyCopyFile ( const char * src, const char * dst ) {
  319. BOOL fCopy = TRUE;
  320. BOOL bRC;
  321. // Copy the file if the src is newer than the dst.
  322. //
  323. // See if the dst exists first.
  324. //
  325. if (_access (dst, 00) != -1 ) {
  326. struct _stat srcbuf;
  327. struct _stat dstbuf;
  328. int irc;
  329. // The dst exists, see if we need to copy the src (newer).
  330. //
  331. irc = _stat (src, &srcbuf);
  332. if ( irc == -1 ) {
  333. Msg ( "MyCopyFile ERROR stat src FAILed: %s\n", src );
  334. }
  335. irc = _stat (dst, &dstbuf);
  336. if ( irc == -1 ) {
  337. Msg ( "MyCopyFile ERROR stat dst FAILed: %s\n", dst );
  338. }
  339. if ( srcbuf.st_mtime <= dstbuf.st_mtime) {
  340. // The src is NOT newer than the dst, don't copy.
  341. fCopy = FALSE;
  342. }
  343. }
  344. else {
  345. // Dst doesn't exist. Copy the file over.
  346. //
  347. //Msg ( "Dst doesn't exist, so copy over: %s\n", dst );
  348. fCopy = TRUE;
  349. }
  350. if ( fCopy ) {
  351. bRC = CopyFile ( src, dst, FALSE );
  352. if ( !bRC ) {
  353. Msg ( "CopyFile ERROR, gle = %ld: %s >>> %s\n",
  354. GetLastError(), src, dst );
  355. exit ( 1 );
  356. }
  357. else {
  358. BOOL b;
  359. Msg ( "CopyFile: %s >>> %s [OK]\n", src, dst );
  360. b = SetFileAttributes ( dst, FILE_ATTRIBUTE_NORMAL );
  361. if ( !b ) {
  362. Msg ( "ERROR SetFileAttributes: %s, gle() = %ld\n",
  363. dst, GetLastError() );
  364. }
  365. ++numFilesCopied;
  366. }
  367. }
  368. }
  369. void MyMakeDir ( char * szPath ) {
  370. char szDirToMake[MAX_PATH];
  371. int numChars = strlen ( szPath );
  372. struct _stat dbuf;
  373. // szPath is the string of the destination path.
  374. // Currently, this assumes a local drive on the machine.
  375. // We could change the below code to skip the first \\server\share
  376. // names in a UNC specified path, if ever needed.
  377. //
  378. strcpy ( szDirToMake, szPath );
  379. //Msg ( "szDirToMake = %s\n", szDirToMake );
  380. if ( _stat ( szDirToMake, &dbuf) == 0 ) {
  381. if ( dbuf.st_mode & S_IFDIR ) {
  382. // Wanted directory exists already.
  383. //
  384. }
  385. if ( dbuf.st_mode & S_IFREG ) {
  386. // Wanted directory to make already exists as a FILE !
  387. //
  388. Msg ("ERROR MyMakeDir(%s) is a file already.", szDirToMake);
  389. exit ( 1 );
  390. }
  391. }
  392. else {
  393. if ( errno == ENOENT ) {
  394. BOOL b;
  395. b = CreateDirectory ( szDirToMake, NULL );
  396. if ( !b ) {
  397. Msg ("ERROR Unable to CreateDirectory(%s), gle = %ld\n",
  398. szDirToMake, GetLastError() );
  399. exit(1);
  400. }
  401. else {
  402. Msg ( "md %s [OK]\n", szDirToMake );
  403. }
  404. }
  405. else {
  406. Msg ( "MyMakeDir ERROR (%s) stat FAILED...\n", szDirToMake );
  407. exit(1);
  408. }
  409. }
  410. }