4 * Utility function for reading path list files.
8 * Copyright (C) 2013 Eric Biggers
10 * This file is part of wimlib, a library for working with WIM files.
12 * wimlib is free software; you can redistribute it and/or modify it under the
13 * terms of the GNU General Public License as published by the Free
14 * Software Foundation; either version 3 of the License, or (at your option)
17 * wimlib is distributed in the hope that it will be useful, but WITHOUT ANY
18 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
19 * A PARTICULAR PURPOSE. See the GNU General Public License for more
22 * You should have received a copy of the GNU General Public License
23 * along with wimlib; if not, see http://www.gnu.org/licenses/.
30 #include "wimlib/encoding.h"
31 #include "wimlib/error.h"
32 #include "wimlib/file_io.h"
33 #include "wimlib/pathlist.h"
34 #include "wimlib/util.h"
44 read_file_contents(const tchar *path, char **buf_ret, size_t *bufsize_ret)
53 raw_fd = topen(path, O_RDONLY | O_BINARY);
55 ERROR_WITH_ERRNO("Can't open \"%"TS"\"", path);
56 return WIMLIB_ERR_OPEN;
58 if (fstat(raw_fd, &st)) {
59 ERROR_WITH_ERRNO("Can't stat \"%"TS"\"", path);
61 return WIMLIB_ERR_STAT;
63 if ((size_t)st.st_size != st.st_size ||
64 (buf = MALLOC(st.st_size)) == NULL)
67 ERROR("Not enough memory to read \"%"TS"\"", path);
68 return WIMLIB_ERR_NOMEM;
71 filedes_init(&fd, raw_fd);
72 ret = full_read(&fd, buf, st.st_size);
77 ERROR_WITH_ERRNO("Error reading \"%"TS"\"", path);
83 *bufsize_ret = st.st_size;
88 read_utf8_file_contents(const tchar *path, tchar **buf_ret, size_t *buflen_ret)
97 ret = read_file_contents(path, &buf_utf8, &bufsize_utf8);
101 /* Ignore UTF-8 BOM. */
102 if (bufsize_utf8 >= 3 && (u8)buf_utf8[0] == 0xef &&
103 (u8)buf_utf8[1] == 0xbb && (u8)buf_utf8[2] == 0xbf)
108 ret = utf8_to_tstr(buf_utf8 + offset_utf8, bufsize_utf8 - offset_utf8,
109 &buf_tstr, &bufsize_tstr);
115 *buflen_ret = bufsize_tstr / sizeof(tchar);
120 parse_path_list_file(tchar *buf, size_t buflen,
121 tchar ***paths_ret, size_t *num_paths_ret)
123 tchar **paths = NULL;
124 size_t num_paths = 0;
125 size_t num_alloc_paths = 0;
129 for (p = buf; p != buf + buflen; p = nl + 1) {
130 tchar *line_begin, *line_end;
133 nl = tmemchr(p, T('\n'), buf + buflen - p);
140 /* Ignore leading whitespace. */
141 while (line_begin < nl && istspace(*line_begin))
144 /* Ignore trailing whitespace. */
145 while (line_end > line_begin && istspace(*(line_end - 1)))
148 line_len = line_end - line_begin;
150 /* Ignore comments and empty lines. */
151 if (line_len == 0 || *line_begin == T(';'))
154 if (num_paths == num_alloc_paths) {
156 size_t new_num_alloc_paths = max(num_alloc_paths + 8,
157 num_alloc_paths * 3 / 2);
159 new_paths = REALLOC(paths, new_num_alloc_paths *
161 if (new_paths == NULL)
164 num_alloc_paths = new_num_alloc_paths;
168 paths[num_paths++] = line_begin;
172 *num_paths_ret = num_paths;
177 return WIMLIB_ERR_NOMEM;
181 read_path_list_file(const tchar *listfile,
182 tchar ***paths_ret, size_t *num_paths_ret,
189 ret = read_utf8_file_contents(listfile, &buf, &buflen);
193 buf[buflen++] = T('\n');
195 ret = parse_path_list_file(buf, buflen, paths_ret, num_paths_ret);