]> wimlib.net Git - wimlib/blobdiff - src/textfile.c
mount_image.c: add fallback definitions of RENAME_* constants
[wimlib] / src / textfile.c
index 01c3959289e6045fc68d47e6b42159b358cc2fd7..d41464cd8cbd17016cdb2b22e9cf2539e9a13623 100644 (file)
  * details.
  *
  * You should have received a copy of the GNU Lesser General Public License
- * along with this file; if not, see http://www.gnu.org/licenses/.
+ * along with this file; if not, see https://www.gnu.org/licenses/.
  */
 
 #ifdef HAVE_CONFIG_H
 #  include "config.h"
 #endif
 
-#include "wimlib/encoding.h"
-#include "wimlib/error.h"
-#include "wimlib/file_io.h"
-#include "wimlib/textfile.h"
-#include "wimlib/util.h"
-
 #include <ctype.h>
 #include <errno.h>
 #include <fcntl.h>
 #include <sys/stat.h>
 #include <unistd.h>
 
+#include "wimlib/encoding.h"
+#include "wimlib/error.h"
+#include "wimlib/file_io.h"
+#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)
 {
@@ -46,9 +78,6 @@ 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);
@@ -141,23 +170,23 @@ translate_text_buffer(const u8 *buf_raw, size_t bufsize_raw,
 }
 
 static int
-string_set_append(struct string_set *set, tchar *str)
+string_list_append(struct string_list *list, tchar *str)
 {
-       size_t num_alloc_strings = set->num_alloc_strings;
+       size_t num_alloc_strings = list->num_alloc_strings;
 
-       if (set->num_strings == num_alloc_strings) {
+       if (list->num_strings == num_alloc_strings) {
                tchar **new_strings;
 
                num_alloc_strings = max(num_alloc_strings * 3 / 2,
                                        num_alloc_strings + 4);
-               new_strings = REALLOC(set->strings,
-                                     sizeof(set->strings[0]) * num_alloc_strings);
+               new_strings = REALLOC(list->strings,
+                                     sizeof(list->strings[0]) * num_alloc_strings);
                if (!new_strings)
                        return WIMLIB_ERR_NOMEM;
-               set->strings = new_strings;
-               set->num_alloc_strings = num_alloc_strings;
+               list->strings = new_strings;
+               list->num_alloc_strings = num_alloc_strings;
        }
-       set->strings[set->num_strings++] = str;
+       list->strings[list->num_strings++] = str;
        return 0;
 }
 
@@ -264,8 +293,8 @@ parse_text_file(const tchar *path, tchar *buf, size_t buflen,
                                return ret;
                }
 
-               ret = string_set_append(pos_sections[current_section].strings,
-                                       line_begin);
+               ret = string_list_append(pos_sections[current_section].strings,
+                                        line_begin);
                if (ret)
                        return ret;
        }
@@ -273,13 +302,14 @@ parse_text_file(const tchar *path, tchar *buf, size_t buflen,
 }
 
 /**
- * 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.
@@ -293,12 +323,11 @@ parse_text_file(const tchar *path, tchar *buf, size_t buflen,
  *     consists of the name of the section (e.g. [ExclusionList], like in the
  *     INI file format), along with a pointer to the list of lines parsed for
  *     that section.  Use an empty name to indicate the destination of lines
- *     not in any section.  Each list must be initialized to an empty string
- *     set.
+ *     not in any section.  Each list must be initialized to empty.
  * @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.
  *
@@ -308,34 +337,40 @@ parse_text_file(const tchar *path, tchar *buf, size_t buflen,
  * 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++)
@@ -347,3 +382,23 @@ do_load_text_file(const tchar *path,
        *mem_ret = tstr;
        return 0;
 }
+
+/* API function documented in wimlib.h */
+WIMLIBAPI int
+wimlib_load_text_file(const tchar *path,
+                     tchar **tstr_ret, size_t *tstr_nchars_ret)
+{
+       void *buf;
+       size_t bufsize;
+       int ret;
+
+       if (path == NULL || (path[0] == '-' && path[1] == '\0'))
+               ret = stdin_get_contents(&buf, &bufsize);
+       else
+               ret = read_file_contents(path, &buf, &bufsize);
+       if (ret)
+               return ret;
+       ret = translate_text_buffer(buf, bufsize, tstr_ret, tstr_nchars_ret);
+       FREE(buf);
+       return ret;
+}