1 /*
2 * Shows information obtained from a VMware Virtual Disk (VMDK) file
3 *
4 * Copyright (C) 2009-2021, Joachim Metz <joachim.metz@gmail.com>
5 *
6 * Refer to AUTHORS for acknowledgements.
7 *
8 * This program is free software: you can redistribute it and/or modify
9 * it under the terms of the GNU Lesser General Public License as published by
10 * the Free Software Foundation, either version 3 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public License
19 * along with this program. If not, see <https://www.gnu.org/licenses/>.
20 */
21
22 #include <common.h>
23 #include <file_stream.h>
24 #include <memory.h>
25 #include <system_string.h>
26 #include <types.h>
27
28 #include <stdio.h>
29
30 #if defined( HAVE_IO_H ) || defined( WINAPI )
31 #include <io.h>
32 #endif
33
34 #if defined( HAVE_STDLIB_H ) || defined( WINAPI )
35 #include <stdlib.h>
36 #endif
37
38 #if defined( HAVE_UNISTD_H )
39 #include <unistd.h>
40 #endif
41
42 #include "info_handle.h"
43 #include "vmdktools_getopt.h"
44 #include "vmdktools_libcerror.h"
45 #include "vmdktools_libclocale.h"
46 #include "vmdktools_libcnotify.h"
47 #include "vmdktools_libvmdk.h"
48 #include "vmdktools_output.h"
49 #include "vmdktools_signal.h"
50 #include "vmdktools_unused.h"
51
52 info_handle_t *vmdkinfo_info_handle = NULL;
53 int vmdkinfo_abort = 0;
54
55 /* Prints the executable usage information
56 */
usage_fprint(FILE * stream)57 void usage_fprint(
58 FILE *stream )
59 {
60 if( stream == NULL )
61 {
62 return;
63 }
64 fprintf( stream, "Use vmdkinfo to determine information about a VMware Virtual Disk (VMDK)\n"
65 "image file.\n\n" );
66
67 fprintf( stream, "Usage: vmdkinfo [ -hvV ] source\n\n" );
68
69 fprintf( stream, "\tsource: the source file(s)\n\n" );
70
71 fprintf( stream, "\t-h: shows this help\n" );
72 fprintf( stream, "\t-v: verbose output to stderr\n" );
73 fprintf( stream, "\t-V: print version\n" );
74 }
75
76 /* Signal handler for vmdkinfo
77 */
vmdkinfo_signal_handler(vmdktools_signal_t signal VMDKTOOLS_ATTRIBUTE_UNUSED)78 void vmdkinfo_signal_handler(
79 vmdktools_signal_t signal VMDKTOOLS_ATTRIBUTE_UNUSED )
80 {
81 libcerror_error_t *error = NULL;
82 static char *function = "vmdkinfo_signal_handler";
83
84 VMDKTOOLS_UNREFERENCED_PARAMETER( signal )
85
86 vmdkinfo_abort = 1;
87
88 if( vmdkinfo_info_handle != NULL )
89 {
90 if( info_handle_signal_abort(
91 vmdkinfo_info_handle,
92 &error ) != 1 )
93 {
94 libcnotify_printf(
95 "%s: unable to signal info handle to abort.\n",
96 function );
97
98 libcnotify_print_error_backtrace(
99 error );
100 libcerror_error_free(
101 &error );
102 }
103 }
104 /* Force stdin to close otherwise any function reading it will remain blocked
105 */
106 #if defined( WINAPI ) && !defined( __CYGWIN__ )
107 if( _close(
108 0 ) != 0 )
109 #else
110 if( close(
111 0 ) != 0 )
112 #endif
113 {
114 libcnotify_printf(
115 "%s: unable to close stdin.\n",
116 function );
117 }
118 }
119
120 /* The main program
121 */
122 #if defined( HAVE_WIDE_SYSTEM_CHARACTER )
wmain(int argc,wchar_t * const argv[])123 int wmain( int argc, wchar_t * const argv[] )
124 #else
125 int main( int argc, char * const argv[] )
126 #endif
127 {
128 system_character_t * const *source_filenames = NULL;
129 libvmdk_error_t *error = NULL;
130 char *program = "vmdkinfo";
131 system_integer_t option = 0;
132 int number_of_source_filenames = 0;
133 int verbose = 0;
134
135 libcnotify_stream_set(
136 stderr,
137 NULL );
138 libcnotify_verbose_set(
139 1 );
140
141 if( libclocale_initialize(
142 "vmdktools",
143 &error ) != 1 )
144 {
145 fprintf(
146 stderr,
147 "Unable to initialize locale values.\n" );
148
149 goto on_error;
150 }
151 if( vmdktools_output_initialize(
152 _IONBF,
153 &error ) != 1 )
154 {
155 fprintf(
156 stderr,
157 "Unable to initialize output settings.\n" );
158
159 goto on_error;
160 }
161 vmdktools_output_version_fprint(
162 stdout,
163 program );
164
165 while( ( option = vmdktools_getopt(
166 argc,
167 argv,
168 _SYSTEM_STRING( "hvV" ) ) ) != (system_integer_t) -1 )
169 {
170 switch( option )
171 {
172 case (system_integer_t) '?':
173 default:
174 fprintf(
175 stderr,
176 "Invalid argument: %" PRIs_SYSTEM "\n",
177 argv[ optind - 1 ] );
178
179 usage_fprint(
180 stdout );
181
182 return( EXIT_FAILURE );
183
184 case (system_integer_t) 'h':
185 usage_fprint(
186 stdout );
187
188 return( EXIT_SUCCESS );
189
190 case (system_integer_t) 'v':
191 verbose = 1;
192
193 break;
194
195 case (system_integer_t) 'V':
196 vmdktools_output_copyright_fprint(
197 stdout );
198
199 return( EXIT_SUCCESS );
200 }
201 }
202 if( optind == argc )
203 {
204 fprintf(
205 stderr,
206 "Missing source file(s).\n" );
207
208 usage_fprint(
209 stdout );
210
211 return( EXIT_FAILURE );
212 }
213 source_filenames = &( argv[ optind ] );
214 number_of_source_filenames = argc - optind;
215
216 libcnotify_verbose_set(
217 verbose );
218 libvmdk_notify_set_stream(
219 stderr,
220 NULL );
221 libvmdk_notify_set_verbose(
222 verbose );
223
224 if( info_handle_initialize(
225 &vmdkinfo_info_handle,
226 &error ) != 1 )
227 {
228 fprintf(
229 stderr,
230 "Unable to initialize info handle.\n" );
231
232 goto on_error;
233 }
234 if( info_handle_open_input(
235 vmdkinfo_info_handle,
236 source_filenames,
237 number_of_source_filenames,
238 &error ) != 1 )
239 {
240 fprintf(
241 stderr,
242 "Unable to open source file(s).\n" );
243
244 goto on_error;
245 }
246 if( info_handle_file_fprint(
247 vmdkinfo_info_handle,
248 &error ) != 1 )
249 {
250 fprintf(
251 stderr,
252 "Unable to print file information.\n" );
253
254 goto on_error;
255 }
256 if( info_handle_close(
257 vmdkinfo_info_handle,
258 &error ) != 0 )
259 {
260 fprintf(
261 stderr,
262 "Unable to close info handle.\n" );
263
264 goto on_error;
265 }
266 if( info_handle_free(
267 &vmdkinfo_info_handle,
268 &error ) != 1 )
269 {
270 fprintf(
271 stderr,
272 "Unable to free info handle.\n" );
273
274 goto on_error;
275 }
276 return( EXIT_SUCCESS );
277
278 on_error:
279 if( error != NULL )
280 {
281 libcnotify_print_error_backtrace(
282 error );
283 libcerror_error_free(
284 &error );
285 }
286 if( vmdkinfo_info_handle != NULL )
287 {
288 info_handle_free(
289 &vmdkinfo_info_handle,
290 NULL );
291 }
292 return( EXIT_FAILURE );
293 }
294
295