release: bump release to v3.8
[mit.git] / util.c
blob482363bee5cfb04d0fcc8f5f1f77063fdefe52de
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <stdint.h>
4 #include <string.h>
5 #include <errno.h>
6 #include <elf.h>
7 #include "logging.h"
8 #include "util.h"
11 * Read one logical line from a configuration file.
13 * Line endings may be escaped with backslashes, to form one logical line from
14 * several physical lines. No end of line character(s) are included in the
15 * result.
17 * If linenum is not NULL, it is incremented by the number of physical lines
18 * which have been read.
20 char *getline_wrapped(FILE *file, unsigned int *linenum)
22 int size = 256;
23 int i = 0;
24 char *buf = NOFAIL(malloc(size));
25 for(;;) {
26 int ch = getc_unlocked(file);
28 switch(ch) {
29 case EOF:
30 if (i == 0) {
31 free(buf);
32 return NULL;
34 /* else fall through */
36 case '\n':
37 if (linenum)
38 (*linenum)++;
39 if (i == size)
40 buf = NOFAIL(realloc(buf, size + 1));
41 buf[i] = '\0';
42 return buf;
44 case '\\':
45 ch = getc_unlocked(file);
47 if (ch == '\n') {
48 if (linenum)
49 (*linenum)++;
50 continue;
52 /* else fall through */
54 default:
55 buf[i++] = ch;
57 if (i == size) {
58 size *= 2;
59 buf = NOFAIL(realloc(buf, size));
66 * Convert filename to the module name. Works if filename == modname, too.
68 void filename2modname(char *modname, const char *filename)
70 const char *afterslash;
71 unsigned int i;
73 afterslash = my_basename(filename);
75 /* Convert to underscores, stop at first . */
76 for (i = 0; afterslash[i] && afterslash[i] != '.'; i++) {
77 if (afterslash[i] == '-')
78 modname[i] = '_';
79 else
80 modname[i] = afterslash[i];
82 modname[i] = '\0';
86 * Replace dashes with underscores.
87 * Dashes inside character range patterns (e.g. [0-9]) are left unchanged.
89 char *underscores(char *string)
91 unsigned int i;
93 if (!string)
94 return NULL;
96 for (i = 0; string[i]; i++) {
97 switch (string[i]) {
98 case '-':
99 string[i] = '_';
100 break;
102 case ']':
103 warn("Unmatched bracket in %s\n", string);
104 break;
106 case '[':
107 i += strcspn(&string[i], "]");
108 if (!string[i])
109 warn("Unmatched bracket in %s\n", string);
110 break;
113 return string;
117 * Get the basename in a pathname.
118 * Unlike the standard implementation, this does not copy the string.
120 char *my_basename(const char *path)
122 const char *base = strrchr(path, '/');
123 if (base)
124 return (char *) base + 1;
125 return (char *) path;
129 * Find the next string in an ELF section.
131 const char *next_string(const char *string, unsigned long *secsize)
133 /* Skip non-zero chars */
134 while (string[0]) {
135 string++;
136 if ((*secsize)-- <= 1)
137 return NULL;
140 /* Skip any zero padding. */
141 while (!string[0]) {
142 string++;
143 if ((*secsize)-- <= 1)
144 return NULL;
146 return string;
150 * Get CPU endianness. 0 = unknown, 1 = ELFDATA2LSB = little, 2 = ELFDATA2MSB = big
152 int __attribute__ ((pure)) native_endianness()
154 /* Encoding the endianness enums in a string and then reading that
155 * string as a 32-bit int, returns the correct endianness automagically.
157 return (char) *((uint32_t*)("\1\0\0\2"));
161 * Check ELF file header.
163 int elf_ident(void *file, unsigned long fsize, int *conv)
165 /* "\177ELF" <byte> where byte = 001 for 32-bit, 002 for 64 */
166 unsigned char *ident = file;
168 if (fsize < EI_CLASS || memcmp(file, ELFMAG, SELFMAG) != 0)
169 return -ENOEXEC; /* Not an ELF object */
170 if (ident[EI_DATA] == 0 || ident[EI_DATA] > 2)
171 return -EINVAL; /* Unknown endianness */
173 if (conv != NULL)
174 *conv = native_endianness() != ident[EI_DATA];
175 return ident[EI_CLASS];
178 #define PERBIT(x) x##32
179 #define ElfPERBIT(x) Elf32_##x
180 #define ELFPERBIT(x) ELF32_##x
181 #include "elf_core.c"
183 #undef PERBIT
184 #undef ElfPERBIT
185 #undef ELFPERBIT
186 #define PERBIT(x) x##64
187 #define ElfPERBIT(x) Elf64_##x
188 #define ELFPERBIT(x) ELF64_##x
189 #include "elf_core.c"
191 void *get_section(void *file, unsigned long filesize,
192 const char *secname, unsigned long *secsize)
194 int conv;
196 switch (elf_ident(file, filesize, &conv)) {
197 case ELFCLASS32:
198 return get_section32(file, filesize, secname, secsize, conv);
199 case ELFCLASS64:
200 return get_section64(file, filesize, secname, secsize, conv);
201 default:
202 return NULL;