svn commit: r189436 - head/lib/libarchive

Tim Kientzle kientzle at FreeBSD.org
Thu Mar 5 21:38:54 PST 2009


Author: kientzle
Date: Fri Mar  6 05:38:53 2009
New Revision: 189436
URL: http://svn.freebsd.org/changeset/base/189436

Log:
  Merge r403,702,721 from libarchive.googlecode.com:  Handle odd
  pathnames on Windows by mapping '\\' to '/' and converting
  illegal characters to '_'.

Modified:
  head/lib/libarchive/archive_write_disk.c

Modified: head/lib/libarchive/archive_write_disk.c
==============================================================================
--- head/lib/libarchive/archive_write_disk.c	Fri Mar  6 05:14:55 2009	(r189435)
+++ head/lib/libarchive/archive_write_disk.c	Fri Mar  6 05:38:53 2009	(r189436)
@@ -1466,6 +1466,57 @@ check_symlinks(struct archive_write_disk
 	return (ARCHIVE_OK);
 }
 
+#ifdef _WIN32
+/*
+ * 1. Convert a path separator from '\' to '/' .
+ *    We shouldn't check multi-byte character directly because some
+ *    character-set have been using the '\' character for a part of
+ *    its multibyte character code.
+ * 2. Replace unusable characters in Windows with underscore('_').
+ * See also : http://msdn.microsoft.com/en-us/library/aa365247.aspx
+ */
+static void
+cleanup_pathname_win(struct archive_write_disk *a)
+{
+	wchar_t wc;
+	char *p;
+	size_t alen, l;
+
+	alen = 0;
+	l = 0;
+	for (p = a->name; *p != '\0'; p++) {
+		++alen;
+		if (*p == '\\')
+			l = 1;
+		/* Rewrite the path name if its character is a unusable. */
+		if (*p == ':' || *p == '*' || *p == '?' || *p == '"' ||
+		    *p == '<' || *p == '>' || *p == '|')
+			*p = '_';
+	}
+	if (alen == 0 || l == 0)
+		return;
+	/*
+	 * Convert path separator.
+	 */
+	p = a->name;
+	while (*p != '\0' && alen) {
+		l = mbtowc(&wc, p, alen);
+		if (l == -1) {
+			while (*p != '\0') {
+				if (*p == '\\')
+					*p = '/';
+				++p;
+			}
+			break;
+		}
+		if (l == 1 && wc == L'\\')
+			*p = '/';
+		p += l;
+		alen -= l;
+	}
+}
+#endif
+
 /*
  * Canonicalize the pathname.  In particular, this strips duplicate
  * '/' characters, '.' elements, and trailing '/'.  It also raises an
@@ -1485,6 +1536,9 @@ cleanup_pathname(struct archive_write_di
 		return (ARCHIVE_FAILED);
 	}
 
+#ifdef _WIN32
+	cleanup_pathname_win(a);
+#endif
 	/* Skip leading '/'. */
 	if (*src == '/')
 		separator = *src++;


More information about the svn-src-all mailing list