Home | History | Annotate | Download | only in contrib
      1 /*
      2  * make-sparse.c --- make a sparse file from stdin
      3  *
      4  * Copyright 2004 by Theodore Ts'o.
      5  *
      6  * %Begin-Header%
      7  * This file may be redistributed under the terms of the GNU Public
      8  * License.
      9  * %End-Header%
     10  */
     11 
     12 #ifndef _LARGEFILE_SOURCE
     13 #define _LARGEFILE_SOURCE
     14 #endif
     15 #ifndef _LARGEFILE64_SOURCE
     16 #define _LARGEFILE64_SOURCE
     17 #endif
     18 
     19 #include <stdio.h>
     20 #include <unistd.h>
     21 #include <stdlib.h>
     22 #include <sys/types.h>
     23 #include <sys/stat.h>
     24 #include <fcntl.h>
     25 #include <errno.h>
     26 
     27 int full_read(int fd, char *buf, size_t count)
     28 {
     29 	int got, total = 0;
     30 	int pass = 0;
     31 
     32 	while (count > 0) {
     33 		got = read(fd, buf, count);
     34 		if (got == -1) {
     35 			if ((errno == EINTR) || (errno == EAGAIN))
     36 				continue;
     37 			return total ? total : -1;
     38 		}
     39 		if (got == 0) {
     40 			if (pass++ >= 3)
     41 				return total;
     42 			continue;
     43 		}
     44 		pass = 0;
     45 		buf += got;
     46 		total += got;
     47 		count -= got;
     48 	}
     49 	return total;
     50 }
     51 
     52 int main(int argc, char **argv)
     53 {
     54 	int fd, got, i;
     55 	int zflag = 0;
     56 	char buf[1024];
     57 
     58 	if (argc != 2) {
     59 		fprintf(stderr, "Usage: make-sparse out-file\n");
     60 		exit(1);
     61 	}
     62 	fd = open(argv[1], O_WRONLY|O_CREAT|O_TRUNC|O_LARGEFILE, 0777);
     63 	if (fd < 0) {
     64 		perror(argv[1]);
     65 		exit(1);
     66 	}
     67 	while (1) {
     68 		got = full_read(0, buf, sizeof(buf));
     69 		if (got == 0)
     70 			break;
     71 		if (got == sizeof(buf)) {
     72 			for (i=0; i < sizeof(buf); i++)
     73 				if (buf[i])
     74 					break;
     75 			if (i == sizeof(buf)) {
     76 				lseek(fd, sizeof(buf), SEEK_CUR);
     77 				zflag = 1;
     78 				continue;
     79 			}
     80 		}
     81 		zflag = 0;
     82 		write(fd, buf, got);
     83 	}
     84 	if (zflag) {
     85 		lseek(fd, -1, SEEK_CUR);
     86 		buf[0] = 0;
     87 		write(fd, buf, 1);
     88 	}
     89 	return 0;
     90 }
     91 
     92