# timing out a connection. The default is 4, therefore
# a connection will timeout in 2 minutes.
# -icon Use the platform-specific icon.
+# -volnamelen <number>
+# Max length of UTF8-MAC volume name for Mac OS X.
+# Note that Hangul is especially sensitive to this.
+# 31: conservative default
+# 80: limit for Mac OS X 10.5
+# 255: limit of spec
+# Mac OS 9 and earlier are not influenced by this,
+# Maccharset volume name is always 27 limit.
# -[un]setuplog "<logtype> <loglevel> [<filename>]"
-# Specify that the given loglevel should be applied
-# to log messages of the given logtype and that
-# these messages should be logged to the given file.
-# If the filename is ommited the loglevel applies to
-# messages passed to syslog.
-# Each logtype may have a loglevel applied to syslog
-# and a loglevel applied to a single file. Latter
-# -setuplog settings will override earlier ones of
-# the same logtype (file or syslog).
-# logtypes: Default, Core, Logger, CNID, AFPDaemon
-# loglevels: LOG_SEVERE, LOG_ERROR, LOG_WARN, LOG_NOTE,
-# LOG_INFO, LOG_DEBUG, LOG_DEBUG6, LOG_DEBUG7,
-# LOG_DEBUG8, LOG_DEBUG9, LOG_MAXDEBUG
-#
-# for example:
-# -setuplog "logger log_maxdebug /var/log/netatalk-logger.log"
-# -setuplog "afpdaemon log_maxdebug /var/log/netatalk-afp.log"
-# -unsetuplog "default level file"
-# -setuplog "default log_maxdebug"
+# Specify that any message of a loglevel up to the given loglevel
+# should be logged to the given file. If the filename is ommited the
+# loglevel applies to messages passed to syslog. Latter -setuplog
+# settings will override earlier ones of the same logtype (file or
+# syslog).
+#
+# By default (no explicit -setuplog and no buildtime configure flag
+# --with-logfile) all netatalk daemons log to syslog with a default
+# logging setup equivalent to "-setuplog default log_debug".
+#
+# If build with --with-logfile (default logfile
+# /var/log/netatalk.log) or --with-logfile=somefile all daemons
+# default to a setup that is equivalent to "-setuplog default
+# log_info [netatalk.log|somefile]"
+#
+# Example: Useful default config
+# -setuplog "default log_info /var/log/afpd.log"
+#
+# Debugging config
+# -setuplog "default log_maxdebug /var/log/afpd.log"
#
# -signature { user:<text> | host }
# Specify a server signature. This option is useful while
/*
- * $Id: directory.c,v 1.92 2009-03-15 13:00:14 franklahm Exp $
+ * $Id: directory.c,v 1.93 2009-03-16 13:59:12 franklahm Exp $
*
* Copyright (c) 1990,1993 Regents of The University of Michigan.
* All Rights Reserved. See COPYRIGHT.
/* remove the node from the tree. this is just like insertion, but
* different. actually, it has to worry about a bunch of things that
* insertion doesn't care about. */
+
static void dir_remove( const struct vol *vol _U_, struct dir *dir)
{
#ifdef REMOVE_NODES
if (toUTF8) {
static char temp[ MAXPATHLEN + 1];
- /* not an UTF8 name */
- if (mtoUTF8(vol, path, strlen(path), temp, MAXPATHLEN) == (size_t)-1) {
- afp_errno = AFPERR_PARAM;
- return( NULL );
+ if (dir->d_did == DIRDID_ROOT_PARENT) {
+ /*
+ With uft8 volume name is utf8-mac, but requested path may be a mangled longname. See #2611981.
+ So we compare it with the longname from the current volume and if they match
+ we overwrite the requested path with the utf8 volume name so that the following
+ strcmp can match.
+ */
+ ucs2_to_charset(vol->v_maccharset, vol->v_macname, temp, AFPVOL_MACNAMELEN + 1);
+ if (strcasecmp( path, temp) == 0)
+ ucs2_to_charset(CH_UTF8_MAC, vol->v_u8mname, path, AFPVOL_U8MNAMELEN);
+ } else {
+ /* toUTF8 */
+ if (mtoUTF8(vol, path, strlen(path), temp, MAXPATHLEN) == (size_t)-1) {
+ afp_errno = AFPERR_PARAM;
+ return( NULL );
+ }
+ strcpy(path, temp);
}
- strcpy(path, temp);
}
/* check for OS X mangled filename :( */
}
if ( !extend ) {
if (dir->d_did == DIRDID_ROOT_PARENT) {
- /* root parent has only one child and d_m_name is *NOT* utm (d_u_name)
- * d_m_name is the Mac volume name
- * d_u_name is the volume unix directory name
- *
- */
- cdir = NULL;
- if (!strcmp(vol->v_dir->d_m_name, ret.m_name)) {
- cdir = vol->v_dir;
- }
+ /*
+ root parent (did 1) has one child: the volume. Requests for did=1 with some <name>
+ must check against the volume name.
+ */
+ if (!strcmp(vol->v_dir->d_m_name, ret.m_name))
+ cdir = vol->v_dir;
+ else
+ cdir = NULL;
}
else {
cdir = dirsearch_byname(vol, dir, ret.u_name);
/*
- * $Id: volume.c,v 1.80 2009-02-16 13:49:20 franklahm Exp $
+ * $Id: volume.c,v 1.81 2009-03-16 13:59:12 franklahm Exp $
*
* Copyright (c) 1990,1993 Regents of The University of Michigan.
* All Rights Reserved. See COPYRIGHT.
#include "file.h"
#include "volume.h"
#include "unix.h"
+#include "mangle.h"
#include "fork.h"
extern int afprun(int root, char *cmd, int *outfd);
static void handle_special_folders (const struct vol *);
static int savevoloptions (const struct vol *);
static void deletevol(struct vol *vol);
+static void volume_free(struct vol *vol);
static void volfree(struct vol_option *options,
const struct vol_option *save)
{
struct vol *volume;
for ( volume = Volumes; volume; volume = volume->v_next ) {
- if (volume->v_hide && !strcasecmp_w( volume->v_name, name ) ) {
+ if (volume->v_hide && !strcasecmp_w( (utf8_encoding()?volume->v_u8mname:volume->v_macname), name ) ) {
volume->v_hide = 0;
return;
}
)
{
struct vol *volume;
- int vlen;
+ int suffixlen, vlen, tmpvlen, u8mvlen, macvlen;
int hide = 0;
- ucs2_t tmpname[512];
+ char tmpname[AFPVOL_U8MNAMELEN+1];
+ ucs2_t u8mtmpname[(AFPVOL_U8MNAMELEN+1)*2], mactmpname[(AFPVOL_MACNAMELEN+1)*2];
+ char suffix[6]; /* max is #FFFF */
+ u_int16_t flags;
if ( name == NULL || *name == '\0' ) {
if ((name = strrchr( path, '/' )) == NULL) {
return -1;
}
+ /* suffix for mangling use (lastvid + 1) */
+ /* because v_vid has not been decided yet. */
+ suffixlen = sprintf(suffix, "%c%X", MANGLE_CHAR, lastvid + 1 );
+
vlen = strlen( name );
- if ( vlen > AFPVOL_NAMELEN ) {
- vlen = AFPVOL_NAMELEN;
- name[AFPVOL_NAMELEN] = '\0';
+
+ /* Unicode Volume Name */
+ /* Firstly convert name from unixcharset to UTF8-MAC */
+ flags = CONV_IGNORE;
+ tmpvlen = convert_charset(obj->options.unixcharset, CH_UTF8_MAC, 0, name, vlen, tmpname, AFPVOL_U8MNAMELEN, &flags);
+ if (tmpvlen <= 0) {
+ strcpy(tmpname, "???");
+ tmpvlen = 3;
+ }
+
+ /* Do we have to mangle ? */
+ if ( (flags & CONV_REQMANGLE) || (tmpvlen > obj->options.volnamelen)) {
+ if (tmpvlen + suffixlen > obj->options.volnamelen) {
+ flags = CONV_FORCE;
+ tmpvlen = convert_charset(obj->options.unixcharset, CH_UTF8_MAC, 0, name, vlen, tmpname, obj->options.volnamelen - suffixlen, &flags);
+ tmpname[tmpvlen != (size_t)-1 ? tmpvlen : 0] = 0;
+ }
+ strcat(tmpname, suffix);
+ tmpvlen = strlen(tmpname);
+ }
+
+ /* Secondly convert name from UTF8-MAC to UCS2 */
+ if ( 0 >= ( u8mvlen = convert_string(CH_UTF8_MAC, CH_UCS2, tmpname, tmpvlen, u8mtmpname, AFPVOL_U8MNAMELEN*2)) )
+ return -1;
+
+ LOG(log_debug, logtype_afpd, "createvol: Volume '%s' -> UTF8-MAC Name: '%s'", name, tmpname);
+
+ /* Maccharset Volume Name */
+ /* Firsty convert name from unixcharset to maccharset */
+ flags = CONV_IGNORE;
+ tmpvlen = convert_charset(obj->options.unixcharset, obj->options.maccharset, 0, name, vlen, tmpname, AFPVOL_U8MNAMELEN, &flags);
+ if (tmpvlen <= 0) {
+ strcpy(tmpname, "???");
+ tmpvlen = 3;
}
- /* convert name to UCS2 first */
- if ( 0 >= ( vlen = convert_string(obj->options.unixcharset, CH_UCS2, name, vlen, tmpname, 512)) )
+ /* Do we have to mangle ? */
+ if ( (flags & CONV_REQMANGLE) || (tmpvlen > AFPVOL_MACNAMELEN)) {
+ if (tmpvlen + suffixlen > AFPVOL_MACNAMELEN) {
+ flags = CONV_FORCE;
+ tmpvlen = convert_charset(obj->options.unixcharset, obj->options.maccharset, 0, name, vlen, tmpname, AFPVOL_MACNAMELEN - suffixlen, &flags);
+ tmpname[tmpvlen != (size_t)-1 ? tmpvlen : 0] = 0;
+ }
+ if (*tmpname == 0) {
+ strcat(tmpname, "???");
+ }
+ strcat(tmpname, suffix);
+ tmpvlen = strlen(tmpname);
+ }
+
+ /* Secondly convert name from maccharset to UCS2 */
+ if ( 0 >= ( macvlen = convert_string(obj->options.maccharset, CH_UCS2, tmpname, tmpvlen, mactmpname, AFPVOL_U8MNAMELEN*2)) )
return -1;
+ LOG(log_debug, logtype_afpd, "createvol: Volume '%s' -> Longname: '%s'", name, tmpname);
+
+ /* check duplicate */
for ( volume = Volumes; volume; volume = volume->v_next ) {
- if ( strcasecmp_w( volume->v_name, tmpname ) == 0 ) {
+ if (( strcasecmp_w( volume->v_u8mname, u8mtmpname ) == 0 ) || ( strcasecmp_w( volume->v_macname, mactmpname ) == 0 )){
if (volume->v_deleted) {
volume->v_new = hide = 1;
}
}
}
-
if (!( volume = (struct vol *)calloc(1, sizeof( struct vol ))) ) {
LOG(log_error, logtype_afpd, "creatvol: malloc: %s", strerror(errno) );
return -1;
}
- if ( NULL == ( volume->v_name = strdup_w(tmpname))) {
+ if ( NULL == ( volume->v_localname = strdup(name))) {
+ LOG(log_error, logtype_afpd, "creatvol: malloc: %s", strerror(errno) );
+ free(volume);
+ return -1;
+ }
+
+ if ( NULL == ( volume->v_u8mname = strdup_w(u8mtmpname))) {
+ LOG(log_error, logtype_afpd, "creatvol: malloc: %s", strerror(errno) );
+ volume_free(volume);
+ free(volume);
+ return -1;
+ }
+ if ( NULL == ( volume->v_macname = strdup_w(mactmpname))) {
LOG(log_error, logtype_afpd, "creatvol: malloc: %s", strerror(errno) );
+ volume_free(volume);
free(volume);
return -1;
}
if (!( volume->v_path = (char *)malloc( strlen( path ) + 1 )) ) {
LOG(log_error, logtype_afpd, "creatvol: malloc: %s", strerror(errno) );
- free(volume->v_name);
+ volume_free(volume);
free(volume);
return -1;
}
{
FILE *fp;
char path[ MAXPATHLEN + 1], tmp[ MAXPATHLEN + 1],
- volname[ AFPVOL_NAMELEN + 1 ], buf[ BUFSIZ ],
+ volname[ AFPVOL_U8MNAMELEN + 1 ], buf[ BUFSIZ ],
type[ 5 ], creator[ 5 ];
char *u, *p;
struct passwd *pw;
/* ------------------------------- */
static void volume_free(struct vol *vol)
{
- free(vol->v_name);
- vol->v_name = NULL;
+ free(vol->v_localname);
+ vol->v_localname = NULL;
+ free(vol->v_u8mname);
+ vol->v_u8mname = NULL;
+ free(vol->v_macname);
+ vol->v_macname = NULL;
free(vol->v_path);
free(vol->v_password);
free(vol->v_veto);
for ( vol = Volumes, ovol = NULL; vol; vol = nvol) {
nvol = vol->v_next;
- if (vol->v_name == NULL) {
+ if (vol->v_localname == NULL) {
if (Volumes == vol) {
Volumes = nvol;
ovol = Volumes;
char *data, *nameoff = NULL;
char *slash;
+ LOG(log_debug, logtype_afpd, "getvolparams: Volume '%s'", vol->v_localname);
+
/* courtesy of jallison@whistle.com:
* For MacOS8.x support we need to create the
* .Parent file here if it doesn't exist. */
if ( nameoff ) {
ashort = htons( data - buf );
memcpy(nameoff, &ashort, sizeof( ashort ));
- /* name is always in mac charset, FIXME mangle if length > 27 char */
- aint = ucs2_to_charset( vol->v_maccharset, vol->v_name, data+1, 255);
+ /* name is always in mac charset */
+ aint = ucs2_to_charset( vol->v_maccharset, vol->v_macname, data+1, AFPVOL_MACNAMELEN + 1);
if ( aint <= 0 ) {
*buflen = 0;
return AFPERR_MISC;
if (volume->v_hide) {
continue; /* config file changed but the volume was mounted */
}
- len = ucs2_to_charset_allocate((utf8_encoding()?CH_UTF8_MAC:obj->options.maccharset),
- &namebuf, volume->v_name);
+
+ if (utf8_encoding()) {
+ len = ucs2_to_charset_allocate(CH_UTF8_MAC, &namebuf, volume->v_u8mname);
+ } else {
+ len = ucs2_to_charset_allocate(obj->options.maccharset, &namebuf, volume->v_macname);
+ }
+
if (len == (size_t)-1)
continue;
if ((volname_tmp = strchr(volname,'+')) != NULL)
volname = volname_tmp+1;
- namelen = convert_string( (utf8_encoding()?CH_UTF8_MAC:obj->options.maccharset), CH_UCS2,
- ibuf, len, volname, sizeof(obj->oldtmp));
+ if (utf8_encoding()) {
+ namelen = convert_string(CH_UTF8_MAC, CH_UCS2, ibuf, len, volname, sizeof(obj->oldtmp));
+ } else {
+ namelen = convert_string(obj->options.maccharset, CH_UCS2, ibuf, len, volname, sizeof(obj->oldtmp));
+ }
+
if ( namelen <= 0){
*rbuflen = 0;
return AFPERR_PARAM;
load_volumes(obj);
for ( volume = Volumes; volume; volume = volume->v_next ) {
- if ( strcasecmp_w( (ucs2_t*) volname, volume->v_name ) == 0 ) {
+ if ( strcasecmp_w( (ucs2_t*) volname, (utf8_encoding()?volume->v_u8mname:volume->v_macname) ) == 0 ) {
break;
}
}
/* initialize volume variables
* FIXME file size
*/
- if (afp_version >= 30) {
+ if (utf8_encoding()) {
volume->max_filename = 255;
}
else {
goto openvol_err;
}
- len = convert_string_allocate( CH_UCS2, (utf8_encoding()?CH_UTF8_MAC:obj->options.maccharset),
- volume->v_name, namelen, &vol_mname);
+ if (utf8_encoding()) {
+ len = convert_string_allocate(CH_UCS2, CH_UTF8_MAC, volume->v_u8mname, namelen, &vol_mname);
+ } else {
+ len = convert_string_allocate(CH_UCS2, obj->options.maccharset, volume->v_macname, namelen, &vol_mname);
+ }
if ( !vol_mname || len <= 0) {
ret = AFPERR_MISC;
goto openvol_err;
closevol(vol);
if (vol->v_deleted) {
- showvol(vol->v_name);
+ showvol(utf8_encoding()?vol->v_u8mname:vol->v_macname);
volume_free(vol);
volume_unlink(vol);
free(vol);