/* * A program to replace the DOS replace.exe command * * Emmet P. Gray US Army, HQ III Corps & Fort Hood * Emmet.Gray@hood.army.mil Attn: AFZF-PW-ENV * Directorate of Public Works * Environmental Division * Fort Hood, TX 76544-5028 */ #include #include #include #include #include #include int main(int argc, char** argv) { char from[MAXPATH], to[MAXPATH], *p; int c, add_option, update_option, ret, attr_to; struct stat sbuf_to, sbuf_from; struct ffblk fbuf; int getopt(int, char**, char*); void usage(void); int copyfile(char*, char*, int); /* quick sanity check for number of command line arguments*/ if (argc < 4) { usage(); exit(1); } strcpy(from, argv[1]); strcpy(to, argv[2]); /* parse the rest of the command line */ add_option = 0; update_option = 0; while ((c = getopt(argc, argv, "AaUu")) != EOF) { switch(c) { case 'a': case 'A': add_option =1; break; case 'u': case 'U': update_option =1; default: exit(1); } } /* The /A and /U are mutualy exclusive options */ if ((add_option + update_option) != 1) { fprintf(stderr, "Not a valid option\n"); exit(1); } /* The destination must be a directory) */ attr_to = _rtl_chmod(to, 0); if ((attr_to < 0) || !(attr_to & FA_DIREC)) { fprintf(stderr, "Destination must be a directory\n"); exit(1); } /* run thru the list of matching files */ if (findfirst(from, &fbuf, 47) < 0) { fprintf(stderr, "Can't find source file\n"); exit(1); } ret = 0; do { /* rebuild the source path */ strcpy(from, argv[1]); if ((p = strrchr(from, '\\')) != NULL) { *p = '\0'; strcat(from, "\\"); strcat(from, fbuf.ff_name); } else strcpy(from, fbuf.ff_name); /* rebuild the destination path */ strcpy(to, argv[2]); if (to[strlen(to)-1] != '\\') strcat(to, "\\"); if ((p = strrchr(from, '\\')) != NULL) strcat(to, ++p); else strcat(to, from); /* lock and load! */ if (add_option) { /* copy only if it doesn't already exist */ if (access(to, 0)) ret = ret + copyfile(from, to, 1); } if (update_option) { /* copy only if it does exist and is older */ if (stat(to, &sbuf_to) < 0) continue; stat(from, &sbuf_from); if (sbuf_from.st_mtime > sbuf_to.st_mtime) ret = ret + copyfile(from, to, 1); } } while (findnext(&fbuf) == 0); return(ret); } int copyfile(from_file, to_file, verbose) char *from_file, *to_file; int verbose; { FILE *fp_from, *fp_to; int num; char buf[BUFSIZ]; if (!(fp_from = fopen(from_file, "r"))) { if (verbose) fprintf(stderr, "Can't open \"%s\" for read\n", from_file); return(1); } if (!(fp_to = fopen(to_file, "w"))) { if (verbose) fprintf(stderr, "Can't open \"%s\" for write\n", to_file); fclose(fp_from); return(1); } while ((num = fread(buf, sizeof(char), BUFSIZ, fp_from)) > 0) { if (fwrite(buf, sizeof(char), num, fp_to) != num) { if (verbose) fprintf(stderr, "Write error on \"%s\"\n", to_file); fclose(fp_from); fclose(fp_to); return(1); } } if (verbose) printf("Copied %s\n", from_file); fclose(fp_from); fclose(fp_to); return(0); } /* * The "usage" error message */ void usage() { fprintf(stderr, "Replaces files.\n\n"); fprintf(stderr, "REPLACE [drive1:][path1]filename [drive2:][path2] [/A] [/U]\n"); fprintf(stderr, " [drive1:][path1]filename Specifies the source file or files.\n"); fprintf(stderr, " [drive2:][path2] Specifies the directory where files are to be\n"); fprintf(stderr, " replaced.\n"); fprintf(stderr, " /A Adds new files to destination directory. Cannot\n"); fprintf(stderr, " use with /U switch.\n"); fprintf(stderr, " /U Replaces (updates) only files that are older than\n"); fprintf(stderr, " source files. Cannot use with the /A switch.\n"); return; } int getopt(argc, argv, opts) int argc; char** argv; char* opts; { static int w = 1; static int c = 0; char ret; if (c >= strlen(argv[w])) { w++; c = 0; } if (w > argc) return(EOF); while (c < strlen(argv[w])) { if (argv[w][c] == '/') { ret = argv[w][c+1]; c = c+2; if (strchr(opts, ret) != NULL) return (int)ret; else { fprintf(stderr, "/%c Invalid option\n", ret); return '?'; } } w++; c = 0; } return(EOF); }