*/
/*
- * Copyright (C) 2012-2023 Eric Biggers
+ * Copyright 2012-2023 Eric Biggers
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#ifdef HAVE_CONFIG_H
static const struct option update_options[] = {
/* Careful: some of the options here set the defaults for update
* commands, but the flags given to an actual update command (and not to
- * `imagex update' itself are also handled in
- * update_command_add_option(). */
+ * wimupdate itself) are also handled in update_command_add_option(). */
{T("threads"), required_argument, NULL, IMAGEX_THREADS_OPTION},
{T("check"), no_argument, NULL, IMAGEX_CHECK_OPTION},
{T("include-integrity"), no_argument, NULL, IMAGEX_INCLUDE_INTEGRITY_OPTION},
{T("rebuild"), no_argument, NULL, IMAGEX_REBUILD_OPTION},
{T("command"), required_argument, NULL, IMAGEX_COMMAND_OPTION},
{T("wimboot-config"), required_argument, NULL, IMAGEX_WIMBOOT_CONFIG_OPTION},
+ {T("ref"), required_argument, NULL, IMAGEX_REF_OPTION},
/* Default delete options */
{T("force"), no_argument, NULL, IMAGEX_FORCE_OPTION},
return sources;
}
-/* 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);
-}
-
#define TO_PERCENT(numerator, denominator) \
(((denominator) == 0) ? 0 : ((numerator) * 100 / (denominator)))
return recognized;
}
-/* How many nonoption arguments each `imagex update' command expects */
+/* How many nonoption arguments each wimupdate command expects */
static const unsigned update_command_num_nonoptions[] = {
[WIMLIB_UPDATE_OP_ADD] = 2,
[WIMLIB_UPDATE_OP_DELETE] = 1,
}
/*
- * Parse a command passed on stdin to `imagex update'.
+ * Parse a command passed on stdin to wimupdate.
*
* @line: Text of the command.
* @len: Length of the line, including a null terminator
if (source_list) {
/* Set up capture sources in source list mode */
- if (source[0] == T('-') && source[1] == T('\0')) {
- source_list_contents = stdin_get_text_contents(&source_list_nchars);
- } else {
- source_list_contents = file_get_text_contents(source,
- &source_list_nchars);
- }
- if (!source_list_contents)
+ if (wimlib_load_text_file(source, &source_list_contents,
+ &source_list_nchars) != 0)
goto out_err;
capture_sources = parse_source_list(&source_list_contents,
int solid_ctype = WIMLIB_COMPRESSION_TYPE_INVALID;
int ret;
WIMStruct *wim;
+ struct wimlib_wim_info info;
const tchar *wimfile;
off_t old_size;
off_t new_size;
case IMAGEX_SOLID_OPTION:
write_flags |= WIMLIB_WRITE_FLAG_SOLID;
write_flags |= WIMLIB_WRITE_FLAG_RECOMPRESS;
+ /* Reset the non-solid compression type to LZMS. */
+ if (compression_type == WIMLIB_COMPRESSION_TYPE_INVALID)
+ compression_type = WIMLIB_COMPRESSION_TYPE_LZMS;
break;
case IMAGEX_NO_SOLID_SORT_OPTION:
write_flags |= WIMLIB_WRITE_FLAG_NO_SOLID_SORT;
if (ret)
goto out;
- if (compression_type != WIMLIB_COMPRESSION_TYPE_INVALID) {
+ wimlib_get_wim_info(wim, &info);
+
+ if (compression_type != WIMLIB_COMPRESSION_TYPE_INVALID &&
+ compression_type != info.compression_type) {
/* Change compression type. */
ret = wimlib_set_output_compression_type(wim, compression_type);
if (ret)
goto out_wimlib_free;
+
+ /* Reset the chunk size. */
+ if (chunk_size == UINT32_MAX)
+ chunk_size = 0;
}
if (chunk_size != UINT32_MAX) {
WIMLIB_ADD_FLAG_WINCONFIG;
int default_delete_flags = 0;
unsigned num_threads = 0;
+ STRING_LIST(refglobs);
int c;
tchar *cmd_file_contents;
size_t cmd_file_nchars;
case IMAGEX_WIMBOOT_CONFIG_OPTION:
wimboot_config = optarg;
break;
+ case IMAGEX_REF_OPTION:
+ ret = string_list_append(&refglobs, optarg);
+ if (ret)
+ goto out;
+ /* assume delta WIM */
+ write_flags |= WIMLIB_WRITE_FLAG_SKIP_EXTERNAL_WIMS;
+ break;
/* Default delete options */
case IMAGEX_FORCE_OPTION:
default_delete_flags |= WIMLIB_DELETE_FLAG_FORCE;
ret = wimlib_open_wim_with_progress(wimfile, open_flags, &wim,
imagex_progress_func, NULL);
if (ret)
- goto out_free_command_str;
+ goto out;
if (argc >= 2) {
/* Image explicitly specified. */
image = 1;
}
+ ret = wim_reference_globs(wim, &refglobs, open_flags);
+ if (ret)
+ goto out_wimlib_free;
+
/* Read update commands from standard input, or the command string if
* specified. */
if (command_str) {
tputs(T("Reading update commands from standard input..."));
recommend_man_page(CMD_UPDATE, stdout);
}
- cmd_file_contents = stdin_get_text_contents(&cmd_file_nchars);
- if (!cmd_file_contents) {
+ if (wimlib_load_text_file(NULL, &cmd_file_contents,
+ &cmd_file_nchars) != 0) {
ret = -1;
goto out_wimlib_free;
}
free(cmd_file_contents);
out_wimlib_free:
wimlib_free(wim);
-out_free_command_str:
+out:
free(command_str);
+ string_list_destroy(&refglobs);
return ret;
out_usage:
usage(CMD_UPDATE, stderr);
out_err:
ret = -1;
- goto out_free_command_str;
+ goto out;
}
/* Verify a WIM file. */
static const tchar * const fmt =
T(
"wimlib-imagex " PACKAGE_VERSION " (using wimlib %"TS")\n"
-"Copyright (C) 2012-2023 Eric Biggers\n"
-"License GPLv3+; GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>.\n"
+"Copyright 2012-2023 Eric Biggers\n"
+"License GPLv3+; GNU GPL version 3 or later <https://gnu.org/licenses/gpl.html>.\n"
"This is free software: you are free to change and redistribute it.\n"
"There is NO WARRANTY, to the extent permitted by law.\n"
"\n"