diff --git a/ftcp/GNUmakefile b/ftcp/GNUmakefile new file mode 100644 index 0000000..c2bd830 --- /dev/null +++ b/ftcp/GNUmakefile @@ -0,0 +1,13 @@ +include GNUmakevars +include GNUmakerules + +ftcp: ftcp.o + $(CC) $^ -lant -o $@ + +clean: + rm -f *.o ftcp core foo bar + +install: $(BINDIR)/ftcp + +distclean: clean + rm -f *.bak *.d diff --git a/ftcp/ftcp.c b/ftcp/ftcp.c new file mode 100644 index 0000000..3896e95 --- /dev/null +++ b/ftcp/ftcp.c @@ -0,0 +1,105 @@ +char ftcp_rcs_id[] = + "$Id: ftcp.c,v 1.1 2002-03-18 20:40:08 hjp Exp $"; +/* + ftcp - fault tolerant copy + + copy one file to another, ignoring any errors. + This is useful for copying files from defective media. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +char *cmnd; + + +off_t skip_size = 512; +size_t buf_size = 512; + +static void usage(void) +{ + fprintf(stderr, "Usage: %s [-s skip_size] source dest\n", cmnd); + exit(1); +} + + +static int ftcp(char const *src, char const *dest) +{ + int sfd, dfd, count; + char *buf; + off_t off = 0; + + if ((buf = malloc(buf_size)) == NULL) { + return -1; + } + sfd = open(src, O_RDONLY); + if (sfd < 0) + return -1; + dfd = open(dest, O_WRONLY|O_CREAT|O_TRUNC, 0666); + if (dfd < 0) + { + close(sfd); + return -1; + } + for (;;) { + lseek(sfd, off, SEEK_SET); + count = read(sfd, buf, buf_size); + switch (count) { + case -1: + fprintf(stderr, "%s: error at offset %lu: %s\n", + cmnd, (unsigned long)off, strerror(errno)); + off += skip_size; + break; + case 0: + goto the_end; + default: + lseek(dfd, off, SEEK_SET); + write(dfd, buf, count); + off += count; + } + } + the_end: + + close(sfd); + close(dfd); + return 0; +} + + + +int main(int argc, char **argv) +{ + int c; + char *p; + + cmnd = argv[0]; + + while ((c = getopt(argc, argv, "s:")) != EOF) { + switch (c) { + case 's': + skip_size = strtoul(optarg, &p, 0); + if (p == optarg || *p != '\0') usage(); + break; + case '?': + usage(); + default: + assert(0); + } + } + + if (optind != argc - 2) { + usage(); + } + ftcp(argv[optind], argv[optind+1]); + return 0; +}