-
-enum capture_config_section {
- CAPTURE_CONFIG_NO_SECTION,
- CAPTURE_CONFIG_EXCLUSION_SECTION,
- CAPTURE_CONFIG_EXCLUSION_EXCEPTION_SECTION,
- CAPTURE_CONFIG_IGNORE_SECTION,
-};
-
-enum {
- CAPTURE_CONFIG_INVALID_SECTION,
- CAPTURE_CONFIG_CHANGED_SECTION,
- CAPTURE_CONFIG_SAME_SECTION,
-};
-
-static int
-check_config_section(tchar *line, size_t len,
- enum capture_config_section *cur_section)
-{
- while (istspace(*line))
- line++;
-
- if (*line != T('['))
- return CAPTURE_CONFIG_SAME_SECTION;
-
- line++;
- tchar *endbrace = tstrrchr(line, T(']'));
- if (!endbrace)
- return CAPTURE_CONFIG_SAME_SECTION;
-
- if (!tmemcmp(line, T("ExclusionList"), endbrace - line)) {
- *cur_section = CAPTURE_CONFIG_EXCLUSION_SECTION;
- } else if (!tmemcmp(line, T("ExclusionException"), endbrace - line)) {
- *cur_section = CAPTURE_CONFIG_EXCLUSION_EXCEPTION_SECTION;
- } else if (!tmemcmp(line, T("CompressionExclusionList"), endbrace - line)) {
- *cur_section = CAPTURE_CONFIG_IGNORE_SECTION;
- tfputs(T("WARNING: Ignoring [CompressionExclusionList] section "
- "of capture config file\n"),
- stderr);
- } else if (!tmemcmp(line, T("AlignmentList"), endbrace - line)) {
- *cur_section = CAPTURE_CONFIG_IGNORE_SECTION;
- tfputs(T("WARNING: Ignoring [AlignmentList] section "
- "of capture config file\n"),
- stderr);
- } else {
- imagex_error(T("Invalid capture config file section \"%"TS"\""),
- line - 1);
- return CAPTURE_CONFIG_INVALID_SECTION;
- }
- return CAPTURE_CONFIG_CHANGED_SECTION;
-}
-
-
-static bool
-pattern_list_add_pattern(struct wimlib_pattern_list *pat_list,
- tchar *pat)
-{
- if (pat_list->num_pats == pat_list->num_allocated_pats) {
- tchar **pats;
- size_t num_allocated_pats = pat_list->num_pats + 8;
-
- pats = realloc(pat_list->pats,
- num_allocated_pats * sizeof(pat_list->pats[0]));
- if (!pats) {
- imagex_error(T("Out of memory!"));
- return false;
- }
- pat_list->pats = pats;
- pat_list->num_allocated_pats = num_allocated_pats;
- }
- pat_list->pats[pat_list->num_pats++] = pat;
- return true;
-}
-
-static bool
-parse_capture_config_line(tchar *line, size_t len,
- enum capture_config_section *cur_section,
- struct wimlib_capture_config *config)
-{
- tchar *filename;
- int ret;
-
- ret = check_config_section(line, len, cur_section);
- if (ret == CAPTURE_CONFIG_INVALID_SECTION)
- return false;
- if (ret == CAPTURE_CONFIG_CHANGED_SECTION)
- return true;
-
- switch (*cur_section) {
- case CAPTURE_CONFIG_NO_SECTION:
- imagex_error(T("Line \"%"TS"\" is not in a section "
- "(such as [ExclusionList]"), line);
- return false;
- case CAPTURE_CONFIG_EXCLUSION_SECTION:
- if (parse_string(&line, &len, &filename) != PARSE_STRING_SUCCESS)
- return false;
- return pattern_list_add_pattern(&config->exclusion_pats,
- filename);
- case CAPTURE_CONFIG_EXCLUSION_EXCEPTION_SECTION:
- if (parse_string(&line, &len, &filename) != PARSE_STRING_SUCCESS)
- return false;
- return pattern_list_add_pattern(&config->exclusion_exception_pats,
- filename);
- case CAPTURE_CONFIG_IGNORE_SECTION:
- return true;
- }
- return false;
-}
-
-static int
-parse_capture_config(tchar **contents_p, size_t nchars,
- struct wimlib_capture_config *config)
-{
- ssize_t nlines;
- tchar *p;
- size_t i;
- enum capture_config_section cur_section;
-
- memset(config, 0, sizeof(*config));
-
- nlines = text_file_count_lines(contents_p, &nchars);
- if (nlines < 0)
- return -1;
-
- cur_section = CAPTURE_CONFIG_NO_SECTION;
- p = *contents_p;
- for (i = 0; i < nlines; i++) {
- tchar *endp = tmemchr(p, T('\n'), nchars);
- size_t len = endp - p + 1;
- *endp = T('\0');
- if (!is_comment_line(p, len))
- if (!parse_capture_config_line(p, len, &cur_section, config))
- return -1;
- p = endp + 1;
-
- }
- return 0;
-}
-
-/* Reads the contents of a file into memory. */
-static char *
-file_get_contents(const tchar *filename, size_t *len_ret)
-{
- struct stat stbuf;
- void *buf = NULL;
- size_t len;
- FILE *fp;
-
- if (tstat(filename, &stbuf) != 0) {
- imagex_error_with_errno(T("Failed to stat the file \"%"TS"\""), filename);
- goto out;
- }
- len = stbuf.st_size;
-
- fp = tfopen(filename, T("rb"));
- if (!fp) {
- imagex_error_with_errno(T("Failed to open the file \"%"TS"\""), filename);
- goto out;
- }
-
- buf = malloc(len ? len : 1);
- if (!buf) {
- imagex_error(T("Failed to allocate buffer of %zu bytes to hold "
- "contents of file \"%"TS"\""), len, filename);
- goto out_fclose;
- }
- if (fread(buf, 1, len, fp) != len) {
- imagex_error_with_errno(T("Failed to read %zu bytes from the "
- "file \"%"TS"\""), len, filename);
- goto out_free_buf;
- }
- *len_ret = len;
- goto out_fclose;
-out_free_buf:
- free(buf);
- buf = NULL;
-out_fclose:
- fclose(fp);
-out:
- return buf;
-}
-
-/* Read standard input until EOF and return the full contents in a malloc()ed
- * buffer and the number of bytes of data in @len_ret. Returns NULL on read
- * error. */
-static char *
-stdin_get_contents(size_t *len_ret)
-{
- /* stdin can, of course, be a pipe or other non-seekable file, so the
- * total length of the data cannot be pre-determined */
- char *buf = NULL;
- size_t newlen = 1024;
- size_t pos = 0;
- size_t inc = 1024;
- for (;;) {
- char *p = realloc(buf, newlen);
- size_t bytes_read, bytes_to_read;
- if (!p) {
- imagex_error(T("out of memory while reading stdin"));
- break;
- }
- buf = p;
- bytes_to_read = newlen - pos;
- bytes_read = fread(&buf[pos], 1, bytes_to_read, stdin);
- pos += bytes_read;
- if (bytes_read != bytes_to_read) {
- if (feof(stdin)) {
- *len_ret = pos;
- return buf;
- } else {
- imagex_error_with_errno(T("error reading stdin"));
- break;
- }
- }
- newlen += inc;
- inc *= 3;
- inc /= 2;
- }
- free(buf);
- return NULL;
-}
-
-
-static tchar *
-translate_text_to_tstr(char *text, size_t num_bytes, size_t *num_tchars_ret)
-{
-#ifndef __WIN32__
- /* On non-Windows, assume an ASCII-compatible encoding, such as UTF-8.
- * */
- *num_tchars_ret = num_bytes;
- return text;
-#else /* !__WIN32__ */
- /* On Windows, translate the text to UTF-16LE */
- wchar_t *text_wstr;
- size_t num_wchars;
-
- if (num_bytes >= 2 &&
- (((unsigned char)text[0] == 0xff && (unsigned char)text[1] == 0xfe) ||
- ((unsigned char)text[0] <= 0x7f && (unsigned char)text[1] == 0x00)))
- {
- /* File begins with 0xfeff, the BOM for UTF-16LE, or it begins
- * with something that looks like an ASCII character encoded as
- * a UTF-16LE code unit. Assume the file is encoded as
- * UTF-16LE. This is not a 100% reliable check. */
- num_wchars = num_bytes / 2;
- text_wstr = (wchar_t*)text;
- } else {
- /* File does not look like UTF-16LE. Assume it is encoded in
- * the current Windows code page. I think these are always
- * ASCII-compatible, so any so-called "plain-text" (ASCII) files
- * should work as expected. */
- text_wstr = win32_mbs_to_wcs(text,
- num_bytes,
- &num_wchars);
- free(text);
- }
- *num_tchars_ret = num_wchars;
- return text_wstr;
-#endif /* __WIN32__ */
-}
-
-static tchar *
-file_get_text_contents(const tchar *filename, size_t *num_tchars_ret)
-{
- char *contents;
- size_t num_bytes;
-
- contents = file_get_contents(filename, &num_bytes);
- if (!contents)
- return NULL;
- return translate_text_to_tstr(contents, num_bytes, num_tchars_ret);
-}
-
-static tchar *
-stdin_get_text_contents(size_t *num_tchars_ret)
-{
- char *contents;
- size_t num_bytes;
-
- contents = stdin_get_contents(&num_bytes);
- if (!contents)
- return NULL;
- return translate_text_to_tstr(contents, num_bytes, num_tchars_ret);
-}
-