18680b4e6805ac9c19980c2348b6cc88b90f5225aTheodore Ts'o/* 28680b4e6805ac9c19980c2348b6cc88b90f5225aTheodore Ts'o * make-sparse.c --- make a sparse file from stdin 38680b4e6805ac9c19980c2348b6cc88b90f5225aTheodore Ts'o * 48680b4e6805ac9c19980c2348b6cc88b90f5225aTheodore Ts'o * Copyright 2004 by Theodore Ts'o. 58680b4e6805ac9c19980c2348b6cc88b90f5225aTheodore Ts'o * 68680b4e6805ac9c19980c2348b6cc88b90f5225aTheodore Ts'o * %Begin-Header% 78680b4e6805ac9c19980c2348b6cc88b90f5225aTheodore Ts'o * This file may be redistributed under the terms of the GNU Public 88680b4e6805ac9c19980c2348b6cc88b90f5225aTheodore Ts'o * License. 98680b4e6805ac9c19980c2348b6cc88b90f5225aTheodore Ts'o * %End-Header% 108680b4e6805ac9c19980c2348b6cc88b90f5225aTheodore Ts'o */ 118680b4e6805ac9c19980c2348b6cc88b90f5225aTheodore Ts'o 128680b4e6805ac9c19980c2348b6cc88b90f5225aTheodore Ts'o#define _LARGEFILE_SOURCE 138680b4e6805ac9c19980c2348b6cc88b90f5225aTheodore Ts'o#define _LARGEFILE64_SOURCE 148680b4e6805ac9c19980c2348b6cc88b90f5225aTheodore Ts'o 158680b4e6805ac9c19980c2348b6cc88b90f5225aTheodore Ts'o#include <stdio.h> 168680b4e6805ac9c19980c2348b6cc88b90f5225aTheodore Ts'o#include <unistd.h> 178680b4e6805ac9c19980c2348b6cc88b90f5225aTheodore Ts'o#include <stdlib.h> 188680b4e6805ac9c19980c2348b6cc88b90f5225aTheodore Ts'o#include <sys/types.h> 198680b4e6805ac9c19980c2348b6cc88b90f5225aTheodore Ts'o#include <sys/stat.h> 208680b4e6805ac9c19980c2348b6cc88b90f5225aTheodore Ts'o#include <fcntl.h> 218680b4e6805ac9c19980c2348b6cc88b90f5225aTheodore Ts'o#include <errno.h> 228680b4e6805ac9c19980c2348b6cc88b90f5225aTheodore Ts'o 238680b4e6805ac9c19980c2348b6cc88b90f5225aTheodore Ts'oint full_read(int fd, char *buf, size_t count) 248680b4e6805ac9c19980c2348b6cc88b90f5225aTheodore Ts'o{ 258680b4e6805ac9c19980c2348b6cc88b90f5225aTheodore Ts'o int got, total = 0; 268680b4e6805ac9c19980c2348b6cc88b90f5225aTheodore Ts'o int pass = 0; 278680b4e6805ac9c19980c2348b6cc88b90f5225aTheodore Ts'o 288680b4e6805ac9c19980c2348b6cc88b90f5225aTheodore Ts'o while (count > 0) { 298680b4e6805ac9c19980c2348b6cc88b90f5225aTheodore Ts'o got = read(fd, buf, count); 308680b4e6805ac9c19980c2348b6cc88b90f5225aTheodore Ts'o if (got == -1) { 318680b4e6805ac9c19980c2348b6cc88b90f5225aTheodore Ts'o if ((errno == EINTR) || (errno == EAGAIN)) 328680b4e6805ac9c19980c2348b6cc88b90f5225aTheodore Ts'o continue; 338680b4e6805ac9c19980c2348b6cc88b90f5225aTheodore Ts'o return total ? total : -1; 348680b4e6805ac9c19980c2348b6cc88b90f5225aTheodore Ts'o } 358680b4e6805ac9c19980c2348b6cc88b90f5225aTheodore Ts'o if (got == 0) { 368680b4e6805ac9c19980c2348b6cc88b90f5225aTheodore Ts'o if (pass++ >= 3) 378680b4e6805ac9c19980c2348b6cc88b90f5225aTheodore Ts'o return total; 388680b4e6805ac9c19980c2348b6cc88b90f5225aTheodore Ts'o continue; 398680b4e6805ac9c19980c2348b6cc88b90f5225aTheodore Ts'o } 408680b4e6805ac9c19980c2348b6cc88b90f5225aTheodore Ts'o pass = 0; 418680b4e6805ac9c19980c2348b6cc88b90f5225aTheodore Ts'o buf += got; 428680b4e6805ac9c19980c2348b6cc88b90f5225aTheodore Ts'o total += got; 438680b4e6805ac9c19980c2348b6cc88b90f5225aTheodore Ts'o count -= got; 448680b4e6805ac9c19980c2348b6cc88b90f5225aTheodore Ts'o } 458680b4e6805ac9c19980c2348b6cc88b90f5225aTheodore Ts'o return total; 468680b4e6805ac9c19980c2348b6cc88b90f5225aTheodore Ts'o} 478680b4e6805ac9c19980c2348b6cc88b90f5225aTheodore Ts'o 488680b4e6805ac9c19980c2348b6cc88b90f5225aTheodore Ts'oint main(int argc, char **argv) 498680b4e6805ac9c19980c2348b6cc88b90f5225aTheodore Ts'o{ 508680b4e6805ac9c19980c2348b6cc88b90f5225aTheodore Ts'o int fd, got, i; 514087bbd68bc129c19f0130ba36679e3e8c80c617Theodore Ts'o int zflag = 0; 528680b4e6805ac9c19980c2348b6cc88b90f5225aTheodore Ts'o char buf[1024]; 538680b4e6805ac9c19980c2348b6cc88b90f5225aTheodore Ts'o 548680b4e6805ac9c19980c2348b6cc88b90f5225aTheodore Ts'o if (argc != 2) { 558680b4e6805ac9c19980c2348b6cc88b90f5225aTheodore Ts'o fprintf(stderr, "Usage: make-sparse out-file\n"); 568680b4e6805ac9c19980c2348b6cc88b90f5225aTheodore Ts'o exit(1); 578680b4e6805ac9c19980c2348b6cc88b90f5225aTheodore Ts'o } 588680b4e6805ac9c19980c2348b6cc88b90f5225aTheodore Ts'o fd = open(argv[1], O_WRONLY|O_CREAT|O_TRUNC|O_LARGEFILE, 0777); 598680b4e6805ac9c19980c2348b6cc88b90f5225aTheodore Ts'o if (fd < 0) { 608680b4e6805ac9c19980c2348b6cc88b90f5225aTheodore Ts'o perror(argv[1]); 618680b4e6805ac9c19980c2348b6cc88b90f5225aTheodore Ts'o exit(1); 628680b4e6805ac9c19980c2348b6cc88b90f5225aTheodore Ts'o } 638680b4e6805ac9c19980c2348b6cc88b90f5225aTheodore Ts'o while (1) { 648680b4e6805ac9c19980c2348b6cc88b90f5225aTheodore Ts'o got = full_read(0, buf, sizeof(buf)); 658680b4e6805ac9c19980c2348b6cc88b90f5225aTheodore Ts'o if (got == 0) 668680b4e6805ac9c19980c2348b6cc88b90f5225aTheodore Ts'o break; 678680b4e6805ac9c19980c2348b6cc88b90f5225aTheodore Ts'o if (got == sizeof(buf)) { 688680b4e6805ac9c19980c2348b6cc88b90f5225aTheodore Ts'o for (i=0; i < sizeof(buf); i++) 698680b4e6805ac9c19980c2348b6cc88b90f5225aTheodore Ts'o if (buf[i]) 708680b4e6805ac9c19980c2348b6cc88b90f5225aTheodore Ts'o break; 718680b4e6805ac9c19980c2348b6cc88b90f5225aTheodore Ts'o if (i == sizeof(buf)) { 728680b4e6805ac9c19980c2348b6cc88b90f5225aTheodore Ts'o lseek(fd, sizeof(buf), SEEK_CUR); 734087bbd68bc129c19f0130ba36679e3e8c80c617Theodore Ts'o zflag = 1; 748680b4e6805ac9c19980c2348b6cc88b90f5225aTheodore Ts'o continue; 758680b4e6805ac9c19980c2348b6cc88b90f5225aTheodore Ts'o } 768680b4e6805ac9c19980c2348b6cc88b90f5225aTheodore Ts'o } 774087bbd68bc129c19f0130ba36679e3e8c80c617Theodore Ts'o zflag = 0; 788680b4e6805ac9c19980c2348b6cc88b90f5225aTheodore Ts'o write(fd, buf, got); 798680b4e6805ac9c19980c2348b6cc88b90f5225aTheodore Ts'o } 804087bbd68bc129c19f0130ba36679e3e8c80c617Theodore Ts'o if (zflag) { 814087bbd68bc129c19f0130ba36679e3e8c80c617Theodore Ts'o lseek(fd, -1, SEEK_CUR); 824087bbd68bc129c19f0130ba36679e3e8c80c617Theodore Ts'o buf[0] = 0; 834087bbd68bc129c19f0130ba36679e3e8c80c617Theodore Ts'o write(fd, buf, 1); 844087bbd68bc129c19f0130ba36679e3e8c80c617Theodore Ts'o } 858680b4e6805ac9c19980c2348b6cc88b90f5225aTheodore Ts'o return 0; 868680b4e6805ac9c19980c2348b6cc88b90f5225aTheodore Ts'o} 878680b4e6805ac9c19980c2348b6cc88b90f5225aTheodore Ts'o 88