mksparse.c (1851B)
1 /* Copyright 2013 Brian Swetland <swetland@frotz.net> 2 * 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16 #define _GNU_SOURCE /* for SEEK_HOLE */ 17 18 #include <stdio.h> 19 #include <string.h> 20 #include <errno.h> 21 #include <unistd.h> 22 #include <fcntl.h> 23 24 #include "util.h" 25 26 static u8 buffer[1024*1024]; 27 28 int main(int argc, char **argv) { 29 struct chunk c; 30 off_t a, b = 0; 31 int fin, fout; 32 33 if (argc != 3) { 34 fprintf(stderr, "usage: mksparse <infile> <outfile>"); 35 return -1; 36 } 37 38 if ((fin = open(argv[1], O_RDONLY)) < 0) { 39 fprintf(stderr, "error: cannot open '%s' for reading\n", argv[1]); 40 return -1; 41 } 42 43 if (!strcmp(argv[2], "-")) { 44 fout = 1; 45 } else if ((fout = open(argv[2], O_WRONLY | O_CREAT, 0600)) < 0) { 46 fprintf(stderr, "error: cannot open '%s' for writing\n", argv[2]); 47 return -1; 48 } 49 50 while ((a = lseek(fin, b, SEEK_DATA)) >= 0) { 51 b = lseek(fin, a, SEEK_HOLE); 52 c.start = a; 53 c.length = b - a; 54 if (lseek(fin, a, SEEK_SET) != a) 55 goto fail; 56 if (writex(fout, &c, sizeof(c))) 57 goto fail; 58 if (copyx(fin, fout, c.length, buffer, sizeof(buffer))) 59 goto fail; 60 /* fprintf(stderr, "%lu bytes at %lu\n", c.length, c.start); */ 61 } 62 63 c.start = c.length = 0; 64 if (writex(fout, &c, sizeof(c))) 65 goto fail; 66 67 if (close(fout)) 68 goto fail; 69 70 return 0; 71 72 fail: 73 fprintf(stderr, "error: %s\n", strerror(errno)); 74 return -1; 75 } 76