2014-10-12  Juan Manuel Guerrero  <juan.guerrero@gmx.de>

	* src/xz/suffix.c (uncompressed_name):  Use HAVE_LFN_SUPPORT to enable
	DJGPP specific support for plain DOS filename length limitations.
	(compressed_name):  Use HAVE_LFN_SUPPORT to enable DJGPP specific
	support for plain DOS filename length limitations.

	* src/common/sysdefs.h [__DJGPP__, __DJGPP_MINOR__]:  DJGPP 2.03 lacks
	inttypes.h so provide required values for PRIx32 and PRIx64.

	* src/xz/xz.1:  DJGPP specific info added.

	* src/common/tuklib_common.h [TUKLIB_DOSLIKE]:  Define the new macros
	IS_SLASH and HAVE_SLASH.  If TUKLIB_DOSLIKE defined it will check for
	slash and backslash else only for slash.
	[__DJGPP__]:  Define new macro HAVE_LFN_SUPPORT.  For DJGPP it will be
	checked at runtime if LFN support is available or not.  For all other
	systems HAVE_LFN_SUPPORT always returns true.

	* src/scripts/xzdiff.in: The DJGPP port of bash has some difficulties
	with redirecting file descriptors in subprocesses.  The functionality
	is reproduced by functions.







diff -aprNU5 xz-5.0.7.orig/src/common/sysdefs.h xz-5.0.7/src/common/sysdefs.h
--- xz-5.0.7.orig/src/common/sysdefs.h	2014-09-20 16:48:04 +0100
+++ xz-5.0.7/src/common/sysdefs.h	2014-10-12 18:47:00 +0100
@@ -32,10 +32,18 @@
 // size_t and NULL
 #include <stddef.h>
 
 #ifdef HAVE_INTTYPES_H
 #	include <inttypes.h>
+#else
+#	if __DJGPP__ == 2 && __DJGPP_MINOR__ < 4
+		/*
+		 * DJGPP 2.03 lacks inttypes.h
+		 */
+#		define PRIx32  "x"
+#		define PRIx64  "llx"
+#	endif
 #endif
 
 // C99 says that inttypes.h always includes stdint.h, but some systems
 // don't do that, and require including stdint.h separately.
 #ifdef HAVE_STDINT_H
diff -aprNU5 xz-5.0.7.orig/src/common/tuklib_common.h xz-5.0.7/src/common/tuklib_common.h
--- xz-5.0.7.orig/src/common/tuklib_common.h	2014-09-20 16:48:04 +0100
+++ xz-5.0.7/src/common/tuklib_common.h	2014-10-12 18:48:00 +0100
@@ -66,6 +66,21 @@
 #if (defined(_WIN32) && !defined(__CYGWIN__)) \
 		|| defined(__OS2__) || defined(__MSDOS__)
 #	define TUKLIB_DOSLIKE 1
 #endif
 
+#if defined TUKLIB_DOSLIKE
+#	define IS_SLASH(c)   ((c) == '/' || (c) == '\\')
+#	define HAVE_SLASH(p) (strchr(p, '/') != NULL || strchr(p, '\\') != NULL || strchr(p, ':') != NULL)
+#	if defined __DJGPP__
+#		include <unistd.h>
+#		define HAVE_LFN_SUPPORT(name) (pathconf((name), _PC_NAME_MAX) > 12)
+#	else
+#		define HAVE_LFN_SUPPORT(name) (1)
+#	endif
+#else
+#	define IS_SLASH(c)   ((c) == '/')
+#	define HAVE_SLASH(p) (strchr(p, '/') != NULL)
+#	define HAVE_LFN_SUPPORT(name) (1)
+#endif
+
 #endif
diff -aprNU5 xz-5.0.7.orig/src/scripts/xzdiff.in xz-5.0.7/src/scripts/xzdiff.in
--- xz-5.0.7.orig/src/scripts/xzdiff.in	2014-09-20 16:48:04 +0100
+++ xz-5.0.7/src/scripts/xzdiff.in	2014-10-12 18:48:32 +0100
@@ -62,12 +62,93 @@ cmp="$cmp --"
 
 for file; do
   test "X$file" = X- || <"$file" || exit 2
 done
 
+unzip_and_compare()
+{
+  local srcdir
+  local tmpdir
+  local file
+  local file1
+  local file2
+  local zip_program
+
+  file1=$1
+  file2=$2
+  zip_program=$3
+
+  srcdir=$(pwd)
+  tmpdir=${TMPDIR-${TMP-${TEMP-$srcdir}}}/ziptemp.$$
+  mkdir -p $tmpdir
+  xz_status=$?
+
+  if [ "$xz_status" -eq 0 ]; then
+    #
+    #  Process first file.
+    #
+    file1=`expr "X$1" : 'X\(.*\)[-.][abglmxzZ2]*$'`
+    if [ "x$file1" == "x" ]; then
+      file1=$1
+
+      if [ "x$file1" == "x-" ]; then
+        cd $tmpdir
+        $zip_program -cd -- - > ziptmp1.out
+        xz_status=$?
+        file1="$tmpdir/ziptmp1.out"
+      fi
+    else
+      cp -f $1 $tmpdir
+      cd $tmpdir
+      file=$(basename $file1)
+      $zip_program -d -- $file*
+      xz_status=$?
+      file1=$(basename $file1 | sed "s,^,$tmpdir/,")
+    fi
+    cd $srcdir
+
+    if [ "$xz_status" -eq 0 ]; then
+      #
+      #  Process second file.
+      #
+      file2=`expr "X$2" : 'X\(.*\)[-.][abglmxzZ2]*$'`
+      if [ "x$file2" == "x" ]; then
+        file2=$2
+  
+        if [ "x$file2" == "x-" ]; then
+          cd $tmpdir
+          file2=ziptmp2.out
+          $zip_program -cd -- - > ziptmp2.out
+          xz_status=$?
+          file2="$tmpdir/ziptmp2.out"
+        fi
+      else
+        cp -f $2 $tmpdir
+        cd $tmpdir
+        file=$(basename $file2)
+        $zip_program -d -- $file*
+        xz_status=$?
+        file2=$(basename $file2 | sed "s,^,$tmpdir/,")
+      fi
+    fi
+  fi
+  cd $srcdir
+
+
+  if [ "$xz_status" -eq 0 ]; then
+    eval "$cmp" '"$file1"' '"$file2"' >&3
+    cmp_status=$?
+  fi
+  rm -fr $tmpdir
+
+  echo $xz_status
+  return $cmp_status
+}
+
 xz1=$xz
 xz2=$xz
+cmp_status=0
 xz_status=0
 exec 3>&1
 
 if test $# -eq 1; then
   case $1 in
@@ -88,12 +169,19 @@ if test $# -eq 1; then
       FILE=`expr "X$1" : 'X\(.*[-.]t\)[abglx]z$'`ar;;
     *.tbz2)
       FILE=`expr "X$1" : 'X\(.*[-.]t\)bz2$'`ar;;
   esac
   xz_status=$(
-    exec 4>&1
-    ($xz1 -cd -- "$1" 4>&-; echo $? >&4) 3>&- | eval "$cmp" - '"$FILE"' >&3
+    #
+    #  The DJGPP port of bash has some difficulties
+    #  with redirecting file descriptors in sub
+    #  processes.  The required functionality will
+    #  be reproduced by a function.
+    #
+    # exec 4>&1
+    # ($xz1 -cd -- "$1" 4>&-; echo $? >&4) 3>&- | eval "$cmp" - '"$FILE"' >&3
+    unzip_and_compare "$1" "$FILE" "$xz1"
   )
 elif test $# -eq 2; then
   case $1 in
     *[-.]bz2 | *.tbz | *.tbz2) xz1=bzip2;;
     *[-.][zZ] | *_z | *[-.]gz | *.t[ag]z) xz1=gzip;;
@@ -131,36 +219,63 @@ elif test $# -eq 2; then
             tmp=
             trap '
               test -n "$tmp" && rm -f "$tmp"
               (exit 2); exit 2
             ' HUP INT PIPE TERM 0
-            tmp=`mktemp -t -- "$F.XXXXXX"` || exit 2
+
+            if type mktemp >/dev/null 2>&1; then
+              tmp=`mktemp -t -- "$F.XXXXXX"` || exit 2
+            else
+              set -C
+              tmp=${TMPDIR-${TMP-${TEMP-$srcdir}}}/$F.$$
+            fi
             $xz2 -cdfq -- "$2" > "$tmp" || exit 2
             xz_status=$(
-              exec 4>&1
-              ($xz1 -cdfq -- "$1" 4>&-; echo $? >&4) 3>&- |
-                eval "$cmp" - '"$tmp"' >&3
+              #
+              #  The DJGPP port of bash has some difficulties
+              #  with redirecting file descriptors in sub
+              #  processes.  The required functionality will
+              #  be reproduced by a function.
+              #
+              # exec 4>&1
+              # ($xz1 -cdfq -- "$1" 4>&-; echo $? >&4) 3>&- |
+              #   eval "$cmp" - '"$tmp"' >&3
+              unzip_and_compare "$1" "$tmp" "$xz1"
             )
             cmp_status=$?
             rm -f "$tmp" || xz_status=$?
             trap - HUP INT PIPE TERM 0
             (exit $cmp_status)
           fi;;
       *)
         xz_status=$(
-          exec 4>&1
-          ($xz1 -cdfq -- "$1" 4>&-; echo $? >&4) 3>&- |
-            eval "$cmp" - '"$2"' >&3
+          #
+          #  The DJGPP port of bash has some difficulties
+          #  with redirecting file descriptors in sub
+          #  processes.  The required functionality will
+          #  be reproduced by a function.
+          #
+          # exec 4>&1
+          # ($xz1 -cdfq -- "$1" 4>&-; echo $? >&4) 3>&- |
+          #   eval "$cmp" - '"$2"' >&3
+          unzip_and_compare "$1" "$2" "$xz1"
         );;
     esac;;
   *)
     case "$2" in
       *[-.][zZ] | *_z | *[-.][gx]z | *[-.]bz2 | *[-.]lzma | *.t[abglx]z | *.tbz2 | -)
         xz_status=$(
-          exec 4>&1
-          ($xz2 -cdfq -- "$2" 4>&-; echo $? >&4) 3>&- |
-            eval "$cmp" '"$1"' - >&3
+          #
+          #  The DJGPP port of bash has some difficulties
+          #  with redirecting file descriptors in sub
+          #  processes.  The required functionality will
+          #  be reproduced by a function.
+          #
+          # exec 4>&1
+          # ($xz2 -cdfq -- "$2" 4>&-; echo $? >&4) 3>&- |
+          #   eval "$cmp" '"$1"' - >&3
+          unzip_and_compare "$1" "$2" "$xz2"
          );;
       *)
         eval "$cmp" '"$1"' '"$2"';;
     esac;;
   esac
diff -aprNU5 xz-5.0.7.orig/src/xz/suffix.c xz-5.0.7/src/xz/suffix.c
--- xz-5.0.7.orig/src/xz/suffix.c	2014-09-20 16:48:04 +0100
+++ xz-5.0.7/src/xz/suffix.c	2014-10-12 18:49:20 +0100
@@ -115,24 +115,92 @@ uncompressed_name(const char *src_name,
 	}
 
 	if (new_len == 0 && custom_suffix != NULL)
 		new_len = test_suffix(custom_suffix, src_name, src_len);
 
-	if (new_len == 0) {
+	if (new_len == 0 && HAVE_LFN_SUPPORT(src_name)) {
 		message_warning(_("%s: Filename has an unknown suffix, "
 				"skipping"), src_name);
 		return NULL;
 	}
 
-	const size_t new_suffix_len = strlen(new_suffix);
-	char *dest_name = xmalloc(new_len + new_suffix_len + 1);
-
-	memcpy(dest_name, src_name, new_len);
-	memcpy(dest_name + new_len, new_suffix, new_suffix_len);
-	dest_name[new_len + new_suffix_len] = '\0';
-
-	return dest_name;
+	if (HAVE_LFN_SUPPORT(src_name)) {
+		const size_t new_suffix_len = strlen(new_suffix);
+		char *dest_name = xmalloc(new_len + new_suffix_len + 1);
+
+		memcpy(dest_name, src_name, new_len);
+		memcpy(dest_name + new_len, new_suffix, new_suffix_len);
+		dest_name[new_len + new_suffix_len] = '\0';
+
+		return dest_name;
+	} else {
+		// For plain DOS there are filename length limitations (8.3).
+		//
+		// compressed name       uncompressed name
+		//   filename.exx    -->   filename.ex
+		//   filename.exz    -->   filename.e
+		//   filename.xz     -->   filename
+		//
+		// compressed name       uncompressed name
+		//   filename.exl    -->   filename.ex
+		//   filename.elz    -->   filename.e
+		//   filename.lzm    -->   filename
+
+		size_t new_len1, new_len2, suffix_len;
+		for (new_len = src_len; new_len && src_name[new_len] != '.'; new_len--)
+			;
+		suffix_len = src_len - new_len;
+		new_len1 = suffix_len > 3 ? new_len + 3 : suffix_len - 1;  // Last suffix char.
+		new_len2 = new_len1 - 1;
+
+		if (suffix_len > 3) {
+			if (src_name[new_len1] == 'x' || src_name[new_len1] == 'X' || src_name[new_len1] == 'l' || src_name[new_len1] == 'L') {
+				char *dest_name = xmalloc(new_len1);
+
+				memcpy(dest_name, src_name, new_len1);
+				dest_name[new_len1] = '\0';  // Discard last suffix char.
+
+				return dest_name;
+			} else
+			if (((src_name[new_len2] == 'x' || src_name[new_len2] == 'l') && src_name[new_len1] == 'z') ||
+			    ((src_name[new_len2] == 'X' || src_name[new_len2] == 'L') && src_name[new_len1] == 'Z')) {
+				char *dest_name = xmalloc(new_len2);
+
+				memcpy(dest_name, src_name, new_len2);
+				dest_name[new_len2] = '\0';  // Discard last 2 suffix chars.
+
+				return dest_name;
+			} else 
+			if ((src_name[new_len + 1] == 'l' && src_name[new_len2] == 'z' && src_name[new_len1] == 'm') ||
+			    (src_name[new_len + 1] == 'L' && src_name[new_len2] == 'Z' && src_name[new_len1] == 'M')) {
+				char *dest_name = xmalloc(new_len + 1);
+
+				memcpy(dest_name, src_name, new_len);
+				dest_name[new_len] = '\0';  // Discard all 3 suffix chars.
+
+				return dest_name;
+			} else {
+				message_warning(_("%s: Filename has an unknown suffix, "
+						"skipping"), src_name);
+				return NULL;
+			}
+		} else {
+			if ((src_name[new_len2] == 'x' && src_name[new_len1] == 'z') ||
+			    (src_name[new_len2] == 'X' && src_name[new_len1] == 'Z')) {
+				char *dest_name = xmalloc(new_len2);
+
+				memcpy(dest_name, src_name, new_len);
+				dest_name[new_len] = '\0';
+
+				return dest_name;
+			} else {
+				message_warning(_("%s: Filename has an unknown suffix, "
+						"skipping"), src_name);
+				return NULL;
+			}
+		}
+	}
 }
 
 
 /// \brief      Appends suffix to src_name
 ///
@@ -197,19 +265,87 @@ compressed_name(const char *src_name, co
 		return NULL;
 	}
 
 	const char *suffix = custom_suffix != NULL
 			? custom_suffix : suffixes[0];
-	const size_t suffix_len = strlen(suffix);
+	if (HAVE_LFN_SUPPORT(src_name)) {
+		const size_t suffix_len = strlen(suffix);
 
-	char *dest_name = xmalloc(src_len + suffix_len + 1);
+		char *dest_name = xmalloc(src_len + suffix_len + 1);
 
-	memcpy(dest_name, src_name, src_len);
-	memcpy(dest_name + src_len, suffix, suffix_len);
-	dest_name[src_len + suffix_len] = '\0';
+		memcpy(dest_name, src_name, src_len);
+		memcpy(dest_name + src_len, suffix, suffix_len);
+		dest_name[src_len + suffix_len] = '\0';
+
+		return dest_name;
+	} else {
+		// For plain DOS there are filename length limitations (8.3).
+		//
+		// uncompressed name     compressed name
+		//   filename.ext    -->   filename.exx
+		//   filename.ex     -->   filename.exx
+		//   filename.e      -->   filename.exz
+		//
+		// uncompressed name     compressed name
+		//   filename.ext    -->   filename.exl
+		//   filename.ex     -->   filename.exl
+		//   filename.e      -->   filename.elz
+
+		size_t len;
+		for (len = src_len; len && src_name[len] != '.'; len--)
+			;
+
+		if (len) {
+			// File name has an extension so only a part of the suffix can be appended.
+			if (src_len - len > 2) {
+				// Only one character left for suffix.
+				const size_t name_len = len + 1 + 2;          // Dot plus 2 extension chars
+
+				char *dest_name = xmalloc(name_len + 1 + 1);  // and 1 suffix char.
+
+				memcpy(dest_name, src_name, name_len);
+				if (suffix[0] == '.')
+					memcpy(dest_name + name_len,  suffix + 1, 1);
+				else
+					memcpy(dest_name + name_len,  suffix, 1);
+				dest_name[name_len + 1] = '\0';
+
+				return dest_name;
+			} else {
+				// Two characters left for suffix.
+				const size_t name_len = len + 1 + 1;          // Dot plus 1 extension char
+
+				char *dest_name = xmalloc(name_len + 2 + 1);  // and 2 suffix chars.
+
+				memcpy(dest_name, src_name, name_len);
+				if (suffix[0] == '.')
+					memcpy(dest_name + name_len,  suffix + 1, 2);
+				else
+					memcpy(dest_name + name_len,  suffix, 2);
+				dest_name[name_len + 2] = '\0';
+
+				return dest_name;
+			}
+		} else {
+			// File name has no extension so simply append the whole suffix.
+			const size_t name_len = suffix[0] == '.' ? src_len : src_len + 1;  // custom suffix may have no leading dot.
+			const size_t suffix_len = strlen(suffix);
+
+			char *dest_name = xmalloc(name_len + suffix_len + 1);
+
+			memcpy(dest_name, src_name, src_len);
+			if (suffix[0] != '.')
+				memcpy(dest_name + src_len, ".", 1);
+			memcpy(dest_name + name_len, suffix, suffix_len);
+			if (suffix_len > 3)
+				dest_name[name_len + ((name_len != src_len) ? 3 : 4)] = '\0';
+			else
+				dest_name[name_len + suffix_len] = '\0';
 
-	return dest_name;
+			return dest_name;
+		}
+	}
 }
 
 
 extern char *
 suffix_get_dest_name(const char *src_name)
diff -aprNU5 xz-5.0.7.orig/src/xz/xz.1 xz-5.0.7/src/xz/xz.1
--- xz-5.0.7.orig/src/xz/xz.1	2014-09-20 16:48:04 +0100
+++ xz-5.0.7/src/xz/xz.1	2014-10-12 18:49:58 +0100
@@ -113,10 +113,112 @@ and
 .BR .tlz ,
 and replaces them with the
 .B .tar
 suffix.
 .PP
+
+The
+.BR DJGPP
+port of
+.BR xz
+will detect at run time if
+.IR LFN
+support is available or not.  If
+.IR LFN
+support is available, then the program will work as described above.
+But if only
+.IR SFN
+support is available, like on plain
+.BR DOS
+, then it will
+.IR not
+be possible to append one extension more if the original
+filename has already an extension.  Appart from this the extension cannot be
+longer than
+.IR 3
+characters.  This has the consequence that 
+.IR 1
+or
+.IR 2
+characters
+of the original extension will be overwritten by the character sequence
+.BR x
+or
+.BR xz
+for the
+.BR .xz
+format and
+.BR l
+or
+.BR lz
+for the
+.BR .lzma
+format and there will be
+.IR no
+way to recreate the original extension when the file is uncompressed.  The
+.BR DJGPP
+port will try to preserve as much characters as possible from the original
+extension.
+.IP \(bu 3
+When compressing using the
+.BR .xz
+format the following naming schema will be used:
+
+uncompressed name     compressed name
+  filename.ex\fIt\fR    -->   filename.ex\fIx\fR
+  filename.ex     -->   filename.ex\fIx\fR
+  filename.e      -->   filename.e\fIxz\fR
+  filename        -->   filename.\fIxz\fR
+.IP \(bu 3
+When decompressing using the
+.BR .xz
+format the following naming schema will be used:
+
+compressed name       uncompressed name
+  filename.ex\fIx\fR    -->   filename.ex
+  filename.e\fIxz\fR    -->   filename.e
+  filename.\fIxz\fR     -->   filename
+
+
+.IP \(bu 3
+When compressing using the
+.BR .lzma
+format the following naming schema will be used:
+
+uncompressed name     compressed name
+  filename.ex\fIt\fR    -->   filename.ex\fIl\fR
+  filename.ex     -->   filename.ex\fIl\fR
+  filename.e      -->   filename.e\fIlz\fR
+  filename        -->   filename.\fIlzm\fR
+.IP \(bu 3
+When decompressing using the
+.BR .lzma
+format the following naming schema will be used:
+
+compressed name       uncompressed name
+  filename.ex\fIl\fR    -->   filename.ex
+  filename.e\fIlz\fR    -->   filename.e
+  filename.\fIlzm\fR    -->   filename
+
+.PP
+For
+.IR LFN
+and
+.IR SFN
+systems the
+.BR DJGPP
+port will always recognize the suffixes
+.B .txz
+and
+.BR .tlz
+as
+.IR tar
+archives and will replace them with the
+.B .tar
+suffix.
+.PP
+
 If the target file already exists, an error is displayed and the
 .I file
 is skipped.
 .PP
 Unless writing to standard output,
