Subject: Patch for linux-2.2.14/15 to handle Japanese node name on the smbfs.
From: [email-masked]
Date: 5 Jun 2000 03:16:54 GMT
Newsgroups: fj.os.linux,fj.sources

Linuxのsmbfsでマウントしたファイルシステム内ノード名をshift_jis/EUC-JP
相互変換し、Linux側でEUC-JPに見せる為の、kernelへのパッチです。2.2.14及
び2.2.15に適用できます。
  <http://www.roboken.esys.tsukuba.ac.jp/~yos/linux/smbfs_jp.2.2.14.y.patch>
では、JIS X 0201片仮名文字集合のshift_jisからEUC-JPへの変換をしないこと
で動作を安定させています。しかし0201仮名が見えないと不便なので、拙作では
この変換をしつつ動作を安定させたつもりです。

Submitted-by: [email-masked]
Archive-name: linux-2.2.14+smbfs_jp-1.1/part01

#!/bin/sh
# This is linux-2.2.14+smbfs_jp-1.1, a shell archive (produced by GNU sharutils 4.2c)
# To extract the files from this archive, save it to some FILE, remove
# everything before the `!/bin/sh' line above, then type `sh FILE'.
#
# Existing files will *not* be overwritten unless `-c' is specified.
#
# This shar contains:
# length mode       name
# ------ ---------- ------------------------------------------
#   4337 -r--r--r-- linux-2.2.14+smbfs_jp-1.1.patch
#
save_IFS="${IFS}"
IFS="${IFS}:"
gettext_dir=FAILED
locale_dir=FAILED
first_param="$1"
for dir in $PATH
do
  if test "$gettext_dir" = FAILED && test -f $dir/gettext \
     && ($dir/gettext --version >/dev/null 2>&1)
  then
    set `$dir/gettext --version 2>&1`
    if test "$3" = GNU
    then
      gettext_dir=$dir
    fi
  fi
  if test "$locale_dir" = FAILED && test -f $dir/shar \
     && ($dir/shar --print-text-domain-dir >/dev/null 2>&1)
  then
    locale_dir=`$dir/shar --print-text-domain-dir`
  fi
done
IFS="$save_IFS"
if test "$locale_dir" = FAILED || test "$gettext_dir" = FAILED
then
  echo=echo
else
  TEXTDOMAINDIR=$locale_dir
  export TEXTDOMAINDIR
  TEXTDOMAIN=sharutils
  export TEXTDOMAIN
  echo="$gettext_dir/gettext -s"
fi
if (echo "testing\c"; echo 1,2,3) | grep c >/dev/null; then
  if (echo -n testing; echo 1,2,3) | sed s/-n/xn/ | grep xn >/dev/null; then
    shar_n= shar_c='
'
  else
    shar_n=-n shar_c=
  fi
else
  shar_n= shar_c='\c'
fi
touch -am 1231235999 $$.touch >/dev/null 2>&1
if test ! -f 1231235999 && test -f $$.touch; then
  shar_touch=touch
else
  shar_touch=:
  echo
  $echo 'WARNING: not restoring timestamps.  Consider getting and'
  $echo "installing GNU \`touch', distributed in GNU File Utilities..."
  echo
fi
rm -f 1231235999 $$.touch
#
$echo $shar_n 'x -' 'lock directory' "\`_sh02474': "$shar_c
if mkdir _sh02474; then
  $echo 'created'
else
  $echo 'failed to create'
  exit 1
fi
# ============= linux-2.2.14+smbfs_jp-1.1.patch ==============
if test -f 'linux-2.2.14+smbfs_jp-1.1.patch' && test "$first_param" != -c; then
  $echo 'x -' SKIPPING 'linux-2.2.14+smbfs_jp-1.1.patch' '(file already exists)'
else
  $echo 'x -' extracting 'linux-2.2.14+smbfs_jp-1.1.patch' '(text)'
  sed 's/^X//' << 'SHAR_EOF' > 'linux-2.2.14+smbfs_jp-1.1.patch' &&
linux-2.2.14+smbfs_jp-1.1.patch
X
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 the Free Software
Foundation; either version 2 of the License, or (at your option) any later
version.
X
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
details.
X
--
X  Linuxのsmbfsでマウントしたファイルシステム内ノード名をshift_jis/EUC-JP
X相互変換し、Linux側でEUC-JPに見せる為の、kernelへのパッチです。2.2.14及
Xび2.2.15に適用できます。
X  <http://www.roboken.esys.tsukuba.ac.jp/~yos/linux/smbfs_jp.2.2.14.y.patch>
(これは、<http://www.KU3G.org/negi/smbfs_jp.2.2.14.patch.gz>に由来し、更
Xなる元は、<http://www.win.or.jp/~susumu-o/Linux/smbfs-ja.patch>である。)
Xでは、JIS X 0201片仮名文字集合のshift_jisからEUC-JPへの変換をしないこと
Xで動作を安定させています。しかし0201仮名が見えないと不便なので、拙作では
Xこの変換をしつつ動作を安定させたつもりです。
X
--- linux-2.2.14/fs/smbfs/proc.c.orig
+++ linux-2.2.14/fs/smbfs/proc.c
@@ -88,6 +88,72 @@
X 	}
X }
X 
+
+#define issjk1(c) ((0x81 <= (c) && (c) <= 0x9f) || (0xe0 <= (c) && (c) <= 0xef))
+#define issjk2(c) ((0x40 <= (c) && (c) <= 0x7e) || (0x80 <= (c) && (c) <= 0xfc))
+#define iskana(c)  (0xa1 <= (c) && (c) <= 0xdf)
+
+static int str_toeuc(char *name, char const *p, int slen)
+{
+	int len;
+
+	for (len = 0; slen > 0 && len < SMB_MAXNAMELEN; ++p, --slen, ++len) {
+		unsigned char const c1 = *p;
+		unsigned char const c2 = *(p + 1);
+
+		if (issjk1(c1) && issjk2(c2) && slen > 1) {
+			++p;
+			--slen;
+			*name++ = 0x80 |
+			(((c1 - (c1 < 0xa0 ? 0x70 : 0xb0)) << 1) - (c2 < 0x9f));
+			if (++len >= SMB_MAXNAMELEN)
+				break;
+			*name++ = 0x80 |
+			(c2 - ((c2 < 0x9f) ? (c2 > 0x7f ? 0x20 : 0x1f) : 0x7e));
+		}
+		else if (iskana(c1)) {
+			*name++ = 0x8e;
+			if (++len >= SMB_MAXNAMELEN)
+				break;
+			*name++ = c1;
+		}
+		else {
+			*name++ = c1;
+		}
+	}
+	return len;
+}
+
+static char *str_tosjis(char *name, int len)
+{
+	char *p;
+
+	for (p = name; len > 0; ++p, --len) {
+		unsigned char c1, c2;
+
+		c1 = *p;
+		c2 = *(p + 1);
+		if ((c1 == 0x8e) && len > 1) {
+			++p;
+			--len;
+			*name++ = c2;
+		}
+		else if (c1 >= 0x80 && c2 >= 0x80 && len > 1) {
+			++p;
+			--len;
+			c1 &= 0x7f;
+			c2 &= 0x7f;
+			*name++ = ((c1 +1) >> 1) + (c1 < 0x5f ? 0x70 : 0xb0);
+			*name++ = c2 +
+				((c1 & 1) ? (c2 > 0x5f ? 0x20 : 0x1f) : 0x7e);
+		}
+		else {
+			*name++ = c1;
+		}
+	}
+	return name;
+}
+
X /*****************************************************************************/
X /*                                                                           */
X /*  Encoding/Decoding section                                                */
@@ -169,6 +235,7 @@
X 
X 	if (server->opt.protocol <= SMB_PROTOCOL_COREPLUS)
X 		str_upper(start, buf - start);
+	buf = str_tosjis(start, buf - start);
X 
X 	return buf;
X }
@@ -1297,6 +1364,7 @@
X 			struct cache_dirent *entry)
X {
X 	int len;
+	char *name = entry->name;
X 
X 	/*
X 	 * SMB doesn't have a concept of inode numbers ...
@@ -1328,6 +1396,8 @@
X 	default:
X 		break;
X 	}
+	entry->len = len = str_toeuc(name, entry->name, len);
+	entry->name = name;
X 	pr_debug("smb_decode_dirent: len=%d, name=%s\n", len, entry->name);
X 	return p + 22;
X }
@@ -1420,7 +1490,9 @@
X 		for (i = 0; i < count; i++)
X 		{
X 			struct cache_dirent this_ent, *entry = &this_ent;
+			char name[SMB_MAXNAMELEN];
X 
+			entry->name = name;
X 			p = smb_decode_dirent(server, p, entry);
X 			if (entries_seen == 2 && entry->name[0] == '.')
X 			{
@@ -1469,6 +1541,7 @@
X {
X 	char *result;
X 	unsigned int len = 0;
+	char *name = entry->name;
X 
X 	/*
X 	 * SMB doesn't have a concept of inode numbers ...
@@ -1515,6 +1588,8 @@
X 	default:
X 		break;
X 	}
+	entry->len = len = str_toeuc(name, entry->name, len);
+	entry->name = name;
X 
X 	return result;
X }
@@ -1684,7 +1759,9 @@
X 		for (i = 0; i < ff_searchcount; i++)
X 		{
X 			struct cache_dirent this_ent, *entry = &this_ent;
+			char name[SMB_MAXNAMELEN];
X 
+			entry->name = name;
X 			p = smb_decode_long_dirent(server, p, entry,
X 							info_level);
X 
SHAR_EOF
  $shar_touch -am 0527030100 'linux-2.2.14+smbfs_jp-1.1.patch' &&
  chmod 0444 'linux-2.2.14+smbfs_jp-1.1.patch' ||
  $echo 'restore of' 'linux-2.2.14+smbfs_jp-1.1.patch' 'failed'
  if ( md5sum --help </dev/null 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \
  && ( md5sum --version </dev/null 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then
    md5sum -c << SHAR_EOF >/dev/null 2>&1 \
    || $echo 'linux-2.2.14+smbfs_jp-1.1.patch:' 'MD5 check failed'
30dbb46f193f1e0fb8e8c22f9117b5aa  linux-2.2.14+smbfs_jp-1.1.patch
SHAR_EOF
  else
    shar_count="`LC_ALL=C wc -c < 'linux-2.2.14+smbfs_jp-1.1.patch'`"
    test 4337 -eq "$shar_count" ||
    $echo 'linux-2.2.14+smbfs_jp-1.1.patch:' 'original size' '4337,' 'current size' "$shar_count!"
  fi
fi
$echo $shar_n 'x -' 'lock directory' "\`_sh02474': " $shar_c
if rm -fr _sh02474; then
  $echo 'removed'
else
  $echo 'failed to remove'
fi
exit 0