1 /*
2 * Copyright (C) 2010 Michael Brown <mbrown@fensystems.co.uk>.
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of the
7 * License, or any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17 * 02110-1301, USA.
18 */
19
20 #include <stddef.h>
21 #include <stdint.h>
22 #include <stdlib.h>
23 #include <stdio.h>
24 #include <string.h>
25 #include <errno.h>
26 #include <sys/types.h>
27 #include <sys/stat.h>
28 #include <sys/mman.h>
29 #include <unistd.h>
30 #include <fcntl.h>
31 #include <getopt.h>
32
33 #define eprintf(...) fprintf ( stderr, __VA_ARGS__ )
34
35 /** Command-line options */
36 struct options {
37 };
38
39 /** Error usage information */
40 struct einfo {
41 /** Size of error information record */
42 uint32_t size;
43 /** Error number */
44 uint32_t error;
45 /** Offset to error description (NUL-terminated) */
46 uint32_t desc;
47 /** Offset to file name (NUL-terminated) */
48 uint32_t file;
49 /** Line number */
50 uint32_t line;
51 } __attribute__ (( packed ));
52
53 /**
54 * Process einfo file
55 *
56 * @v infile Filename
57 * @v opts Command-line options
58 */
einfo(const char * infile,struct options * opts)59 static void einfo ( const char *infile,
60 struct options *opts __attribute__ (( unused )) ) {
61 int fd;
62 struct stat stat;
63 size_t len;
64 void *start;
65 struct einfo *einfo;
66
67 /* Open einfo file */
68 if ( ( fd = open ( infile, O_RDONLY ) ) < 0 ) {
69 eprintf ( "Cannot open \"%s\": %s\n",
70 infile, strerror ( errno ) );
71 exit ( 1 );
72 }
73
74 /* Get file size */
75 if ( fstat ( fd, &stat ) < 0 ) {
76 eprintf ( "Cannot stat \"%s\": %s\n",
77 infile, strerror ( errno ) );
78 exit ( 1 );
79 }
80 len = stat.st_size;
81
82 if ( len ) {
83
84 /* Map file */
85 if ( ( start = mmap ( NULL, len, PROT_READ, MAP_SHARED,
86 fd, 0 ) ) == MAP_FAILED ) {
87 eprintf ( "Cannot mmap \"%s\": %s\n",
88 infile, strerror ( errno ) );
89 exit ( 1 );
90 }
91
92 /* Iterate over einfo records */
93 for ( einfo = start ; ( ( void * ) einfo ) < ( start + len ) ;
94 einfo = ( ( ( void * ) einfo ) + einfo->size ) ) {
95 printf ( "%08x\t%s\t%d\t%s\n", einfo->error,
96 ( ( ( char * ) einfo ) + einfo->file ),
97 einfo->line,
98 ( ( ( char * ) einfo ) + einfo->desc ) );
99 }
100
101 /* Unmap file */
102 munmap ( start, len );
103 }
104
105 /* Close file */
106 close ( fd );
107 }
108
109 /**
110 * Print help
111 *
112 * @v program_name Program name
113 */
print_help(const char * program_name)114 static void print_help ( const char *program_name ) {
115 eprintf ( "Syntax: %s file1.einfo [file2.einfo...]\n",
116 program_name );
117 }
118
119 /**
120 * Parse command-line options
121 *
122 * @v argc Argument count
123 * @v argv Argument list
124 * @v opts Options structure to populate
125 */
parse_options(const int argc,char ** argv,struct options * opts)126 static int parse_options ( const int argc, char **argv,
127 struct options *opts __attribute__ (( unused )) ) {
128 int c;
129
130 while (1) {
131 int option_index = 0;
132 static struct option long_options[] = {
133 { "help", 0, NULL, 'h' },
134 { 0, 0, 0, 0 }
135 };
136
137 if ( ( c = getopt_long ( argc, argv, "s:h",
138 long_options,
139 &option_index ) ) == -1 ) {
140 break;
141 }
142
143 switch ( c ) {
144 case 'h':
145 print_help ( argv[0] );
146 exit ( 0 );
147 case '?':
148 default:
149 exit ( 2 );
150 }
151 }
152 return optind;
153 }
154
main(int argc,char ** argv)155 int main ( int argc, char **argv ) {
156 struct options opts = {
157 };
158 int infile_index;
159 const char *infile;
160
161 /* Parse command-line arguments */
162 infile_index = parse_options ( argc, argv, &opts );
163 if ( argc <= infile_index ) {
164 print_help ( argv[0] );
165 exit ( 2 );
166 }
167
168 /* Process each einfo file */
169 for ( ; infile_index < argc ; infile_index++ ) {
170 infile = argv[infile_index];
171 einfo ( infile, &opts );
172 }
173
174 return 0;
175 }
176