1 |
#define _GNU_SOURCE |
2 |
|
3 |
#include <stdlib.h> |
4 |
#include <string.h> |
5 |
#include <ctype.h> |
6 |
#include <unistd.h> |
7 |
#include <sys/types.h> |
8 |
#include <fnmatch.h> |
9 |
|
10 |
#include "fileutil.h" |
11 |
#include "ImageMapFile.h" |
12 |
|
13 |
#define WHITESPACE_CHARS " \t\n" |
14 |
#define QUOTING_CHARS "\"" |
15 |
#define ESCAPING_CHARS "\\" |
16 |
#define COMMENT_CHARS "#" |
17 |
#define WILD_CHARS '*' |
18 |
#define DIGIT_CHARS "0123456789" |
19 |
#define USERID_SEP_CHARS "," |
20 |
#define USERID_TERMINATOR_CHARS USERID_SEP_CHARS WHITESPACE_CHARS |
21 |
#define NUL '\0' |
22 |
#define USERID_CHUNK_SIZE 4 |
23 |
|
24 |
|
25 |
/****************************************************************************** |
26 |
Function: gridmap_parse_line |
27 |
Description: |
28 |
Given a line from the gridmap file, parse it returning |
29 |
a gridmap_line_t structure. line is modified during parsing. |
30 |
|
31 |
The format of the line is expected to be: |
32 |
|
33 |
<DN> <userid>[,<userid>[,<userid>...]] |
34 |
|
35 |
Leading and trailing whitespace is ignored. |
36 |
|
37 |
userids must only have a comma between them, no whitespace. |
38 |
|
39 |
Anything after the userids is ignored. |
40 |
|
41 |
Anything after an unescaped comment character is ignored. |
42 |
|
43 |
Parameters: |
44 |
line, a pointer to the line from the file (NUL-terminated string) |
45 |
|
46 |
gline, a pointer to a pointer that will be set to point at |
47 |
the gridmap_line_t structure containing the line information. |
48 |
If the line contains no content, gline will be set to NULL. |
49 |
|
50 |
Returns: |
51 |
0 on success, non-zero on error. |
52 |
|
53 |
******************************************************************************/ |
54 |
static int gridmap_parse_line(char * line, gridmap_line_t ** gline); |
55 |
static int xdigit_to_value(char xdigit); |
56 |
static int gridmap_parse_globusid(const char * unparsed, char ** pparsed); |
57 |
static void gridmap_free_gridmap_line(gridmap_line_t *gline); |
58 |
static int match_dn(const char * dn, const char * match, unsigned short matching_type); |
59 |
|
60 |
static int match_dn(const char * match, const char * to_match, unsigned short matching_type) { |
61 |
if ( (matching_type&MATCH_WILD_CHARS) == MATCH_WILD_CHARS ){ |
62 |
return fnmatch(match, to_match, 0); |
63 |
} else { |
64 |
return strcmp(match, to_match); |
65 |
} |
66 |
} |
67 |
|
68 |
gridmap_line_t * find_mapping(const gridmap_list_t * list, const char * to_match, unsigned short matching_type) { |
69 |
const gridmap_list_t * current = list; |
70 |
while (current != NULL){ |
71 |
if (match_dn(current->line->match,to_match,matching_type) == 0) |
72 |
return current->line; |
73 |
current = current->next; |
74 |
if (current == list) |
75 |
break; |
76 |
} |
77 |
return NULL; |
78 |
} |
79 |
|
80 |
void gridmap_list_free(gridmap_list_t * list){ |
81 |
gridmap_list_t * current = list; |
82 |
gridmap_list_t * working = NULL; |
83 |
while (current != NULL){ |
84 |
working = current; |
85 |
current = current->next; |
86 |
|
87 |
gridmap_free_gridmap_line(working->line); |
88 |
free(working); |
89 |
} |
90 |
} |
91 |
|
92 |
int parseImageMapFile(const char * image_map_file, gridmap_list_t ** list){ |
93 |
gridmap_list_t * result = NULL; |
94 |
gridmap_list_t * resultlast = NULL; |
95 |
gridmap_list_t * resultnew = NULL; |
96 |
gridmap_line_t * gline = NULL; |
97 |
char * contents = NULL; |
98 |
char * linestart = NULL; |
99 |
char * lineend = NULL; |
100 |
int eof = 0; |
101 |
int size; |
102 |
|
103 |
size = cgul_read_config(image_map_file, &contents, getuid(), getgid()); |
104 |
if (size != 0){ |
105 |
/*EEF_log(LOG_ERR,"Unable to safely open the image map file '%s', reason: %d (for an explenation of the reason look in cgul/fileutil/fileutil.h)",image_map_file,size);*/ |
106 |
goto failure; |
107 |
} |
108 |
|
109 |
linestart = contents; |
110 |
while (eof == 0){ |
111 |
lineend = linestart; |
112 |
while (*lineend != '\n'){ |
113 |
if (*lineend == '\0'){ |
114 |
eof = 1; |
115 |
break; |
116 |
} |
117 |
lineend++; |
118 |
} |
119 |
*lineend = '\0'; |
120 |
|
121 |
size = gridmap_parse_line(linestart, &gline); |
122 |
linestart = lineend+1; |
123 |
|
124 |
/* error which is unrecoverable only will result in a non 0 value */ |
125 |
if (size != 0) { |
126 |
goto failure; |
127 |
} |
128 |
|
129 |
/* line consisting of comment or whitespaces only */ |
130 |
if (gline == NULL) |
131 |
continue; |
132 |
|
133 |
resultnew = calloc(1,sizeof(gridmap_list_t)); |
134 |
resultnew->line = gline; |
135 |
|
136 |
if (result == NULL){ |
137 |
resultlast = result = resultnew; |
138 |
} else { |
139 |
resultlast->next = resultnew; |
140 |
resultlast = resultnew; |
141 |
} |
142 |
/* be sure to point the last result to the actual last result in the list */ |
143 |
while (resultlast->next != NULL) |
144 |
resultlast = resultlast->next; |
145 |
|
146 |
gline = NULL; |
147 |
resultnew = NULL; |
148 |
} |
149 |
|
150 |
*list = result; |
151 |
|
152 |
return 0; |
153 |
failure: |
154 |
gridmap_free_gridmap_line(gline); |
155 |
gline = NULL; |
156 |
|
157 |
free(contents); |
158 |
contents = NULL; |
159 |
|
160 |
gridmap_list_free(result); |
161 |
result = NULL; |
162 |
resultlast = NULL; |
163 |
|
164 |
return -1; |
165 |
} |
166 |
|
167 |
static int gridmap_parse_line(char * line, gridmap_line_t ** gline) { |
168 |
charlist_t * mappings = NULL; |
169 |
charlist_t * mappingsnew = NULL; |
170 |
char * dn_end; |
171 |
char * parsed_dn = NULL; |
172 |
gridmap_line_t * gline_tmp = NULL; |
173 |
|
174 |
|
175 |
/* Check arguments */ |
176 |
if ((line == NULL) || (gline == NULL)) |
177 |
goto error; |
178 |
|
179 |
/* Skip over leading whitespace */ |
180 |
line += strspn(line, WHITESPACE_CHARS); |
181 |
|
182 |
/* Check for comment at start of line and ignore line if present */ |
183 |
if (strchr(COMMENT_CHARS, *line) != NULL) { |
184 |
/* Ignore line, return NULL gline */ |
185 |
*gline = NULL; |
186 |
return 0; |
187 |
} |
188 |
|
189 |
/* Check for empty line */ |
190 |
if (*line == NUL) { |
191 |
/* Empty line, return NULL gline. */ |
192 |
*gline = NULL; |
193 |
return 0; |
194 |
} |
195 |
|
196 |
/* Is DN quoted? */ |
197 |
if (strchr(QUOTING_CHARS, *line) != NULL) { |
198 |
/* |
199 |
* Yes, skip over opening quote and look for unescaped |
200 |
* closing double quote |
201 |
*/ |
202 |
line++; |
203 |
dn_end = line; |
204 |
while (strchr(QUOTING_CHARS, *dn_end) == NULL){ |
205 |
if (strchr(ESCAPING_CHARS, *dn_end) != NULL) |
206 |
dn_end++; |
207 |
if (*dn_end == 0) |
208 |
goto error; |
209 |
dn_end++; |
210 |
} |
211 |
} else { |
212 |
/* No, just find next whitespace */ |
213 |
dn_end = line + strcspn(line, WHITESPACE_CHARS); |
214 |
|
215 |
if (*dn_end == NUL) |
216 |
goto error; /* Nothing after DN */ |
217 |
} |
218 |
|
219 |
/* NUL terminate DN and parse */ |
220 |
*dn_end = NUL; |
221 |
|
222 |
if (gridmap_parse_globusid(line, &parsed_dn) != 0) |
223 |
return -1; |
224 |
|
225 |
/* Skip over closing delim and any whitespace after DN */ |
226 |
line = dn_end + 1; |
227 |
line += strspn(line, WHITESPACE_CHARS); |
228 |
|
229 |
/* Parse list of unix user ID seperated by USERID_SEP_CHARS */ |
230 |
while ((*line != NUL) && (strchr(WHITESPACE_CHARS, *line) == NULL)) { |
231 |
int mapping_len; |
232 |
char * mapping; |
233 |
|
234 |
/* Find end of this userid */ |
235 |
mapping_len = strcspn(line, USERID_TERMINATOR_CHARS); |
236 |
|
237 |
mapping = strndup(line,mapping_len); |
238 |
if (mapping == NULL) |
239 |
goto error; |
240 |
|
241 |
mappingsnew = charlist_add_char_ptr_own(mappings, mapping); |
242 |
/* test for the memory beeing available */ |
243 |
if (mappingsnew == NULL){ |
244 |
/* free the local char ptr */ |
245 |
free(mapping); |
246 |
|
247 |
goto error; |
248 |
} |
249 |
|
250 |
mappings = mappingsnew; |
251 |
|
252 |
line += mapping_len; |
253 |
|
254 |
/* If we're on a seperator character, skip over it */ |
255 |
if (strchr(USERID_SEP_CHARS, *line) != NULL) |
256 |
line++; |
257 |
} |
258 |
|
259 |
/* |
260 |
* There might be more stuff on the line, but we're ignoring |
261 |
* it for now. |
262 |
*/ |
263 |
|
264 |
/* Ok, build our gridmap_line_t structure */ |
265 |
gline_tmp = malloc(sizeof(*gline_tmp)); |
266 |
|
267 |
if (gline_tmp == NULL) |
268 |
goto error; |
269 |
|
270 |
gline_tmp->match = parsed_dn; |
271 |
gline_tmp->mappings = mappings; |
272 |
|
273 |
*gline = gline_tmp; |
274 |
|
275 |
return 0; |
276 |
|
277 |
error: |
278 |
free(parsed_dn); |
279 |
parsed_dn = NULL; |
280 |
|
281 |
charlist_free(mappings); |
282 |
|
283 |
free(gline_tmp); |
284 |
|
285 |
return -1; |
286 |
|
287 |
} /* gridmap_parse_line() */ |
288 |
|
289 |
/****************************************************************************** |
290 |
Function: gridmap_parse_globusid |
291 |
Description: |
292 |
Given a pointer to a string containing the globusid from the |
293 |
gridmap file, return a pointer to a string containing the |
294 |
parsed from of the id. |
295 |
|
296 |
Specifically handle backslashed characters - e.g. '\\', |
297 |
'\x4a' or '\37'. |
298 |
|
299 |
Parameters: |
300 |
unparsed, pointer to unparsed string |
301 |
|
302 |
pparsed, pointer to pointer that should be set to point at |
303 |
allocated parsed string |
304 |
|
305 |
Returns: |
306 |
0 on success |
307 |
non-zero on error. |
308 |
|
309 |
******************************************************************************/ |
310 |
static int gridmap_parse_globusid(const char * unparsed, char ** pparsed) { |
311 |
int escaped = 0; /* Is the current character escaped? (Previous char was backslash) */ |
312 |
char * buffer = NULL; /* Buffer we are putting resulting name into */ |
313 |
int buffer_len = 0; /* Buffer's length in bytes */ |
314 |
int buffer_index = 0; /* And our current position in buffer */ |
315 |
char unparsed_char; /* Character we're currently looking at */ |
316 |
|
317 |
|
318 |
/* Check input parameters for legality */ |
319 |
if ((unparsed == NULL) || (pparsed == NULL)) |
320 |
return -1; |
321 |
|
322 |
buffer_len = strlen(unparsed); |
323 |
buffer = malloc(buffer_len); |
324 |
if (buffer == NULL) |
325 |
return -1; |
326 |
|
327 |
/* Walk through the name, parsing as we go */ |
328 |
while ((unparsed_char = *(unparsed++)) != NUL){ |
329 |
/* Unescaped backslash */ |
330 |
if (strchr(ESCAPING_CHARS, unparsed_char) && !escaped) { |
331 |
escaped = 1; |
332 |
continue; |
333 |
} |
334 |
|
335 |
/* Escaped hex character - e.g. '\xfe' */ |
336 |
if ((unparsed_char == 'x') && escaped) { |
337 |
if (isxdigit(*unparsed) && isxdigit(*(unparsed + 1))) { |
338 |
/* Set unparsed_char to value represented by hex value */ |
339 |
unparsed_char = (xdigit_to_value(*unparsed) << 4) + xdigit_to_value(*(unparsed + 1)); |
340 |
unparsed += 2; |
341 |
} |
342 |
/* else just fall through */ |
343 |
} |
344 |
|
345 |
/* |
346 |
* Ok, we now have the character in unparsed_char to be appended |
347 |
* to our output string. |
348 |
* |
349 |
* First, make sure we have enough room in our output buffer. |
350 |
*/ |
351 |
if ((buffer_index + 1 /* for NUL */) >= buffer_len) { |
352 |
/* Grow buffer */ |
353 |
char *tmp_buffer; |
354 |
buffer_len *= 2; |
355 |
tmp_buffer = realloc(buffer, buffer_len); |
356 |
if (tmp_buffer == NULL) { |
357 |
free(buffer); |
358 |
return -1; |
359 |
} |
360 |
buffer = tmp_buffer; |
361 |
} |
362 |
|
363 |
buffer[buffer_index++] = unparsed_char; |
364 |
buffer[buffer_index] = NUL; |
365 |
|
366 |
escaped = 0; |
367 |
} |
368 |
|
369 |
/* XXX What if escaped == 1 here? */ |
370 |
/* Success */ |
371 |
|
372 |
*pparsed = buffer; |
373 |
|
374 |
return 0; |
375 |
|
376 |
} /* gridmap_parse_globusid() */ |
377 |
|
378 |
/****************************************************************************** |
379 |
Function: xdigit_to_value |
380 |
Description: |
381 |
Convert a ascii character representing a hexadecimal digit |
382 |
into a integer. |
383 |
|
384 |
Parameters: |
385 |
xdigit, character contain the hex digit. |
386 |
|
387 |
Returns: |
388 |
value contained in xdigit, or -1 on error. |
389 |
|
390 |
******************************************************************************/ |
391 |
|
392 |
static int xdigit_to_value(char xdigit) { |
393 |
if ((xdigit >= '0') && (xdigit <= '9')) |
394 |
return (xdigit - '0'); |
395 |
if ((xdigit >= 'a') && (xdigit <= 'f')) |
396 |
return (xdigit - 'a' + 0xa); |
397 |
if ((xdigit >= 'A') && (xdigit <= 'F')) |
398 |
return (xdigit - 'A' + 0xa); |
399 |
/* Illegal digit */ |
400 |
return -1; |
401 |
} /* xdigit_to_value() */ |
402 |
|
403 |
/****************************************************************************** |
404 |
Function: gridmap_free_gridmap_line |
405 |
Description: |
406 |
Frees all memory allocated to a gridmap_line_t structure. |
407 |
|
408 |
Parameters: |
409 |
gline, pointer to structure to be freed. |
410 |
|
411 |
Returns: |
412 |
Nothing. |
413 |
******************************************************************************/ |
414 |
static void gridmap_free_gridmap_line(gridmap_line_t *gline) { |
415 |
if (gline == NULL) |
416 |
return; |
417 |
|
418 |
free(gline->match); |
419 |
gline->match = NULL; |
420 |
|
421 |
charlist_free(gline->mappings); |
422 |
gline->mappings = NULL; |
423 |
|
424 |
free(gline); |
425 |
} /* gridmap_free_gridmap_line() */ |
426 |
|