Windows NT 4.0 source code leak
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.

565 lines
16 KiB

4 years ago
  1. /*
  2. * UPD: update
  3. *
  4. * HISTORY:
  5. *
  6. * 4/13/86 danl Fix /d bug. Print warning on eq time ne length
  7. * 4/11/86 danl Remove test for length just before copyfile
  8. * 4/09/86 danl Converted to ztools\lib
  9. * 5/07/86 danl Add msg if no such source found
  10. * 5/29/86 danl Add /s flag
  11. * 6/02/86 danl Add /g flag
  12. * 6/04/86 danl Allow %n with /g flag
  13. * 6/10/86 danl Allow blank lines in /g file, # are not echo'd
  14. * 6/12/86 danl Output \n and ends of lines
  15. * 6/26/86 danl Convert from fatal to usage
  16. * 7/01/86 danl Add /a flag
  17. * 12/04/86 danl Add /p flag
  18. * 12/24/86 danl Use malloc for pPat
  19. * 2/24/87 brianwi Use findclose()
  20. * 2/25/87 brianwi Add 'echo' and 'rem' to /g files
  21. * 07-Apr-87 danl Add fAnyUpd
  22. * 13-Apr-87 brianwi Issue error message if source dir invalid
  23. * 07-May-87 danl Add /e switch
  24. * 22-May-87 brianwi Fix descent from root directory bug
  25. * 20-Aug-87 brianwi Fix Null Pointer with /o ( free(pPat) in walk() )
  26. */
  27. #include <malloc.h>
  28. #include <math.h>
  29. #include <ctype.h>
  30. #include <fcntl.h>
  31. #include <sys\types.h>
  32. #include <sys\stat.h>
  33. #include <io.h>
  34. #include <string.h>
  35. #include <stdio.h>
  36. #include <process.h>
  37. #include <ctype.h>
  38. #include <math.h>
  39. #include <stdlib.h>
  40. #include <windows.h>
  41. #include <tools.h>
  42. // Forward Function Declarations...
  43. int _CRTAPI1 main( int, char ** );
  44. int savespec( char * );
  45. int copyfile( char *, struct findType *, char * );
  46. void walk( char *, struct findType *, void *);
  47. void RecWalk( char *, struct findType *, void * );
  48. void saveext( char * );
  49. void usage( char *, ... );
  50. void getfile( int, char ** );
  51. char *rgstrUsage[] = {
  52. "Usage: UPD [/nxdfvosape] {src directories}+ dest directory [{wildcard specs}*]",
  53. " UPD /g file",
  54. " Options:",
  55. " -n No saving of replaced files to deleted directory",
  56. " -x eXclude files, see tools.ini",
  57. " -d Descend into subdirectories",
  58. " -f Files differ, then update",
  59. " -v Verbose",
  60. " -o Only files already existing in dest are updated",
  61. " -s Subdirectory DEBUG has priority",
  62. " -a Archive bit on source should NOT be reset",
  63. " -p Print actions, but do nothing",
  64. " -e Exit codes 1-error or no src else 0",
  65. " Default is 1-update done 0-no updates done",
  66. " -g Get params from file",
  67. 0};
  68. #define BUFLEN 256
  69. #define MAXSPEC 32
  70. #define MAXFIL 256
  71. #define MAXARGV 20
  72. char *exclude[MAXFIL], dir[BUFLEN];
  73. unsigned _stack = 4096;
  74. flagType fInGetfile = FALSE;
  75. flagType _fExpand = FALSE;
  76. flagType fDescend = FALSE;
  77. flagType fAll = FALSE;
  78. flagType fExclude = FALSE;
  79. flagType fDel = TRUE;
  80. flagType fVerbose = FALSE;
  81. flagType fOnly = FALSE;
  82. flagType fSubDebug = FALSE; /* TRUE => priority to subdir DEBUG */
  83. flagType fArchiveReset = TRUE;
  84. flagType fPrintOnly = FALSE;
  85. flagType fErrorExit = FALSE; /* TRUE => exit (1) errors or no src else 0 */
  86. flagType fNoSrc = FALSE; /* TRUE => "No src msg emitted" */
  87. int numexcl = 0;
  88. int cCopied = 0;
  89. int fAnyUpd = 0;
  90. int nWildSpecs = 0;
  91. char *wildSpecs[MAXSPEC];
  92. struct findType buf;
  93. char source[BUFLEN], dest[BUFLEN], srcDebug[BUFLEN];
  94. /* for use by getfile */
  95. char *argv[MAXARGV];
  96. char bufIn[BUFLEN];
  97. char strLine[BUFLEN];
  98. char ekoLine[BUFLEN]; /* undestroyed copy of line for echo */
  99. savespec (p)
  100. char *p;
  101. {
  102. char namebuf[ 16 ];
  103. int i;
  104. buf.fbuf.dwFileAttributes = 0;
  105. namebuf[ 0 ] = 0;
  106. if (strchr(p, '\\') || strchr(p, ':' ) )
  107. return FALSE;
  108. ffirst( p, FILE_ATTRIBUTE_DIRECTORY, &buf );
  109. findclose( &buf );
  110. if ( /* !HASATTR( buf.attr, FILE_ATTRIBUTE_DIRECTORY ) && */
  111. filename( p, namebuf )
  112. ) {
  113. fileext( p, namebuf);
  114. upper( namebuf );
  115. for (i=0; i<nWildSpecs; i++)
  116. if (!strcmp( namebuf, wildSpecs[ i ]))
  117. return TRUE;
  118. if (nWildSpecs < MAXSPEC) {
  119. wildSpecs[ nWildSpecs++ ] = _strdup (namebuf);
  120. return TRUE;
  121. }
  122. else
  123. usage( "Too many wild card specifications - ", namebuf, 0 );
  124. }
  125. else
  126. return FALSE;
  127. }
  128. copyfile( src, srctype, dst )
  129. char *src, *dst;
  130. struct findType *srctype;
  131. {
  132. int i;
  133. char *result, temp[ 20 ]; /* temp for storing file names */
  134. flagType fNewfile = FALSE;
  135. if ( fExclude ) {
  136. fileext( src, temp );
  137. for (i = 0; i< numexcl; i++) {
  138. if( !_strcmpi( exclude[i], temp ) ) {
  139. return( FALSE );
  140. }
  141. }
  142. }
  143. fflush( stdout );
  144. /* if the file already exists, fdelete will return 0; then don't */
  145. /* notify the user that a file transfer has taken place. Otherwise */
  146. /* a new file has been created so tell the user about it. */
  147. printf( " %s => %s", src, dst );
  148. fAnyUpd = 1;
  149. if ( !fPrintOnly ) {
  150. if (fDel) fNewfile = (flagType)((fdelete(dst)) ? TRUE : FALSE );
  151. if (!(result = fcopy( src, dst ))) {
  152. if (fArchiveReset)
  153. SetFileAttributes( src, srctype->fbuf.dwFileAttributes & ~FILE_ATTRIBUTE_ARCHIVE );
  154. if (fVerbose || fNewfile) printf( " [OK]" );
  155. }
  156. else
  157. printf( " %s - %s", result, error() );
  158. }
  159. else
  160. printf ( " [no upd]" );
  161. printf( "\n" );
  162. fflush( stdout );
  163. }
  164. void
  165. walk (
  166. char *p,
  167. struct findType *b,
  168. void *dummy
  169. )
  170. {
  171. int fNotFound;
  172. char *pPat;
  173. char *pT = p;
  174. struct findType *bT = b;
  175. struct findType bufT;
  176. if( strcmp( bT->fbuf.cFileName, "." ) &&
  177. strcmp( bT->fbuf.cFileName, ".." )
  178. ) {
  179. if (HASATTR (bT->fbuf.dwFileAttributes, FILE_ATTRIBUTE_DIRECTORY)) {
  180. /* do nothing if you find a dir */
  181. } else if( !HASATTR( bT->fbuf.dwFileAttributes, FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM ) ) {
  182. //
  183. // Note: windows does not support FILE_ATTRIBUTE_VOLUME_LABEL, so
  184. // it was removed from above
  185. //
  186. pPat = malloc ( BUFLEN );
  187. strcpy( pPat, dest );
  188. if (*(strend( pPat ) - 1) != '\\') {
  189. strcat( pPat, "\\" );
  190. }
  191. fileext( pT, strend ( pPat ) );
  192. /* ffirst == 0 => file found */
  193. if (fOnly && ffirst( pPat, -1, &buf ) ) {
  194. free ( pPat );
  195. return;
  196. }
  197. if (fOnly) {
  198. findclose( &buf );
  199. }
  200. /* so far we know src\file and dest\file exist */
  201. if (fSubDebug) {
  202. /* now check to see if src\DEBUG\file exists */
  203. drive(pT, srcDebug);
  204. path(pT, srcDebug + strlen(srcDebug));
  205. strcat(srcDebug + strlen(srcDebug), "debug\\");
  206. fileext(pT, srcDebug + strlen(srcDebug));
  207. if( !ffirst( srcDebug, -1, &bufT ) ) {
  208. findclose( &bufT );
  209. /* it exists so use it for the compares below */
  210. pT = srcDebug;
  211. bT = &bufT;
  212. }
  213. }
  214. cCopied++;
  215. if( ( fNotFound = ffirst( pPat, -1, &buf ) ) ||
  216. ( CompareFileTime( &buf.fbuf.ftLastWriteTime, &bT->fbuf.ftLastWriteTime ) < 0 ) ||
  217. ( fAll &&
  218. CompareFileTime( &buf.fbuf.ftLastWriteTime, &bT->fbuf.ftLastWriteTime ) > 0
  219. )
  220. ) {
  221. copyfile( pT, bT, pPat );
  222. } else if( !fNotFound &&
  223. CompareFileTime( &buf.fbuf.ftLastWriteTime, &bT->fbuf.ftLastWriteTime ) == 0 &&
  224. buf.fbuf.nFileSizeLow != bT->fbuf.nFileSizeLow
  225. ) {
  226. printf("\n\007UPD: warning - %s not copied\n", pT);
  227. printf("\007UPD: warning - same time, different length in src & dest\n", pT);
  228. }
  229. findclose( &buf );
  230. free ( pPat );
  231. }
  232. }
  233. dummy;
  234. }
  235. /* a first walking routine, just copies the files on given directory */
  236. /* doesn't deal with nested subdirectories. Ie split the process up into */
  237. /* two parts, first deal with files on current directory, then deal with */
  238. /* subdirectories as necessary. */
  239. /* only called when fDescend is true */
  240. void
  241. RecWalk (
  242. char *p,
  243. struct findType *b,
  244. void *dummy
  245. )
  246. {
  247. char *pPat;
  248. char *pDestEnd;
  249. int i;
  250. if (strcmp (b->fbuf.cFileName, ".") && strcmp (b->fbuf.cFileName, ".."))
  251. if (HASATTR (b->fbuf.dwFileAttributes, FILE_ATTRIBUTE_DIRECTORY) && !HASATTR (b->fbuf.dwFileAttributes, FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) {
  252. /* ignore Hidden and System directories */
  253. pPat = malloc ( BUFLEN );
  254. if ( (pDestEnd = strend(dest))[-1] != '\\' )
  255. strcat(pDestEnd, "\\");
  256. fileext(p, strend(pDestEnd));
  257. sprintf( pPat, "%s\\*.*", p);
  258. forfile( pPat, FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM, RecWalk, NULL );
  259. for (i=0; i<nWildSpecs; i++) {
  260. sprintf( pPat, "%s\\%s", p, wildSpecs[ i ] );
  261. forfile( pPat, FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM, walk, NULL );
  262. }
  263. *pDestEnd = '\0';
  264. free ( pPat );
  265. }
  266. dummy;
  267. }
  268. void
  269. saveext (p)
  270. char *p;
  271. {
  272. upper (p) ;
  273. if (numexcl < MAXFIL)
  274. exclude [numexcl++] = _strdup (p);
  275. }
  276. void usage( char *p, ... )
  277. {
  278. char **rgstr;
  279. rgstr = &p;
  280. if (*rgstr) {
  281. fprintf (stderr, "UPD: ");
  282. while (*rgstr)
  283. fprintf (stderr, "%s", *rgstr++);
  284. fprintf (stderr, "\n");
  285. }
  286. rgstr = rgstrUsage;
  287. while (*rgstr)
  288. fprintf (stderr, "%s\n", *rgstr++);
  289. exit ((fErrorExit ? 1 : 0));
  290. }
  291. /* call if UPD /g getfile, reads lines from getfile and for each line
  292. calls main */
  293. void getfile(c, v)
  294. int c;
  295. char *v[];
  296. {
  297. FILE *fp;
  298. int cargv = 0;
  299. int i, j;
  300. char *p;
  301. ConvertAppToOem( c, v );
  302. if( c == 0 ) {
  303. usage("no getfile specified", 0);
  304. }
  305. fInGetfile = TRUE;
  306. if( ( fp = fopen( *v, "r" ) ) == (FILE *)NULL ) {
  307. usage("error opening ", *v, 0);
  308. }
  309. SHIFT(c, v);
  310. /*
  311. * 13-SEPT-90 w-barry
  312. * Changed open to fopen and switched to fgets instead of assembly
  313. * routines 'getl' and 'getlinit'.
  314. *
  315. * getlinit((char far *)bufIn, BUFLEN, fh);
  316. * while (getl(strLine, BUFLEN) != NULL) {
  317. */
  318. while( fgets( strLine, BUFLEN, fp ) != NULL ) {
  319. if( *strLine == '#' )
  320. continue;
  321. if( *strLine == ';') {
  322. printf( "%s\n", strLine );
  323. continue;
  324. }
  325. /* fgets doesn't strip the trailing \n */
  326. *strbscan(strLine, "\n") = '\0';
  327. cargv = 0;
  328. /* convert strLine into argv */
  329. p = strbskip(strLine, " ");
  330. strcpy (ekoLine, p + 5);
  331. while (*p) {
  332. argv[cargv++] = p;
  333. p = strbscan(p, " ");
  334. if (*p)
  335. *p++ = '\0';
  336. p = strbskip(p, " ");
  337. }
  338. if (!_stricmp (argv[0], "rem")) continue;
  339. if (!_stricmp (argv[0], "echo"))
  340. {
  341. if (!_stricmp (argv[1], "on" ))
  342. {
  343. fVerbose = TRUE;
  344. printf ("Verbose On\n");
  345. }
  346. else if (!_stricmp (argv[1], "off"))
  347. {
  348. fVerbose = FALSE;
  349. printf ("Verbose Off\n");
  350. }
  351. else printf ("%s\n", ekoLine);
  352. continue;
  353. }
  354. for (i = 0; i < cargv; i++) {
  355. if (*(p = argv[i]) == '%') {
  356. if ((j = atoi(++p)) < c)
  357. argv[i] = v[j];
  358. else
  359. usage("bad arg ", argv[i], 0);
  360. }
  361. }
  362. if (cargv)
  363. main(cargv, argv);
  364. }
  365. fclose( fp );
  366. exit( (int)fErrorExit ? (int)fNoSrc : fAnyUpd );
  367. }
  368. _CRTAPI1
  369. main (c, v)
  370. int c;
  371. char *v[];
  372. {
  373. int i, j, k;
  374. FILE *fh;
  375. char *p, *p1, namebuf[ BUFLEN ];
  376. _fExpand = FALSE;
  377. fDescend = FALSE;
  378. fAll = FALSE;
  379. fExclude = FALSE;
  380. fDel = TRUE;
  381. fOnly = FALSE;
  382. fSubDebug = FALSE;
  383. fArchiveReset = TRUE;
  384. fPrintOnly = FALSE;
  385. numexcl = 0;
  386. cCopied = 0;
  387. nWildSpecs = 0;
  388. if (!fInGetfile)
  389. SHIFT(c, v); /* Flush the command name */
  390. /*
  391. * 13-SEPT-90 w-barry
  392. * Added test for arguments remaining before test for switch char.
  393. */
  394. while( c && fSwitChr ( *v[ 0 ] ) ) {
  395. p = v[ 0 ];
  396. SHIFT(c, v);
  397. while (*++p)
  398. switch (tolower(*p)) {
  399. case 'a':
  400. fArchiveReset = FALSE;
  401. break;
  402. case 'g':
  403. if (fInGetfile)
  404. usage( "/g allowed only on command line", 0);
  405. getfile(c, v);
  406. break;
  407. case 'e':
  408. fErrorExit = TRUE;
  409. case 'x':
  410. fExclude = TRUE;
  411. break;
  412. case 'v':
  413. fVerbose = TRUE;
  414. break;
  415. case 'd':
  416. fDescend = TRUE;
  417. break;
  418. case 'f':
  419. fAll = TRUE;
  420. break;
  421. case 'n':
  422. fDel = FALSE;
  423. break;
  424. case 'o':
  425. fOnly = TRUE;
  426. break;
  427. case 'p':
  428. fPrintOnly = TRUE;
  429. break;
  430. case 's':
  431. fSubDebug = TRUE;
  432. break;
  433. default:
  434. usage( "Invalid switch - ", p, 0);
  435. }
  436. }
  437. if (fSubDebug && fDescend) {
  438. printf("UPD: /s and /d both specified, /d ignored\n");
  439. fDescend = FALSE;
  440. }
  441. if (fExclude)
  442. if ((fh = swopen ("$USER:\\tools.ini", "upd")) ) {
  443. while (swread (p1 = dir, BUFLEN, fh)) {
  444. while (*(p = strbskip (p1, " "))) {
  445. if (*(p1 = strbscan (p, " ")))
  446. *p1++ = 0;
  447. saveext (p) ;
  448. }
  449. }
  450. swclose (fh) ;
  451. }
  452. /* Must be at least one source dir and the dest dir. */
  453. if (c < 2)
  454. usage( 0 );
  455. /* Save away any wildcard specs at end of argument list */
  456. for (i=c-1; i>=2; i--)
  457. if (!savespec( v[ i ] ))
  458. break;
  459. else
  460. c--;
  461. /* Still must be at least one source dir and the dest dir. */
  462. if (c < 2)
  463. usage( 0 );
  464. /* Make sure destination is a valid directory */
  465. rootpath( v[ c-1 ], dest );
  466. if (ffirst( dest, FILE_ATTRIBUTE_DIRECTORY, &buf ) == -1)
  467. usage( "Destination directory does not exist - ", v[ c-1 ], 0 );
  468. else {
  469. findclose( &buf );
  470. c--;
  471. }
  472. if (!nWildSpecs)
  473. savespec( "*.*" );
  474. if (fVerbose) {
  475. printf( "Copying all files matching:" );
  476. for (i=0; i<nWildSpecs; i++)
  477. printf( " %s", wildSpecs[ i ] );
  478. printf( "\n" );
  479. printf( "To destination directory: %s\n", dest );
  480. printf( "From the following source directories:\n" );
  481. }
  482. for (i=0; i<c; i++) {
  483. if (rootpath( v[ i ], namebuf )) {
  484. printf( "\aSource directory does not exist - %s\n", v[ i ]);
  485. continue;
  486. }
  487. if (fVerbose) printf( " %s\n", namebuf );
  488. if (namebuf[k = strlen( namebuf ) - 1] == '\\')
  489. namebuf[k] = '\0';
  490. for (j=0; j<nWildSpecs; j++) {
  491. sprintf( source, "%s\\%s", namebuf, wildSpecs[ j ] );
  492. cCopied = 0;
  493. forfile( source, FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM, walk, NULL );
  494. if (!cCopied) {
  495. printf( "UPD: no src file matching %s\\%s\n", namebuf, wildSpecs[ j ] );
  496. fNoSrc = 1;
  497. }
  498. }
  499. if (fDescend) {
  500. sprintf( source, "%s\\*.*", namebuf );
  501. forfile( source, FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM, RecWalk, NULL );
  502. }
  503. /* if (fVerbose) printf( "\n" ); */
  504. }
  505. if (!fInGetfile)
  506. return( (int)fErrorExit ? (int)fNoSrc : fAnyUpd );
  507. }