1 #include "config.h"
2 
3 #include <sys/types.h>
4 #include <sys/param.h>
5 #include <errno.h>
6 #include <limits.h>
7 #include <stdio.h>
8 #include <stdlib.h>
9 #include <string.h>
10 #include <unistd.h>
11 
12 #include "argcargv.h"
13 #include "list.h"
14 
15 #define K_CLIENT	0
16 #define K_SERVER	1
17 
18 extern int		errno;
19 
20 off_t			lsize( char *tpath );
21 off_t 			kfile_size( char *kfile, int location );
22 
23 static struct list	*kfile_list;
24 static char		kdir[ MAXPATHLEN ];
25 
26     off_t
lsize(char * tpath)27 lsize( char *tpath )
28 {
29     FILE		*tfp = NULL;
30     unsigned long long	totalsize = 0, cursize = 0;
31     char		**tav = NULL;
32     char		line[ MAXPATHLEN * 2 ];
33     int			tac, linenum = 1;
34 
35     if (( tfp = fopen( tpath, "r" )) == NULL ) {
36         fprintf( stderr, "fopen %s: %s\n", tpath, strerror( errno ));
37         exit( 2 );
38     }
39 
40     while ( fgets( line, MAXPATHLEN * 2, tfp ) != NULL ) {
41         linenum++;
42         if (( tac = argcargv( line, &tav )) != 8 ) {
43             continue;
44         }
45 
46         if ( *tav[ 0 ] != 'a' && *tav[ 0 ] != 'f' ) {
47             continue;
48         }
49 
50 	/* XXX - use strtoofft */
51         cursize = strtoull( tav[ 6 ], NULL, 10 );
52         if ( errno == ERANGE || errno == EINVAL ) {
53             fprintf( stderr, "line %d: strtoull %s: %s\n",
54                         linenum, tav[ 6 ], strerror( errno ));
55             exit( 2 );
56         }
57 
58         totalsize += cursize;
59     }
60 
61     ( void )fclose( tfp );
62 
63     return( totalsize );
64 }
65 
66     off_t
kfile_size(char * kfile,int location)67 kfile_size( char *kfile, int location )
68 {
69     FILE	*fp;
70     off_t	cursize = 0, total = 0;
71     int		length, ac, linenum = 0;
72     char	line[ MAXPATHLEN ];
73     char	fullpath[ MAXPATHLEN ];
74     char	*subpath;
75     char	**av;
76 
77     if (( fp = fopen( kfile, "r" )) == NULL ) {
78 	perror( kfile );
79 	return( -1 );
80     }
81 
82     while ( fgets( line, sizeof( line ), fp ) != NULL ) {
83 	linenum++;
84 	length = strlen( line );
85 	if ( line[ length - 1 ] != '\n' ) {
86 	    fprintf( stderr, "command: line %d: line too long\n", linenum );
87 	    return( -1 );
88 	}
89 
90 	/* skips blank lines and comments */
91 	if ((( ac = argcargv( line, &av )) == 0 ) || ( *av[ 0 ] == '#' )) {
92 	    continue;
93 	}
94 
95 	if ( ac != 2 ) {
96 	    fprintf( stderr, "command: line %d: expected 2 arguments, got %d\n",
97 		    linenum, ac );
98 	    return( -1 );
99 	}
100 
101 	switch( location ) {
102 	case K_CLIENT:
103 	    if ( snprintf( fullpath, MAXPATHLEN, "%s%s", kdir,
104 		    av[ 1 ] ) >= MAXPATHLEN ) {
105 		fprintf( stderr, "command: line %d: path too long\n",
106 			linenum );
107 		fprintf( stderr, "command: line %d: %s%s\n",
108 			linenum, kdir, av[ 1 ] );
109 		return( -1 );
110 	    }
111 	    break;
112 
113 	case K_SERVER:
114 	    if ( *av[ 0 ] == 'k' ) {
115 		subpath = "command";
116 	    } else {
117 		subpath = "transcript";
118 	    }
119 	    if ( snprintf( fullpath, MAXPATHLEN, "%s/%s/%s", _RADMIND_PATH,
120 			subpath, av[ 1 ] ) >= MAXPATHLEN ) {
121 		fprintf( stderr, "command: line %d: path too long\n",
122 			linenum );
123 		fprintf( stderr, "command: line %d: %s%s\n",
124 			linenum, kdir, av[ 1 ] );
125 		return( -1 );
126 	    }
127 	    break;
128 
129 	default:
130 	    fprintf( stderr, "unknown location\n" );
131 	    return( -1 );
132 	}
133 
134 	switch( *av[ 0 ] ) {
135 	case 'k':				/* command file */
136 	    if ( list_check( kfile_list, fullpath )) {
137 		fprintf( stderr,
138 		    "%s: line %d: command file loop: %s already included\n",
139 		    kfile, linenum, av[ 1 ] );
140 		return( -1 );
141 	    }
142 	    if ( list_insert( kfile_list, fullpath ) != 0 ) {
143 		perror( "list_insert" );
144 		return( -1 );
145 	    }
146 
147 	    if (( cursize = kfile_size( fullpath, location )) < 0 ) {
148 		return( -1 );
149 	    }
150 	    total += cursize;
151 	    break;
152 
153 	case 'n':				/* negative */
154 	    /* XXX - include sizes from negative? */
155 	    continue;
156 
157 	case 'p':				/* positive */
158 	    total += lsize( fullpath );
159 	    break;
160 
161 	case 's':				/* special */
162 	    /* XXX - provide -h option to indicate client? */
163 	    continue;
164 
165 	default:
166 	    fprintf( stderr, "command: line %d: '%s' invalid\n",
167 		    linenum, av[ 0 ] );
168 	    return( -1 );
169 	}
170     }
171 
172     if ( fclose( fp ) != 0 ) {
173 	perror( kfile );
174 	return( -1 );
175     }
176 
177     return( total );
178 }
179 
180     int
main(int ac,char * av[])181 main( int ac, char *av[] )
182 {
183     char		*path = NULL, *ext = NULL, *p;
184     double		totalsize = 0;
185     int			c, factor = 1024, err = 0, kfile = 0;
186     extern int		optind;
187 
188     while (( c = getopt( ac, av, "bgkm" )) != EOF ) {
189 	switch ( c ) {
190 	case 'b':	/* bytes */
191 	    factor = 1;
192 	    break;
193 
194 	case 'g':	/* gigabytes */
195 	    factor = ( 1024 * 1024 * 1024 );
196 	    break;
197 
198 	case 'k':	/* kilobytes (default) */
199 	    factor = 1024;
200 	    break;
201 
202 	case 'm':	/* megabytes */
203 	    factor = ( 1024 * 1024 );
204 	    break;
205 
206 	case '?':
207 	    err++;
208 	}
209     }
210 
211     path = av[ optind ];
212 
213     if ( err || ( ac - optind ) != 1 ) {
214 	fprintf( stderr, "Usage: %s [ -bgkmt ] { commandfile "
215 			"| transcript }\n", av[ 0 ] );
216 	exit( 1 );
217     }
218 
219     if (( ext = strrchr( path, '.' )) != NULL ) {
220 	if ( strcmp( ++ext, "K" ) == 0 ) {
221 	    kfile = 1;
222 	    if ( strlen( path ) >= MAXPATHLEN ) {
223 		fprintf( stderr, "%s: path too long\n", path );
224 		exit( 2 );
225 	    }
226 	    strcpy( kdir, path );
227 
228 	    if (( p = strrchr( kdir, '/' )) == NULL ) {
229 		/* use working directory */
230 		strcpy( kdir, "./" );
231 	    } else {
232 		p++;
233 		*p = (char)'\0';
234 	    }
235 	    if (( kfile_list = list_new()) == NULL ) {
236 		perror( "list_new" );
237 		exit( 2 );
238 	    }
239 	    if ( list_insert( kfile_list, path ) != 0 ) {
240 		perror( "list_insert" );
241 		exit( 2 );
242 	    }
243 	}
244 	/* otherwise assume it's a transcript */
245     }
246 
247     if ( kfile ) {
248 	if (( totalsize = ( double )kfile_size( path, K_SERVER )) < 0 ) {
249 	    exit( 2 );
250 	}
251     } else {
252 	totalsize = ( double )lsize( path );
253     }
254 
255     totalsize /= ( double )factor;
256 
257     printf( "%.2f\n", totalsize );
258 
259     return( 0 );
260 }
261