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