]> git.proxmox.com Git - efi-boot-shim.git/blame - csv.c
Force usage of newest revocations at build time
[efi-boot-shim.git] / csv.c
CommitLineData
031e5cce
SM
1// SPDX-License-Identifier: BSD-2-Clause-Patent
2/*
3 * csv.c - CSV parser
4 */
5
6#include "shim.h"
7
8void NONNULL(1, 3, 4)
9parse_csv_line(char * line, size_t max, size_t *n_columns, const char *columns[])
10{
11 char *next = line;
12 size_t n = 0, new_n = n;
13 const char * const delims = ",";
14 char state = 0;
15 char *token = NULL;
16
17 bool valid = true;
8529e0f7 18
031e5cce
SM
19 for (n = 0; n < *n_columns; n++) {
20
21 if (valid) {
22 valid = strntoken(next, max, delims, &token, &state);
23 }
24 if (valid) {
25 next += strlen(token) + 1;
26 max -= strlen(token) + 1;
27 columns[n] = token;
28 new_n = n + 1;
29 } else {
30 columns[n] = NULL;
31 continue;
32 }
33 }
34 *n_columns = new_n;
35}
36
37void
38free_csv_list(list_t *list)
39{
40 list_t *pos = NULL, *tmp = NULL;
41 list_for_each_safe(pos, tmp, list) {
42 struct csv_row *row;
43
44 row = list_entry(pos, struct csv_row, list);
45 list_del(&row->list);
46 FreePool(row);
47 }
48}
49
50EFI_STATUS
51parse_csv_data(char *data, char *data_end, size_t n_columns, list_t *list)
52{
53 EFI_STATUS efi_status = EFI_OUT_OF_RESOURCES;
54 char delims[] = "\r\n";
55 char *line = data;
56 size_t max = 0;
57 char *end = data_end;
58
8119f718
SM
59 if (!data || !end || end <= data || !n_columns || !list) {
60 dprint(L"data:0x%lx end:0x%lx n_columns:%lu list:0x%lx\n",
61 data, end, n_columns, list);
031e5cce 62 return EFI_INVALID_PARAMETER;
8119f718 63 }
031e5cce
SM
64
65 max = (uintptr_t)end - (uintptr_t)line + (end > line ? 1 : 0);
8529e0f7 66 if (is_utf8_bom(line, max))
031e5cce 67
031e5cce
SM
68 line += UTF8_BOM_SIZE;
69
8529e0f7 70 while (line <= data_end && *line) {
031e5cce
SM
71 size_t entrysz = sizeof(char *) * n_columns + sizeof(struct csv_row);
72 struct csv_row *entry;
73 size_t m_columns = n_columns;
74 char *delim;
75 bool found = true;
8529e0f7 76 bool eof = false;
031e5cce
SM
77
78 end = data_end;
79 max = (uintptr_t)end - (uintptr_t)line + (end > line ? 1 : 0);
8529e0f7 80 /* Skip the delimiter(s) of the previous line */
031e5cce
SM
81 while (max && found) {
82 found = false;
83 for (delim = &delims[0]; max && *delim; delim++) {
84 if (line[0] == *delim) {
85 line++;
86 max--;
87 found = true;
88 }
89 }
90 }
8529e0f7 91 /* Find the first delimiter of the current line */
031e5cce
SM
92 for (delim = &delims[0]; *delim; delim++) {
93 char *tmp = strnchrnul(line, max, *delim);
94 if (tmp < end)
95 end = tmp;
96 }
97 max = (uintptr_t)end - (uintptr_t)line + (end > line ? 1 : 0);
8529e0f7
SM
98
99 if (!*end)
100 eof = true;
031e5cce
SM
101 *end = '\0';
102
103 if (line == data_end || max == 0) {
104 line = end + 1;
105 continue;
106 }
107
108 entry = AllocateZeroPool(entrysz);
109 if (!entry) {
110 efi_status = EFI_OUT_OF_RESOURCES;
111 goto err_oom;
112 }
113
114 INIT_LIST_HEAD(&entry->list);
115 list_add_tail(&entry->list, list);
116
117 for (delim = &delims[0]; *delim; delim++) {
118 char *tmp = strnchrnul((const char *)line, max, *delim);
119 if (tmp < end)
120 end = tmp;
121 }
122
123 parse_csv_line(line, max, &m_columns, (const char **)entry->columns);
124 entry->n_columns = m_columns;
8529e0f7
SM
125 if (eof)
126 break;
127
031e5cce
SM
128 line = end + 1;
129 }
130
131 return EFI_SUCCESS;
132err_oom:
133 free_csv_list(list);
134 return efi_status;
135}
136
137// vim:fenc=utf-8:tw=75:noet