Subject: [netatalk-admins] ISO filenames patch, netatalk<->samba<->unix

From: Palle Girgensohn <[email-masked]>
Date: Wed, 07 Jan 1998 22:39:42 +0100

Hello!

I have put together a patch that will use ISO-latin to name files stored
on a netatalk server. If this interest you, please feel free to try them
(consider it alpha quality though; of course I take no responsibility 
;-) Do not be too alarmed; they work fine for me, with the catch
described below.

I know this is not the only patch around for this, but I couldn't wait
:) 
(I'm still interested in getting the patch from Julian, but there's no
rush).

To patch, cd into the netatalk-1.4b2 directory and do 'patch <
xxx/patch.iso' and 'patch < xxx/patch.makefile' (or change the Makefile
in etc/aftpd and add ISO_FILENAMES to the CFLAGS). Then cd into etc/afpd
and do make clean, 
cd ../.. and do make; make install and restart afpd. (on some systems,
you might need to reboot... odd, but this is not because of the
patch...)

Now, file names with MacRoman characters that exist in the
ISO-Latin(8859-1) character set are translated into ISO-Latin. This
helps you if you wan't to share files with Unix or Windows (eg via
Samba). For samba, use 
'character set = iso8859-1' in smb.conf.

The caveat: 
MacRoman has a larger set of characters than iso-8859-1. ASCII defines
only seven bits of a byte, in the interval between 0 and 0x7f. The
interval just after ASCII ends, 0x80 and 0x9f, is used for control chars
by 8859-1 (mirroring the first 32 ASCII chars, sort of?). MacRoman
starts right away defining characters. So I use that interval to map
MacRoman unique chars into iso, so the mac will get them. That is,
MacRoman unique chars are represented in the range 0x80 to 0x9f in
iso-latin. That way, netatalk maintains a one to relation when
converting mac filenames back and forth to the server.

Samba doesn't like the chars in this range and hides the files from the
Windows user. Originally, netatalk converts chars above 0x7f to ':xx'.
This colon is not liked by samba either. The chars not available in iso
are usually stuff like (tm) and the like, which is mostly used for Mac
binaries. These files, you really not need to see in samba. All letters
with umlauts and stuff are available in both charsets...

I feel that files with these names probably only are important to mac
users. Am I right? Maybe using the original colon idea for these are the
best approach; this way samba will see them but the filename is chopped
at the first colon and can not be opened. Other characters than colon
would create even bigger problems, because colon is the only filename
character that is forbidden in both Windows and Mac.

Please give me feedback on this. Also, your own patches for this
functionality interest me :)

Regards,
Palle Girgensohn
Partitur Informationsteknik AB
http://www.partitur.se/

*** ./etc/afpd/desktop.c.orig	Wed Dec 31 01:42:51 1997
--- ./etc/afpd/desktop.c	Wed Jan  7 20:51:12 1998
***************
*** 414,480 ****
      return( path );
  }
  
  char *
  mtoupath( mpath )
      char	*mpath;
  {
!     static char	upath[ MAXNAMLEN ];
!     char	*m, *u;
!     int		i = 0;
! 
!     if ( *mpath == '\0' ) {
! 	return( "." );
      }
! 
!     m = mpath;
!     u = upath;
!     while ( *m != '\0' ) {
! 	if ( !isascii( *m ) || *m == '/' || ( i == 0 && *m == '.' )) {
! 	    *u++ = ':';
! 	    *u++ = hexdig[ ( *m & 0xf0 ) >> 4 ];
! 	    *u++ = hexdig[ *m & 0x0f ];
! 	} else {
  #ifdef DOWNCASE
! 	    *u++ = ( isupper( *m )) ? tolower( *m ) : *m;
  #else DOWNCASE
! 	    *u++ = *m;
  #endif DOWNCASE
- 	}
- 	i++;
- 	m++;
      }
!     *u = '\0';
!     return( upath );
  }
  
- #define hextoint( c )	( isdigit( c ) ? c - '0' : c + 10 - 'a' )
- #define islxdigit(x)	(!isupper(x)&&isxdigit(x))
  
  char *
  utompath( upath )
!     char	*upath;
  {
!     static char	mpath[ MAXNAMLEN ];
!     char	*m, *u;
!     int		h;
! 
!     u = upath;
!     m = mpath;
!     while ( *u != '\0' ) {
! 	if ( *u == ':' && *(u+1) != '\0' && islxdigit( *(u+1)) &&
! 		*(u+2) != '\0' && islxdigit( *(u+2))) {
! 	    ++u;
! 	    h = hextoint( *u ) << 4;
! 	    ++u;
! 	    h |= hextoint( *u );
! 	    *m++ = h;
! 	} else {
! 	    *m++ = *u;
! 	}
! 	u++;
      }
!     *m = '\0';
!     return( mpath );
  }
  
  iconopen( vol, creator, flags, mode )
--- 414,577 ----
      return( path );
  }
  
+ #define hextoint( c )	( isdigit( c ) ? c - '0' : c + 10 - 'a' )
+ #define islxdigit(x)	(!isupper(x)&&isxdigit(x))
+ #ifdef ISO_FILENAMES
+ /*
+  * Macintosh/ISO Character Translation Routines
+  *
+  */
+ 
+ /*
+  * Table for translating Macintosh characters 0x80-0xff to ISO
+  * (Macintosh characters 0x00-0x7f map directly to ISO equivalent).
+  *
+  * The table contains a reversible mapping for text translation.
+  *
+  */
+ 
+ u_char Mac2ISO[128] = {
+       0xC4, 0xC5, 0xC7, 0xC9, 0xD1, 0xD6, 0xDC, 0xE1,  /* 80 - 87 */
+       0xE0, 0xE2, 0xE4, 0xE3, 0xE5, 0xE7, 0xE9, 0xE8,  /* 88 - 8F */
+       0xEA, 0xEB, 0xED, 0xEC, 0xEE, 0xEF, 0xF1, 0xF3,  /* 90 - 97 */
+       0xF2, 0xF4, 0xF6, 0xF5, 0xFA, 0xF9, 0xFB, 0xFC,  /* 98 - 9F */
+       0x84, 0xB0, 0xA2, 0xA3, 0xA7, 0xB7, 0xB6, 0xDF,  /* A0 - A7 */
+       0xAE, 0xA9, 0x85, 0xB4, 0xA8, 0xAD, 0xC6, 0xD8,  /* A8 - AF */
+       0x86, 0xB1, 0xB2, 0xB3, 0xA5, 0xB5, 0x87, 0x88,  /* B0 - B7 */
+       0xBC, 0xB9, 0xBE, 0xAA, 0xBA, 0xBD, 0xE6, 0xF8,  /* B8 - BF */
+       0xBF, 0xA1, 0xAC, 0x89, 0x8A, 0x8B, 0x8C, 0xAB,  /* C0 - C7 */
+       0xBB, 0x8D, 0xA0, 0xC0, 0xC3, 0xD5, 0x8E, 0x8F,  /* C8 - CF */
+       0xD0, 0x90, 0x91, 0x92, 0x93, 0x94, 0xF7, 0xD7,  /* D0 - D7 */
+       0xFF, 0xDD, 0x80, 0xA4, 0x82, 0x83, 0xDE, 0x95,  /* D8 - DF */
+       0x96, 0x97, 0x98, 0x99, 0x9A, 0xC2, 0xCA, 0xC1,  /* E0 - E7 */
+       0xCB, 0xC8, 0xCD, 0xCE, 0xCF, 0xCC, 0xD3, 0xD4,  /* E8 - EF */
+       0xF0, 0xD2, 0xDA, 0xDB, 0xD9, 0x9B, 0x5E, 0x7E,  /* F0 - F7 */
+       0xAF, 0x9C, 0x9D, 0x9E, 0xB8, 0xFD, 0xFE, 0x9F,  /* F8 - FF */
+ };
+ 
+ /*
+  * Table for translating ISO characters 0x80-0xff to Macintosh
+  * (ISO characters 0x00-0x7f map directly to Macintosh equivalent).
+  *
+  * The table contains a reversible mapping for text translation.
+  *
+  */
+ 
+ u_char ISO2Mac[128] = {
+       0xda, 0x2f, 0xdc, 0xde, 0xA0, 0xAA, 0xB0, 0xB6,  /* 80 - 87 */
+       0xB7, 0xC3, 0xC4, 0xC5, 0xC6, 0xC9, 0xCE, 0xCF,  /* 88 - 8F */
+       0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xDF, 0xE0, 0xE1,  /* 90 - 97 */
+       0xE2, 0xE3, 0xE4, 0xF5, 0xF9, 0xFA, 0xFB, 0xFF,  /* 98 - 9F */
+       0xCA, 0xC1, 0xA2, 0xA3, 0xDB, 0xB4, 0x7C, 0xA4,  /* A0 - A7 */
+       0xAC, 0xA9, 0xBB, 0xC7, 0xC2, 0xAD, 0xA8, 0xF8,  /* A8 - AF */
+       0xA1, 0xB1, 0xB2, 0xB3, 0xAB, 0xB5, 0xA6, 0xA5,  /* B0 - B7 */
+       0xFC, 0xB9, 0xBC, 0xC8, 0xB8, 0xBD, 0xBA, 0xC0,  /* B8 - BF */
+       0xCB, 0xE7, 0xE5, 0xCC, 0x80, 0x81, 0xAE, 0x82,  /* C0 - C7 */
+       0xE9, 0x83, 0xE6, 0xE8, 0xED, 0xEA, 0xEB, 0xEC,  /* C8 - CF */
+       0xD0, 0x84, 0xF1, 0xEE, 0xEF, 0xCD, 0x85, 0xD7,  /* D0 - D7 */
+       0xAF, 0xF4, 0xF2, 0xF3, 0x86, 0xD9, 0xDE, 0xA7,  /* D8 - DF */
+       0x88, 0x87, 0x89, 0x8B, 0x8A, 0x8C, 0xBE, 0x8D,  /* E0 - E7 */
+       0x8F, 0x8E, 0x90, 0x91, 0x93, 0x92, 0x94, 0x95,  /* E8 - EF */
+       0xF0, 0x96, 0x98, 0x97, 0x99, 0x9B, 0x9A, 0xD6,  /* F0 - F7 */
+       0xBF, 0x9D, 0x9C, 0x9E, 0x9F, 0xFD, 0xFE, 0xD8,  /* F8 - FF */
+ };
+ 
+ #endif
+ 
  char *
  mtoupath( mpath )
      char	*mpath;
  {
!   static char	upath[ MAXNAMLEN ];
!   char	*m, *u;
!   int		i = 0;
!   
!   if ( *mpath == '\0' ) {
!     return( "." );
!   }
!   
!   m = mpath;
!   u = upath;
!   while ( *m != '\0' ) {
!     
! #ifdef ISO_FILENAMES
!     if ( i == 0 && *m == '.' ) 
!       *u = 0xb7;
!     else if (*m == '/') 
!       *u = 0x81; 
!     else if (*m & 0x80)
!       *u = Mac2ISO[*m & 0x7f];
!     else {
!       *u = *m;
!       
! #ifdef DOWNCASE
!       *u = ( isupper( *u )) ? tolower( *u) : *u;
! #endif DOWNCASE
      }
!     
!     u++;
!     /* PLEASE NOTE: on some systems, a proper LOCALE will 
!        get downcase working with ISO characters. */
!     
! #else ISO_FILENAMES
!     
!     if ( !isascii( *m ) || *m == '/' || ( i == 0 && *m == '.' )) {
!       *u++ = ':';
!       *u++ = hexdig[ ( *m & 0xf0 ) >> 4 ];
!       *u++ = hexdig[ *m & 0x0f ];
!       
!     } else {
!       
  #ifdef DOWNCASE
!       *u++ = ( isupper( *m )) ? tolower( *m ) : *m;
  #else DOWNCASE
!       *u++ = *m;
  #endif DOWNCASE
      }
! 
! #endif ISO_FILENAMES      
!     
!     i++;
!     m++;
!   }
!   *u = '\0';
!   return( upath );
  }

  char *
  utompath( upath )
!      char	*upath;
  {
!   static char	mpath[ MAXNAMLEN ];
!   char	*m, *u;
!   int		h;
!   
!   u = upath;
!   m = mpath;
!   while ( *u != '\0' ) {
! #ifdef ISO_FILENAMES
!     if ( *u & 0x80 ) {
!       *m++ = ISO2Mac[*u & 0x7f];
!     }
! #else 
!     if ( *u == ':' && *(u+1) != '\0' && islxdigit( *(u+1)) &&
! 	 *(u+2) != '\0' && islxdigit( *(u+2))) {
!       ++u;
!       h = hextoint( *u ) << 4;
!       ++u;
!       h |= hextoint( *u );
!       *m++ = h;
!     }
! #endif ISO_FILENAMES
!     
!     else {
!       *m++ = *u;
      }
!     u++;
!   }
!   *m = '\0';
!   return( mpath );
  }
  
  iconopen( vol, creator, flags, mode )
*** /home/girgen/netatalk/netatalk-1.4b2/etc/afpd/Makefile	Tue Dec 30 19:12:36 1997
--- etc/afpd/Makefile	Wed Dec 31 01:37:29 1997
***************
*** 10,16 ****
  
  INCPATH=	-I../../include ${AFSINCPATH} ${KRBINCPATH}
  CFLAGS=	${DEFS} ${AFSDEFS} ${KRBDEFS} ${OPTOPTS} ${INCPATH} \
! 	-DAPPLCNAME -DCRLF # -DDOWNCASE
  LIBS=	-latalk ${AFSLIBS} ${KRBLIBS} ${ADDLIBS}
  LIBDIRS=	-L../../libatalk ${AFSLIBDIRS} ${KRBLIBDIRS}
  TAGSFILE=	tags
--- 10,16 ----
  
  INCPATH=	-I../../include ${AFSINCPATH} ${KRBINCPATH}
  CFLAGS=	${DEFS} ${AFSDEFS} ${KRBDEFS} ${OPTOPTS} ${INCPATH} \
! 	-DAPPLCNAME -DCRLF -DISO_FILENAMES # -DDOWNCASE
  LIBS=	-latalk ${AFSLIBS} ${KRBLIBS} ${ADDLIBS}
  LIBDIRS=	-L../../libatalk ${AFSLIBDIRS} ${KRBLIBDIRS}
  TAGSFILE=	tags