[bug] the last char of multibyte string may not be correctly shown

Samba-JP TAKAHASHI Motonobu monyo at samba.gr.jp
Mon Jun 25 16:59:48 GMT 2001


Hello

The following problem was found at Samba-JP.

If a multibyte character is the last char(not byte) of a string, only
the 1st byte of the char may be displayed.

For example there is a string named "s", 
  0xb4c1bbfa (means "KANJI" in Kanji character of EUC code) 

and display with 

  printf("%-3.3s", s);

then only the 1st byte (0xbb) of the last char (0xbbfa) is displayed
and this becomes a broken character in Japanese.

Here is a big patch to fix it for Samba HEAD branch at 21st June.

---- Cut Here for HEAD ----
diff -urNP ../../samba-head/source/rpcclient/display.c ./rpcclient/display.c
--- ../../samba-head/source/rpcclient/display.c	Wed Aug  2 03:32:34 2000
+++ ./rpcclient/display.c	Thu Jun 21 14:10:44 2001
@@ -1206,13 +1206,18 @@
 static void print_reg_value(FILE *out_hnd, char *val_name, uint32 val_type, BUFFER2 *value)
 {
 	fstring type;
+	pstring name;
+
 	fstrcpy(type, get_reg_val_type_str(val_type));
+	pstrcpy(name, dos_to_unix(val_name, False));
+	val_name = name;
 
 	switch (val_type)
 	{
 		case 0x01: /* unistr */
 		{
-			fprintf(out_hnd,"\t%s:\t%s:\t%s\n", val_name, type, dos_buffer2_to_str(value));
+			fprintf(out_hnd,"\t%s:\t%s:\t%s\n", val_name, type,
+				dos_to_unix(dos_buffer2_to_str(value), False));
 			break;
 		}
 
@@ -1234,13 +1239,15 @@
 
 		case 0x04: /* uint32 */
 		{
-			fprintf(out_hnd,"\t%s:\t%s: 0x%08x\n", val_name, type, buffer2_to_uint32(value));
+			fprintf(out_hnd,"\t%s:\t%s: 0x%08x\n", val_name, type,
+				buffer2_to_uint32(value));
 			break;
 		}
 
 		case 0x07: /* multiunistr */
 		{
-			fprintf(out_hnd,"\t%s:\t%s:\t%s\n", val_name, type, dos_buffer2_to_multistr(value));
+			fprintf(out_hnd,"\t%s:\t%s:\t%s\n", val_name, type,
+				dos_to_unix(dos_buffer2_to_multistr(value), False));
 			break;
 		}
 	}
diff -ur client/client.c.010622 client/client.c
--- client/client.c.010622	Tue May  8 14:13:38 2001
+++ client/client.c	Fri Jun 22 15:04:12 2001
@@ -1546,6 +1546,7 @@
 static void browse_fn(const char *name, uint32 m, const char *comment)
 {
         fstring typestr;
+	pstring s;
 
         *typestr=0;
 
@@ -1561,8 +1562,8 @@
             fstrcpy(typestr,"IPC"); break;
         }
 
-        printf("\t%-15.15s%-10.10s%s\n",
-               name, typestr,comment);
+	dos_to_unix(s, strncpy_fill(s, unix_to_dos(s, name), 15));
+	printf("\t%s%-10.10s%s\n", s, typestr, comment);
 }
 
 
@@ -1587,7 +1588,10 @@
 ****************************************************************************/
 static void server_fn(const char *name, uint32 m, const char *comment)
 {
-        printf("\t%-16.16s     %s\n", name, comment);
+	pstring s;
+
+	dos_to_unix(s, strncpy_fill(s, unix_to_dos(s, name), 16));
+        printf("\t%s     %s\n", s, comment);
 }
 
 /****************************************************************************
diff -ur include/proto.h.010622 include/proto.h
--- include/proto.h.010622	Fri Jun 22 14:54:37 2001
+++ include/proto.h	Fri Jun 22 14:57:14 2001
@@ -404,6 +404,7 @@
 char *safe_strcat(char *dest, const char *src, size_t maxlength);
 char *alpha_strcpy(char *dest, const char *src, size_t maxlength);
 char *StrnCpy(char *dest,const char *src,size_t n);
+char *strncpy_fill(char *dest, const char *src, size_t n);
 char *strncpyn(char *dest, const char *src,size_t n, char c);
 size_t strhex_to_str(char *p, size_t len, const char *strhex);
 BOOL in_list(char *s,char *list,BOOL casesensitive);
diff -ur lib/util.c.010622 lib/util.c
--- lib/util.c.010622	Wed Jun 13 13:19:00 2001
+++ lib/util.c	Fri Jun 22 15:08:23 2001
@@ -301,8 +301,11 @@
   (void)memset( buf, 0, 20 );
   if (strcmp(In,"*") == 0)
     buf[0] = '*';
-  else
-    (void)slprintf( buf, sizeof(buf) - 1, "%-15.15s%c", In, name_type );
+  else {
+    strncpy_fill(buf, In, 15);
+    buf[15] = name_type;
+    buf[16] = '\0';
+  }
 
   /* Place the length of the first field into the output buffer. */
   p[0] = 32;
diff -ur lib/util_str.c.010622 lib/util_str.c
--- lib/util_str.c.010622	Fri Jun 15 17:33:37 2001
+++ lib/util_str.c	Fri Jun 22 15:34:27 2001
@@ -1166,11 +1166,46 @@
 	n -= skip;
 	while (skip--) *d++ = *src++;
       } else {
-        n--;
-        *d++ = *src++;
+	n--;
+	*d++ = *src++;
       }
     }
   }
+  *d = 0;
+  return(dest);
+}
+
+/****************************************************************************
+ Like strncpy but always spaces fill the rest. Make sure there is room!
+ The variable n should always be one less than the available size.
+****************************************************************************/
+
+char *strncpy_fill(char *dest, const char *src, size_t n)
+{
+  size_t skip;
+  char *d = dest;
+
+  if (!dest) {
+    return(NULL);
+  }
+
+  if (!src);
+  else if(!global_is_multibyte_codepage) {
+    while (n-- && *src) *d++ = *src++;
+  } else {
+    while (n && *src) {
+      skip = get_character_len( *src );
+      if( skip != 0 ) {
+	if (skip > n) break;
+	n -= skip;
+	while (skip--) *d++ = *src++;
+      } else {
+	n--;
+	*d++ = *src++;
+      }
+    }
+  }
+  while (n--) *d++ = ' ';
   *d = 0;
   return(dest);
 }
diff -ur libsmb/nmblib.c.010622 libsmb/nmblib.c
--- libsmb/nmblib.c.010622	Fri May  4 04:11:43 2001
+++ libsmb/nmblib.c	Fri Jun 22 15:09:54 2001
@@ -279,7 +279,9 @@
     buf1[0] = '*';
     buf1[15] = name->name_type;
   } else {
-    slprintf(buf1, sizeof(buf1) - 1,"%-15.15s%c",name->name,name->name_type);
+    strncpy_fill(buf1, name->name, 15);
+    buf[15] = name->name_type;
+    buf[16] = '\0';
   }
 
   buf[offset] = 0x20;
diff -ur nmbd/nmbd_incomingrequests.c.010622 nmbd/nmbd_incomingrequests.c
--- nmbd/nmbd_incomingrequests.c.010622	Wed May 10 23:28:47 2000
+++ nmbd/nmbd_incomingrequests.c	Fri Jun 22 15:17:04 2001
@@ -368,7 +368,7 @@
       {
         /* Start with the name. */
         memset(buf,'\0',18);
-        slprintf(buf, 17, "%-15.15s",namerec->name.name);
+	strncpy_fill(buf, namerec->name.name, 15);
         strupper(buf);
         
         /* Put the name type and netbios flags in the buffer. */
diff -ur rpcclient/display.c.010622 rpcclient/display.c
--- rpcclient/display.c.010622	Thu Jun 21 14:12:40 2001
+++ rpcclient/display.c	Fri Jun 22 15:05:20 2001
@@ -716,8 +716,12 @@
 		}
 		case ACTION_ENUMERATE:
 		{
-			fprintf(out_hnd, "\t%-15.15s%-20s %s\n",
-			                 sname, get_server_type_str(type), comment);
+			pstring s1, s2;
+
+			dos_to_unix(s1, strncpy_fill(s1, sname, 15));
+			dos_to_unix(s2, comment);
+			fprintf(out_hnd, "\t%s%-20s %s\n",
+			                 s1, get_server_type_str(type), s2);
 			break;
 		}
 		case ACTION_FOOTER:
@@ -741,8 +745,12 @@
 		}
 		case ACTION_ENUMERATE:
 		{
-			fprintf(out_hnd, "\t%-15.15s%-10.10s%s\n",
-			                 sname, get_share_type_str(type), comment);
+			pstring s1, s2;
+
+			dos_to_unix(s1, strncpy_fill(s1, sname, 15));
+			dos_to_unix(s2, comment);
+			fprintf(out_hnd, "\t%s%-10.10s%s\n",
+			                 s1, get_share_type_str(type), s2);
 			break;
 		}
 		case ACTION_FOOTER:
@@ -769,8 +777,12 @@
 		}
 		case ACTION_ENUMERATE:
 		{
-			fprintf(out_hnd, "\t%-15.15s%-10.10s%s %x %x %x %s %s\n",
-			                 sname, get_share_type_str(type), comment,
+			pstring s1, s2;
+
+			dos_to_unix(s1, strncpy_fill(s1, sname, 15));
+			dos_to_unix(s2, comment);
+			fprintf(out_hnd, "\t%s%-10.10s%s %x %x %x %s %s\n",
+			                 s1, get_share_type_str(type), s2,
 			                 perms, max_uses, num_uses, path, passwd);
 			break;
 		}
@@ -796,7 +808,10 @@
 		}
 		case ACTION_ENUMERATE:
 		{
-			fprintf(out_hnd, "\t%-21.21s\n", sname);
+			pstring s;
+
+			dos_to_unix(s, strncpy_fill(s, sname, 21));
+			fprintf(out_hnd, "\t%s\n", s);
 			break;
 		}
 		case ACTION_FOOTER:
----- Cut Here -----

-----
TAKAHASHI Motonobu                    mailto:monyo at samba.gr.jp
Samba Users Group Japan               http://www.samba.gr.jp/




More information about the samba-technical mailing list