/* * Extract a part from a file. * * Author: Peter Wu * Date: 2012-11-01 */ #include #include #include #include int main(int argc, char **argv) { if (argc < 4) { fprintf(stderr, "Usage: %s file offset last-byte|+length\n", *argv); return 1; } char *filename = argv[1]; unsigned long seekpos = strtoul(argv[2], NULL, 0); unsigned long bytes_end = strtoul(argv[3], NULL, 0); if (*argv[3] == '+') { if (bytes_end + seekpos < bytes_end) { fprintf(stderr, "Integer overflow on the last byte\n"); return 1; } bytes_end += seekpos; } if (bytes_end <= seekpos) { fprintf(stderr, "The last byte must be greater than the first byte.\n"); return 1; } FILE *fp; if (filename[0] == '-' && filename[1] == 0) fp = stdin; else fp = fopen(filename, "r"); if (!fp) { perror(filename); return 1; } unsigned long read_bytes = 0; if (!fseek(fp, seekpos, SEEK_SET)) read_bytes += seekpos; do { char buf[8 * 1024]; unsigned int read_count = sizeof(buf); unsigned long skip_bytes = 0; if (bytes_end - read_bytes < read_count) read_count = bytes_end - read_bytes; if (read_bytes < seekpos) skip_bytes = seekpos - read_bytes; unsigned long n = fread(buf, 1, read_count, fp); if (!n) break; /* EOF? */ if (n > skip_bytes) write(STDOUT_FILENO, buf + skip_bytes, n); read_bytes += n; } while (read_bytes < bytes_end); if (read_bytes != bytes_end) fprintf(stderr, "Output is truncated, missing %lu bytes.\n", bytes_end - read_bytes); fclose(fp); return 0; }