Fix glob()
authorEric Biggers <ebiggers3@gmail.com>
Thu, 21 Mar 2013 02:07:02 +0000 (21:07 -0500)
committerEric Biggers <ebiggers3@gmail.com>
Thu, 21 Mar 2013 02:07:02 +0000 (21:07 -0500)
configure.ac
programs/imagex-win32.c
programs/imagex.c
src/encoding.c
src/util.c
src/util.h

index e30d455..06a7540 100644 (file)
@@ -157,10 +157,9 @@ if test "x$ENABLE_MULTITHREADED_COMPRESSION" = "xyes"; then
        AC_DEFINE([ENABLE_MULTITHREADED_COMPRESSION], [1],
                        [Define to 1 if including support for multithreaded
                         compression])
-       PTHREAD_LDADD="-lpthread"
-else
-       PTHREAD_LDADD=""
 fi
+
+PTHREAD_LDADD="-lpthread"
 AC_SUBST([PTHREAD_LDADD], [$PTHREAD_LDADD])
 
 WITH_NTFS_3G_DEFAULT="yes"
index 3dc51d9..1664850 100644 (file)
@@ -25,6 +25,20 @@ int glob(const char *pattern, int flags,
        int ret;
        size_t nspaces;
 
+       const char *backslash, *forward_slash, *end_slash;
+       size_t prefix_len;
+
+       backslash = strrchr(pattern, '\\');
+       end_slash = strrchr(pattern, '/');
+
+       if (backslash > end_slash)
+               end_slash = backslash;
+
+       if (end_slash)
+               prefix_len = end_slash - pattern + 1;
+       else
+               prefix_len = 0;
+
        /* This function does not support all functionality of the POSIX glob(),
         * so make sure the parameters are consistent with supported
         * functionality. */
@@ -49,7 +63,7 @@ int glob(const char *pattern, int flags,
        pglob->gl_pathv = NULL;
        nspaces = 0;
        do {
-               char *filename;
+               char *path;
                if (pglob->gl_pathc == nspaces) {
                        size_t new_nspaces;
                        char **pathv;
@@ -62,10 +76,16 @@ int glob(const char *pattern, int flags,
                        pglob->gl_pathv = pathv;
                        nspaces = new_nspaces;
                }
-               filename = strdup(dat.cFileName);
-               if (!filename)
+               size_t filename_len = strlen(dat.cFileName);
+               size_t len_needed = prefix_len + filename_len;
+
+               path = malloc(len_needed + 1);
+               if (!path)
                        goto oom;
-               pglob->gl_pathv[pglob->gl_pathc++] = filename;
+
+               memcpy(path, pattern, prefix_len);
+               memcpy(path + prefix_len, dat.cFileName, filename_len + 1);
+               pglob->gl_pathv[pglob->gl_pathc++] = path;
        } while (FindNextFileA(hFind, &dat));
        err = GetLastError();
        CloseHandle(hFind);
@@ -93,7 +113,7 @@ void globfree(glob_t *pglob)
        size_t i;
        for (i = 0; i < pglob->gl_pathc; i++)
                free(pglob->gl_pathv[i]);
-       free(pglob->gl_pathv[i]);
+       free(pglob->gl_pathv);
 }
 
 static bool
index c8fa94a..0f65ae5 100644 (file)
@@ -2138,8 +2138,7 @@ int main(int argc, char **argv)
        /* The user may like to see more informative error messages. */
        wimlib_set_print_errors(true);
 
-       /* Calling wimlib_global_init() is not strictly necessary because
-        * 'imagex' is single-threaded. */
+       /* Do any initializations that the library needs */
        ret = wimlib_global_init();
        if (ret)
                goto out;
@@ -2178,8 +2177,9 @@ out:
                if (ret == WIMLIB_ERR_NTFS_3G && errno != 0)
                        imagex_error_with_errno("errno");
        }
-       /* Calling wimlib_global_cleanup() is not strictly necessary because the
-        * process is exiting anyway. */
+
+       /* Make the library free any resources it's holding (not strictly
+        * necessary because the process is ending anyway). */
        wimlib_global_cleanup();
        return ret;
 }
index aa8f928..48bad18 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * encoding.c:  Convert "multibyte" strings (the locale-default encoding---
  * generally, UTF-8 or something like ISO-8859-1) to UTF-16LE strings, and vice
- * versa.
+ * versa.  Also, convert UTF-8 strings to multibyte strings.
  */
 
 /*
  * along with wimlib; if not, see http://www.gnu.org/licenses/.
  */
 
-#include "config.h"
 #include "wimlib_internal.h"
-#include <pthread.h>
-#include "list.h"
 
+#include <errno.h>
 #include <iconv.h>
+#include <pthread.h>
 #include <stdlib.h>
-#include <errno.h>
 
 bool wimlib_mbs_is_utf8 = true;
 
+/* List of iconv_t conversion descriptors for a specific character conversion.
+ * The idea is that it is not thread-safe to have just one conversion
+ * descriptor, but it also is inefficient to open a new conversion descriptor to
+ * convert every string.  Both these problems can be solved by maintaining a
+ * list of conversion descriptors; then, a thread can use an existing conversion
+ * descriptor if available. */
 struct iconv_list_head {
        const char *from_encoding;
        const char *to_encoding;
@@ -166,7 +170,11 @@ varname1##_to_##varname2##_buf(const chartype1 *in, size_t in_nbytes,      \
                                                                        \
        len = iconv(*cd, &inbuf, &inbytesleft, &outbuf, &outbytesleft); \
        if (len == (size_t)-1) {                                        \
-               err_msg;                                                \
+               if (!error_message_being_printed) {                     \
+                       error_message_being_printed = true;             \
+                       err_msg;                                        \
+                       error_message_being_printed = false;            \
+               }                                                       \
                ret = err_return;                                       \
        } else {                                                        \
                out[(LARGE_NUMBER-outbytesleft)/sizeof(chartype2)] = 0; \
@@ -210,23 +218,28 @@ DEFINE_CHAR_CONVERSION_FUNCTIONS(utf16le, "UTF-16LE", utf16lechar,
                                 mbs, "", mbchar,
                                 in_nbytes / 2 * MB_CUR_MAX,
                                 WIMLIB_ERR_UNICODE_STRING_NOT_REPRESENTABLE,
-                                ERROR_WITH_ERRNO("Failed to convert UTF-16LE "
-                                                 "string %U to multibyte string", in))
+                                ERROR("Failed to convert UTF-16LE string "
+                                      "to multibyte string!");
+                                ERROR("This may be because the UTF-16LE data "
+                                      "could not be represented in your "
+                                      "locale's character encoding."))
 
 DEFINE_CHAR_CONVERSION_FUNCTIONS(mbs, "", mbchar,
                                 utf16le, "UTF-16LE", utf16lechar,
                                 in_nbytes * 2,
                                 WIMLIB_ERR_INVALID_MULTIBYTE_STRING,
                                 ERROR_WITH_ERRNO("Failed to convert multibyte "
-                                                 "string %s to UTF-16LE string", in))
+                                                 "string \"%s\" to UTF-16LE string!", in);
+                                ERROR("If the data you provided was UTF-8, please make sure "
+                                      "the character encoding of your current locale is UTF-8."))
 
 DEFINE_CHAR_CONVERSION_FUNCTIONS(utf8, "UTF-8", utf8char,
                                 mbs, "", mbchar,
                                 in_nbytes,
-                                WIMLIB_ERR_INVALID_UTF8_STRING,
-                                ERROR_WITH_ERRNO("Failed to convert UTF-8 "
-                                                 "string %U to multibyte string", in))
-
+                                WIMLIB_ERR_UNICODE_STRING_NOT_REPRESENTABLE,
+                                ERROR("Failed to convert UTF-8 string to multibyte string!");
+                                ERROR("This may be because the UTF-8 data could not be represented "
+                                      "in your locale's character encoding."))
 
 static void
 iconv_cleanup(struct iconv_list_head *head)
@@ -250,8 +263,6 @@ iconv_global_cleanup()
        iconv_cleanup(&iconv_utf8_to_mbs);
 }
 
-
-
 bool
 utf8_str_contains_nonascii_chars(const utf8char *utf8_str)
 {
index 20bff95..c0244ba 100644 (file)
@@ -92,7 +92,7 @@ special:
                                                  &mbs, &mbs_nbytes);
                        }
                        if (ret) {
-                               ret = fprintf(fp, "???CONVERSION FAILURE???");
+                               ret = fprintf(fp, "??????");
                        } else {
                                ret = fprintf(fp, "%s", mbs);
                                FREE(mbs);
index 4fd117d..28f9655 100644 (file)
@@ -52,9 +52,10 @@ typedef uint64_t u64;
 /* A pointer to 'mbchar' indicates a string of "multibyte characters" provided
  * in the default encoding of the user's locale, which may be "UTF-8",
  * "ISO-8859-1", "C", or any other ASCII-compatible encoding.
- * "ASCII-compatible" here means any encoding where all ASCII characters have
- * the same representation, and any non-ASCII character is represented as a
- * sequence of one or more bytes not already used by any ASCII character. */
+ * "ASCII-compatible" here means any encoding where all ASCII-representable
+ * characters have the same representation as in ASCII itself, and any non-ASCII
+ * character is represented as a sequence of one or more bytes not already used
+ * by any ASCII character. */
 typedef char mbchar;
 
 /* A pointer to 'utf8char' indicates a UTF-8 encoded string */