existing integrity tables. This can be useful to avoid unwanted
verification of large WIM files, e.g. WIMs given by '--delta-from'.
+ 'wimextract' now reads a pathlist file from standard input when "@-" is
+ given as an argument.
+
wimsplit (API: wimlib_split()) now correctly handles a dot in the path
to the first split WIM part, prior to the filename extension.
not begin with the '@' character, or a \fILISTFILE\fR if it does. Each
\fIPATH\fR specifies a file or directory tree within the WIM image to extract,
whereas each \fILISTFILE\fR specifies a file that itself contains a list of
-paths to extract. See \fBPATHS AND LISTFILES\fR for more details.
+paths to extract. If a \fILISTFILE\fR is "-" (i.e. the whole argument is "@-"),
+then the listfile is read from standard input. See \fBPATHS AND LISTFILES\fR
+for more details.
.PP
By default, files and directories are extracted to the current directory. Use
\fB--dest-dir\fR to select a different destination directory. Alternatively,
* are otherwise delimited by the newline character. However, quotes will be
* stripped if present.
*
+ * If @p path_list_file is @c NULL, then the pathlist file is read from standard
+ * input.
+ *
* The error codes are the same as those returned by wimlib_extract_paths(),
* except that wimlib_extract_pathlist() returns an appropriate error code if it
* cannot read the path list file (e.g. ::WIMLIB_ERR_OPEN, ::WIMLIB_ERR_STAT,
#define LOAD_TEXT_FILE_REMOVE_QUOTES 0x00000001
#define LOAD_TEXT_FILE_NO_WARNINGS 0x00000002
+#define LOAD_TEXT_FILE_ALLOW_STDIN 0x00000004
extern int
-do_load_text_file(const tchar *path,
- const void *buf, size_t bufsize, void **mem_ret,
- const struct text_file_section *pos_sections,
- int num_pos_sections, int flags,
- line_mangle_t mangle_line);
-
-static inline int
-load_text_file(const tchar *path, void **mem_ret,
+load_text_file(const tchar *path, const void *buf, size_t bufsize,
+ void **mem_ret,
const struct text_file_section *pos_sections,
- int num_pos_sections, line_mangle_t mangle_line)
-{
- return do_load_text_file(path, NULL, 0, mem_ret,
- pos_sections, num_pos_sections,
- LOAD_TEXT_FILE_REMOVE_QUOTES, mangle_line);
-}
+ int num_pos_sections,
+ int flags, line_mangle_t mangle_line);
#endif /* _WIMLIB_TEXTFILE_H_ */
argc -= num_paths;
argv += num_paths;
} else {
+ const tchar *listfile = argv[0] + 1;
+
+ if (!tstrcmp(listfile, T("-"))) {
+ tputs(T("Reading pathlist file from standard input..."));
+ listfile = NULL;
+ }
+
ret = wimlib_extract_pathlist(wim, image, dest_dir,
- argv[0] + 1,
- extract_flags);
+ listfile, extract_flags);
argc--;
argv++;
}
ret = read_path_list_file(path_list_file, &paths, &num_paths, &mem);
if (ret) {
ERROR("Failed to read path list file \"%"TS"\"",
- path_list_file);
+ path_list_file ? path_list_file : T("<stdin>"));
return ret;
}
void *buf;
int ret;
- ret = load_text_file(listfile, &buf, &tmp, 1, NULL);
+ ret = load_text_file(listfile, NULL, 0, &buf, &tmp, 1,
+ LOAD_TEXT_FILE_REMOVE_QUOTES |
+ LOAD_TEXT_FILE_ALLOW_STDIN, NULL);
if (ret)
return ret;
};
void *mem;
- ret = do_load_text_file(config_file, buf, bufsize, &mem,
- sections, ARRAY_LEN(sections),
- LOAD_TEXT_FILE_REMOVE_QUOTES, mangle_pat);
+ ret = load_text_file(config_file, buf, bufsize, &mem,
+ sections, ARRAY_LEN(sections),
+ LOAD_TEXT_FILE_REMOVE_QUOTES, mangle_pat);
if (ret) {
ERROR("Failed to load capture configuration file \"%"TS"\"",
config_file);
#include "wimlib/textfile.h"
#include "wimlib/util.h"
+static int
+stdin_get_contents(void **buf_ret, size_t *bufsize_ret)
+{
+ char *buf = NULL;
+ size_t filled = 0;
+ size_t capacity = 0;
+
+ do {
+ size_t new_capacity = (capacity * 2) + 256;
+ char *new_buf;
+
+ if (new_capacity <= capacity ||
+ !(new_buf = REALLOC(buf, new_capacity))) {
+ ERROR("Too much data sent on stdin!");
+ FREE(buf);
+ return WIMLIB_ERR_INVALID_PARAM;
+ }
+ buf = new_buf;
+ capacity = new_capacity;
+ filled += fread(&buf[filled], 1, capacity - filled, stdin);
+ } while (filled == capacity);
+
+ if (!feof(stdin)) {
+ ERROR_WITH_ERRNO("Error reading stdin");
+ FREE(buf);
+ return WIMLIB_ERR_READ;
+ }
+ *buf_ret = buf;
+ *bufsize_ret = filled;
+ return 0;
+}
+
static int
read_file_contents(const tchar *path, void **buf_ret, size_t *bufsize_ret)
{
int ret;
int errno_save;
- if (!path || !*path)
- return WIMLIB_ERR_INVALID_PARAM;
-
raw_fd = topen(path, O_RDONLY | O_BINARY);
if (raw_fd < 0) {
ERROR_WITH_ERRNO("Can't open \"%"TS"\"", path);
}
/**
- * do_load_text_file -
+ * load_text_file -
*
- * Read and parse lines from a text file from an on-disk file or a buffer.
- * The file may contain sections, like in an INI file.
+ * Read and parse lines from a text file given as an on-disk file, standard
+ * input, or a buffer. The file may contain sections, like in an INI file.
*
* @path
- * Path to the file on disk to read, or a dummy name for the buffer.
+ * If @buf is NULL, then either the path to the file on-disk to read, or
+ * NULL to read from standard input. Else, a dummy name for the buffer.
* @buf
* If NULL, the data will be read from the @path file. Otherwise the data
* will be read from this buffer.
* @num_pos_sections
* Number of entries in the @pos_sections array.
* @flags
- * Flags: LOAD_TEXT_FILE_REMOVE_QUOTES, LOAD_TEXT_FILE_NO_WARNINGS.
+ * Flags: LOAD_TEXT_FILE_* flags.
* @mangle_line
* Optional callback to validate and/or modify each line being read.
*
* LOAD_TEXT_FILE_NO_WARNINGS is specified.
*/
int
-do_load_text_file(const tchar *path,
- const void *buf, size_t bufsize,
- void **mem_ret,
- const struct text_file_section *pos_sections,
- int num_pos_sections,
- int flags,
- line_mangle_t mangle_line)
+load_text_file(const tchar *path, const void *buf, size_t bufsize,
+ void **mem_ret,
+ const struct text_file_section *pos_sections,
+ int num_pos_sections,
+ int flags, line_mangle_t mangle_line)
{
int ret;
- bool pathmode = (buf == NULL);
+ bool is_filemode = (buf == NULL);
+ bool is_stdin = (is_filemode && path == NULL);
tchar *tstr;
size_t tstr_nchars;
- if (pathmode) {
- ret = read_file_contents(path, (void **)&buf, &bufsize);
+ if (is_stdin && !(flags & LOAD_TEXT_FILE_ALLOW_STDIN))
+ return WIMLIB_ERR_INVALID_PARAM;
+
+ if (is_filemode) {
+ if (is_stdin)
+ ret = stdin_get_contents((void **)&buf, &bufsize);
+ else
+ ret = read_file_contents(path, (void **)&buf, &bufsize);
if (ret)
return ret;
}
ret = translate_text_buffer(buf, bufsize, &tstr, &tstr_nchars);
- if (pathmode)
+ if (is_filemode)
FREE((void *)buf);
if (ret)
return ret;
tstr[tstr_nchars++] = T('\n');
- ret = parse_text_file(path, tstr, tstr_nchars, pos_sections,
+ ret = parse_text_file(is_stdin ? T("<stdin>") : path,
+ tstr, tstr_nchars, pos_sections,
num_pos_sections, flags, mangle_line);
if (ret) {
for (int i = 0; i < num_pos_sections; i++)
sec.name = T("PrepopulateList");
sec.strings = strings;
- ret = do_load_text_file(path, buf, blob->size, &mem, &sec, 1,
- LOAD_TEXT_FILE_REMOVE_QUOTES |
- LOAD_TEXT_FILE_NO_WARNINGS,
- mangle_pat);
+ ret = load_text_file(path, buf, blob->size, &mem, &sec, 1,
+ LOAD_TEXT_FILE_REMOVE_QUOTES |
+ LOAD_TEXT_FILE_NO_WARNINGS,
+ mangle_pat);
STATIC_ASSERT(OS_PREFERRED_PATH_SEPARATOR == WIM_PATH_SEPARATOR);
FREE(buf);
if (ret) {
../tree-cmp hello2 out.dir/hello2
[ ! -e out.dir/otherfile ]
+msg "Testing path list extract (stdin)"
+rm -rf out.dir
+wimextract test.wim 1 @- --dest-dir=out.dir << EOF
+hello1
+hello2
+EOF
+../tree-cmp hello1 out.dir/hello1
+../tree-cmp hello2 out.dir/hello2
+[ ! -e out.dir/otherfile ]
+
msg "Testing path list extract (w/ wildcard)"
cat > pathlist << EOF
hello*