/[gxemul]/upstream/0.4.3/experiments/cp_removeblocks.c
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Contents of /upstream/0.4.3/experiments/cp_removeblocks.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 33 - (show annotations)
Mon Oct 8 16:21:06 2007 UTC (16 years, 5 months ago) by dpavlin
File MIME type: text/plain
File size: 4202 byte(s)
0.4.3
1 /*
2 * Copyright (C) 2004 Anders Gavare. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
6 *
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * 3. The name of the author may not be used to endorse or promote products
13 * derived from this software without specific prior written permission.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
26 *
27 *
28 * $Id: cp_removeblocks.c,v 1.11 2005/01/09 01:55:27 debug Exp $
29 *
30 * This program copies a file, but only those blocks that are not zero-
31 * filled. Typical usage would be if you have a harddisk image stored
32 * as a file, which has all its zeroed blocks explicitly saved on disk,
33 * and would like to save space.
34 *
35 * Example: You download a file called diskimage.gz from somewhere,
36 * run gunzip on it, and the resulting file diskimage is
37 * 1 GB large. ls -l reports the file size as 1 GB, and
38 * so does 'du -k diskimage'. If a lot of the space used
39 * by diskimage is actually zeroes, those parts do not need
40 * to actually be saved. By running this program on diskimage:
41 *
42 * ./cp_removeblocks diskimage diskimage_compact
43 *
44 * you will get a file with the same functionality, but possibly
45 * using less disk space. ('ls -l diskimage_compact' should
46 * return the same size as for diskimage, but 'du -k' will
47 * print only how many kb the file takes up on your disk.)
48 *
49 * You don't even need to gunzip the file to be 1 GB first,
50 * you can pipe it through cp_removeblocks directly.
51 *
52 * gunzip -c file.img.gz | ./cp_removeblocks - file.img
53 */
54
55 #include <stdio.h>
56 #include <stdlib.h>
57 #include <string.h>
58 #include <sys/types.h>
59
60 #define BSIZE 512
61
62
63 int main(int argc, char *argv[])
64 {
65 FILE *f1, *f2;
66 unsigned char buf[BSIZE];
67 off_t len;
68 off_t in_pos = 0;
69 int i, res, wrote_last = 0;
70
71 if (argc != 3) {
72 fprintf(stderr, "usage: %s infile outfile\n", argv[0]);
73 fprintf(stderr, "if infile is \"-\", then stdin is used.\n");
74 fprintf(stderr, "if outfile is \"-\", then stdout is used.\n");
75 exit(1);
76 }
77
78 if (strcmp(argv[1], "-") == 0)
79 f1 = stdin;
80 else
81 f1 = fopen(argv[1], "r");
82
83 if (f1 == NULL) {
84 perror(argv[1]);
85 exit(1);
86 }
87
88 if (strcmp(argv[2], "-") == 0)
89 f2 = stdout;
90 else
91 f2 = fopen(argv[2], "w");
92
93 if (f2 == NULL) {
94 perror(argv[2]);
95 exit(1);
96 }
97
98 while (!feof(f1)) {
99 len = fread(buf, 1, BSIZE, f1);
100
101 if (len > 0) {
102 /* Check for data in buf: */
103 for (i=0; i<len; i++)
104 if (buf[i])
105 break;
106
107 if (i < len) {
108 fseeko(f2, in_pos, SEEK_SET);
109 fwrite(buf, 1, len, f2);
110 wrote_last = 1;
111 } else
112 wrote_last = 0;
113
114 in_pos += len;
115 }
116 }
117
118 /*
119 * Copy the last byte explicitly, if necessary.
120 * (This causes f2 to get the correct file size.)
121 */
122 if (!wrote_last && in_pos > 0) {
123 res = fseeko(f2, in_pos - 1, SEEK_SET);
124 if (res != 0)
125 perror("fseeko(f2)");
126
127 buf[0] = '\0';
128 fwrite(&buf[0], 1, 1, f2);
129 }
130
131 fclose(f1);
132 fclose(f2);
133
134 return 0;
135 }
136

  ViewVC Help
Powered by ViewVC 1.1.26