mirror of
https://github.com/ibm-s390-linux/s390-tools.git
synced 2026-08-05 02:14:52 +00:00
zipl: fix Error when title is not the first field in BLS file
Problem: zipl implementation (specifically the scan code) implicitly assumes that title field is always on the top of BLS file, and this assumption doesn't comply the bootloader standards: https://www.freedesktop.org/wiki/Specifications/BootLoaderSpec/ Solution: Before parsing in-memory BLS entry, rearrange its lines as following: search for a line with keyword "title" and move it to the top. The scan code is invariant against such transform Fixes: https://github.com/ibm-s390-tools/s390-tools/issues/64 Signed-off-by: Stefan Haberland <sth@linux.ibm.com> Signed-off-by: Eduard Shishkin <edward6@linux.ibm.com> Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
This commit is contained in:
committed by
Jan Höppner
parent
36bd05c4ba
commit
301eece09b
@@ -21,6 +21,7 @@
|
||||
#define _GNU_SOURCE
|
||||
#endif
|
||||
|
||||
#include <assert.h>
|
||||
#include <ctype.h>
|
||||
#include <dirent.h>
|
||||
#include <errno.h>
|
||||
@@ -28,6 +29,7 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include <sys/stat.h>
|
||||
|
||||
@@ -730,6 +732,67 @@ scan_bls_field(struct misc_file_buffer *file, struct scan_token* scan,
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* find a line with keyword "title" and move it to the top
|
||||
*/
|
||||
static int sort_bls_fields(struct misc_file_buffer *file, char *filename)
|
||||
{
|
||||
bool is_title = false;
|
||||
size_t title_len = 0;
|
||||
int nr_titles = 0;
|
||||
size_t title_off;
|
||||
char *title;
|
||||
int current;
|
||||
size_t len;
|
||||
|
||||
while (file->length - file->pos > 4 /* for "title" */) {
|
||||
if (strncmp("title", &file->buffer[file->pos], 5) == 0) {
|
||||
is_title = true;
|
||||
nr_titles++;
|
||||
title_off = file->pos;
|
||||
}
|
||||
for (len = 0;; file->pos++, len++) {
|
||||
current = misc_get_char(file, 0);
|
||||
if (current == '\n' || current == EOF)
|
||||
break;
|
||||
}
|
||||
if (is_title == true)
|
||||
title_len = len;
|
||||
if (current == EOF)
|
||||
break;
|
||||
file->pos++;
|
||||
}
|
||||
file->pos = 0;
|
||||
|
||||
if (nr_titles == 0) {
|
||||
error_reason("no title in %s", filename);
|
||||
return -1;
|
||||
}
|
||||
if (nr_titles > 1) {
|
||||
error_reason("more than one title in %s", filename);
|
||||
return -1;
|
||||
}
|
||||
if (title_off == 0)
|
||||
return 0;
|
||||
|
||||
title = misc_malloc(title_len);
|
||||
if (!title)
|
||||
return -1;
|
||||
/*
|
||||
* copy the title field w/o trailing '\n' to the temporary buffer
|
||||
*/
|
||||
memcpy(title, &file->buffer[title_off], title_len);
|
||||
/*
|
||||
* shift preceded memory region w/o trailing '\n' to the right
|
||||
*/
|
||||
assert(file->buffer[title_off - 1] == '\n');
|
||||
memmove(&file->buffer[title_len + 1], &file->buffer[0], title_off - 1);
|
||||
file->buffer[title_len] = '\n';
|
||||
memcpy(&file->buffer[0], title, title_len);
|
||||
|
||||
free(title);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
scan_bls(const char* blsdir, struct scan_token** token, int scan_size)
|
||||
@@ -780,6 +843,10 @@ scan_bls(const char* blsdir, struct scan_token** token, int scan_size)
|
||||
if (rc)
|
||||
goto err;
|
||||
|
||||
rc = sort_bls_fields(&file, filename);
|
||||
if (rc)
|
||||
goto err;
|
||||
|
||||
while ((size_t)file.pos < file.length) {
|
||||
current = misc_get_char(&file, 0);
|
||||
switch (current) {
|
||||
|
||||
Reference in New Issue
Block a user