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