1 /*
2  * affstats.cpp:
3  *
4  * print specific statistics about one or more AFF files.
5  * Ideally, we can get the stats from the metadata, but this program will
6  * calculate it if necessary.
7  */
8 
9 /*
10  * Copyright (c) 2005-2006
11  *	Simson L. Garfinkel and Basis Technology, Inc.
12  *      All rights reserved.
13  *
14  * This code is derrived from software contributed by
15  * Simson L. Garfinkel
16  *
17  * Redistribution and use in source and binary forms, with or without
18  * modification, are permitted provided that the following conditions
19  * are met:
20  * 1. Redistributions of source code must retain the above copyright
21  *    notice, this list of conditions and the following disclaimer.
22  * 2. Redistributions in binary form must reproduce the above copyright
23  *    notice, this list of conditions and the following disclaimer in the
24  *    documentation and/or other materials provided with the distribution.
25  * 3. [omitted]
26  * 4. Neither the name of Simson Garfinkel, Basis Technology, or other
27  *    contributors to this program may be used to endorse or promote
28  *    products derived from this software without specific prior written
29  *    permission.
30  *
31  * THIS SOFTWARE IS PROVIDED BY SIMSON GARFINKEL, BASIS TECHNOLOGY,
32  * AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
33  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
34  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
35  * DISCLAIMED.  IN NO EVENT SHALL SIMSON GARFINKEL, BAIS TECHNOLOGy,
36  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
37  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
38  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
39  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
40  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
41  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
42  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
43  * SUCH DAMAGE.
44  */
45 
46 
47 #include "affconfig.h"
48 #include "afflib.h"
49 #include "afflib_i.h"
50 
51 #include <openssl/md5.h>
52 #include <openssl/sha.h>
53 #include <zlib.h>
54 #include <assert.h>
55 
56 #ifdef HAVE_ERR_H
57 #include <err.h>
58 #endif
59 
60 #ifdef HAVE_UNISTD_H
61 #include <unistd.h>
62 #endif
63 
64 #ifdef HAVE_UNISTD_H
65 #include <unistd.h>
66 #endif
67 
68 #ifdef WIN32
69 #include "unix4win32.h"
70 #include <malloc.h>
71 #endif
72 
73 const char *progname = "affstats";
74 int  opt_m = 0;
75 
usage()76 void usage()
77 {
78     printf("%s version %s\n\n",progname,PACKAGE_VERSION);
79     printf("usage: %s [options] infile(s)\n",progname);
80     printf("      -m = print all output in megabytes\n");
81     printf("      -v = Just print the version number and exit.\n");
82     exit(0);
83 }
84 
85 
title()86 void title()
87 {
88     printf("fname\tbytes\tcompressed\n");
89 }
90 
print_size(uint64_t s)91 void print_size(uint64_t s)
92 {
93     if(opt_m){
94 	printf("%u",(unsigned int)(s/(1024*1024)));
95 	return;
96     }
97     printf("%" I64u,s);
98 }
99 
affstats_title()100 void affstats_title()
101 {
102     printf("Name\tAF_IMAGESIZE\tCompressed\tUncompressed\tBlank\tBad\n");
103 }
104 
affstats(const char * fname)105 void affstats(const char *fname)
106 {
107     AFFILE *af = af_open(fname,O_RDONLY,0);
108     if(!af) af_err(1,"af_open(%s)",fname);
109 
110     printf("%s\t",fname);
111 
112     uint32_t segsize=0;
113 
114     int64_t imagesize=0;
115     int64_t blanksectors=0;
116     int64_t badsectors=0;
117     af_get_segq(af,AF_IMAGESIZE,&imagesize);
118     if(af_get_seg(af,AF_PAGESIZE,&segsize,0,0)){
119 	af_get_seg(af,AF_SEGSIZE_D,&segsize,0,0); // check for oldstype
120     }
121     af_get_segq(af,AF_BADSECTORS,&badsectors);
122     af_get_segq(af,AF_BLANKSECTORS,&blanksectors);
123 
124     print_size(imagesize);
125     printf("\t");
126     fflush(stdout);
127 
128     int64_t compressed_bytes = 0;
129     int64_t uncompressed_bytes = 0;
130 
131     /* Now read through all of the segments and count the number of
132      * data segments. We know the uncompressed size...
133      */
134     af_rewind_seg(af);
135     char segname[AF_MAX_NAME_LEN+1];
136     size_t datalen;
137     while(af_get_next_seg(af,segname,sizeof(segname),0,0,&datalen)==0){
138 	int64_t page_num = af_segname_page_number(segname);
139 	if(page_num>=0){
140 	    compressed_bytes += datalen;
141 	    uncompressed_bytes += segsize;
142 	}
143     }
144     if(uncompressed_bytes > imagesize) uncompressed_bytes = imagesize;
145 
146     print_size(compressed_bytes);
147     printf("\t");
148     print_size(uncompressed_bytes);
149     printf(" %" I64d " %" I64d,blanksectors,badsectors);
150     putchar('\n');
151 
152 
153 }
154 
155 
156 
157 
main(int argc,char ** argv)158 int main(int argc,char **argv)
159 {
160     int ch;
161     while ((ch = getopt(argc, argv, "mh?V")) != -1) {
162 	switch (ch) {
163 	case 'm':
164 	    opt_m = 1;
165 	    break;
166 	case 'h':
167 	case '?':
168 	default:
169 	    usage();
170 	    break;
171 	case 'V':
172 	    printf("%s version %s\n",progname,PACKAGE_VERSION);
173 	    exit(0);
174 	}
175     }
176     argc -= optind;
177     argv += optind;
178 
179     if(argc<1){
180 	usage();
181     }
182 
183     /* Each argument is now a file. Process each one */
184     affstats_title();
185     while(*argv){
186 	affstats(*argv++);
187 	argc--;
188     }
189     exit(0);
190 }
191 
192 
193