* NEW: Add the ability to enable debugging at runtime by sending afpd a
SIGUSR1.
+* NEW: Add support for long filename mangling.
* NEW: Add a -noslp option to disable SLP per afpd instance.
* NEW: Added -d option for pap to enable debugging at runtime rather than
compile time.
#undef AFS
#undef BSD4_4
#undef CNID_DB
+#undef FILE_MANGLING
#undef DISABLE_LOGGER
#undef LOGFILEPATH
#undef DEBUG
-dnl $Id: configure.in,v 1.157 2002-04-29 06:23:57 morgana Exp $
+dnl $Id: configure.in,v 1.158 2002-05-29 18:02:57 jmarcus Exp $
dnl configure.in for netatalk
AC_INIT(bin/adv1tov2/adv1tov2.c)
dnl Don't use DB3 unless it's needed
db3_required=no
-
dnl Determine DID scheme
AC_MSG_CHECKING([for DID scheme to use])
AC_ARG_WITH(did,
fi
AM_CONDITIONAL(COMPILE_CNID, test "x$did_scheme" = "xcnid")
+dnl Determine whether or not to use filename mangling
+AC_MSG_CHECKING([whether or not to use filename mangling])
+AC_ARG_WITH(mangling,
+ [ --with-mangling enable filename mangling],
+ if test "$withval" = "yes"; then
+ if test "x$did_scheme" != "xcnid"; then
+ AC_MSG_ERROR([DID scheme must be CNID to use filename mangling])
+ else
+ AC_DEFINE(FILE_MANGLING, 1)
+ AC_MSG_RESULT([yes])
+ fi
+ fi
+)
+
dnl Check for Berkeley DB3 library
if test "x$db3_required" = "xyes"; then
AC_PATH_DB3(, [AC_MSG_ERROR([Berkeley DB3 library not found!])])
afpd_SOURCES = unix.c ofork.c main.c switch.c auth.c volume.c directory.c \
file.c enumerate.c desktop.c filedir.c fork.c appl.c gettok.c \
- status.c afp_options.c afp_asp.c afp_dsi.c messages.c afp_config.c \
- nfsquota.c codepage.c quota.c uam.c afs.c uid.c parse_mtab.c \
- afp_util.c
+ mangle.c status.c afp_options.c afp_asp.c afp_dsi.c messages.c \
+ afp_config.c nfsquota.c codepage.c quota.c uam.c afs.c uid.c \
+ parse_mtab.c afp_util.c
test_parse_mtab_SOURCES = test_parse_mtab.c parse_mtab.c
test_parse_mtab_LDADD = $(top_builddir)/libatalk/libatalk.la
afpd_LDFLAGS = -export-dynamic
noinst_HEADERS = auth.h codepage.h afp_config.h desktop.h directory.h file.h \
- filedir.h fork.h globals.h icon.h misc.h status.h switch.h uam_auth.h \
- uid.h unix.h volume.h parse_mtab.h
+ filedir.h fork.h globals.h icon.h mangle.h misc.h status.h switch.h \
+ uam_auth.h uid.h unix.h volume.h parse_mtab.h
LIBS = @LIBS@ @AFPD_LIBS@ @QUOTA_LIBS@ @SLP_LIBS@
/*
- * $Id: desktop.c,v 1.12 2002-03-24 01:23:40 sibaz Exp $
+ * $Id: desktop.c,v 1.13 2002-05-29 18:02:59 jmarcus Exp $
*
* See COPYRIGHT.
*/
#include "fork.h"
#include "globals.h"
#include "desktop.h"
+#ifdef FILE_MANGLING
+#include "mangle.h"
+#endif /* CNID_DB */
int afp_opendt(obj, ibuf, ibuflen, rbuf, rbuflen )
AFPObj *obj;
return( "." );
}
+#ifdef FILE_MANGLING
+ mpath = demangle(vol, mpath);
+#endif /* FILE_MANGLING */
+
m = mpath;
u = upath;
while ( *m != '\0' ) {
char *m, *u;
int h;
+#ifdef FILE_MANGLING
+ upath = mangle(vol, upath);
+#endif /* FILE_MANGLING */
+
/* do the hex conversion */
u = upath;
m = mpath;
--- /dev/null
+/*
+ * $Id: mangle.c,v 1.1 2002-05-29 18:02:59 jmarcus Exp $
+ *
+ * Copyright (c) 2002. Joe Marcus Clarke (marcus@marcuscom.com)
+ * All Rights Reserved. See COPYRIGHT.
+ *
+ * mangle, demangle (filename):
+ * mangle or demangle filenames if they are greater than the max allowed
+ * characters for a given version of AFP.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif /* HAVE_CONFIG_H */
+
+#ifdef FILE_MANGLING
+#include "mangle.h"
+
+char *
+demangle(const struct vol *vol, char *mfilename) {
+ char *filename = NULL;
+ char *ext = NULL;
+ char dir[MAXPATHLEN+1];
+ char *mangle;
+
+ /* Is this really a mangled file? */
+ mangle = strstr(mfilename, MANGLE_CHAR);
+ if (!mangle) {
+ return mfilename;
+ }
+
+ ext = strrchr(mfilename, '.');
+ if (strlen(mangle) != strlen(MANGLE_CHAR) + MANGLE_LENGTH + strlen(ext)) {
+ return mfilename;
+ }
+
+ getcwd(dir, MAXPATHLEN);
+
+ if (strlen(dir) > MAXPATHLEN - strlen(mfilename) - 1) {
+ LOG(log_error, logtype_default, "demangle: Path is too large");
+ return mfilename;
+ }
+
+ strcat(dir, "/");
+ strcat(dir, mfilename);
+
+ filename = cnid_mangle_get(vol->v_db, dir);
+
+ /* No unmangled filename was found. */
+ if (filename == NULL) {
+ LOG(log_debug, logtype_default, "demangle: Unable to lookup %s in the mangle database", dir);
+ return mfilename;
+ }
+
+ return filename;
+}
+char *
+mangle(const struct vol *vol, char *filename) {
+ char *ext = NULL;
+ char mfilename[MAX_LENGTH+1];
+ char mangle_suffix[MANGLE_LENGTH+1];
+ char dir[MAXPATHLEN+1];
+ char tmp[MAXPATHLEN+1];
+ int mangle_suffix_int = 0;
+
+ /* Do we really need to mangle this filename? */
+ if (strlen(filename) <= MAX_LENGTH) {
+ return filename;
+ }
+
+ /* First, attmept to locate a file extension. */
+ ext = strrchr(filename, '.');
+
+ getcwd(dir, MAXPATHLEN);
+
+ if (strlen(dir) > MAXPATHLEN - strlen(filename) - 1) {
+ LOG(log_error, logtype_default, "mangle: path is too large");
+ return filename;
+ }
+
+ /* Check to see if we already have a mangled filename by this name. */
+ while (1) {
+ strcpy(tmp, dir);
+ strncpy(mfilename, filename, MAX_LENGTH - strlen(MANGLE_CHAR) - MANGLE_LENGTH - ((ext != NULL)?strlen(ext):0));
+ strcat(mfilename, MANGLE_CHAR);
+ (void)sprintf(mangle_suffix, "%03d", mangle_suffix_int);
+ strcat(mfilename, mangle_suffix);
+
+ if (ext) {
+ strcat(mfilename, ext);
+ }
+
+ strcat(tmp, "/");
+ strcat(tmp, mfilename);
+
+ if (!cnid_mangle_get(vol->v_db, tmp)) {
+ break;
+ }
+ else {
+ if (++mangle_suffix_int > MAX_MANGLE_SUFFIX_LENGTH) {
+ LOG(log_error, logtype_default, "mangle: Failed to find a free mangle suffix; returning original filename");
+ return filename;
+ }
+ }
+ }
+
+ if (cnid_mangle_add(vol->v_db, mfilename, tmp) < 0) {
+ return filename;
+ }
+
+ filename = mfilename;
+
+ return filename;
+}
+#endif /* FILE_MANGLING */
--- /dev/null
+/*
+ * $Id: mangle.h,v 1.1 2002-05-29 18:02:59 jmarcus Exp $
+ *
+ */
+
+#ifndef AFPD_MANGLE_H
+#define AFPD_MANGLE_H 1
+
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#ifdef CNID_DB
+#include <atalk/cnid.h>
+#endif /* CNID_DB */
+#include <atalk/logger.h>
+
+#include "globals.h"
+#include "volume.h"
+#include "directory.h"
+
+#define MANGLE_CHAR "~"
+#define MANGLE_LENGTH 3 /* XXX This really can't be changed. */
+#define MAX_MANGLE_SUFFIX_LENGTH 999
+#define MAX_LENGTH 31
+
+extern char *mangle __P((const struct vol *, char *));
+extern char *demangle __P((const struct vol *, char *));
+
+#endif /* AFPD_MANGLE_H */
/*
- * $Id: ofork.c,v 1.14 2002-05-13 04:59:36 jmarcus Exp $
+ * $Id: ofork.c,v 1.15 2002-05-29 18:02:59 jmarcus Exp $
*
* Copyright (c) 1996 Regents of The University of Michigan.
* All Rights Reserved. See COPYRIGHT.
/* here's the deal: we allocate enough for the standard mac file length.
* in the future, we'll reallocate in fairly large jumps in case
* of long unicode names */
- if (( of->of_name =(char *)malloc(MACFILELEN + 1)) ==
+ if (( of->of_name =(char *)malloc(255 + 1)) ==
NULL ) {
LOG(log_error, logtype_afpd, "of_alloc: malloc: %s", strerror(errno) );
if (!ad)
oforks[ of_refnum ] = NULL;
return NULL;
}
- strncpy( of->of_name, path, of->of_namelen = MACFILELEN + 1);
+ strncpy( of->of_name, path, of->of_namelen = 255 + 1);
*ofrefnum = refnum;
of->of_refnum = refnum;
of_hash(of);
/* cnid_nextid.c */
extern cnid_t cnid_nextid __P((void *));
+/* cnid_mangle_* */
+extern int cnid_mangle_add __P((void *, char *, char *));
+extern char *cnid_mangle_get __P((void *, char *));
+
#endif /* include/atalk/cnid.h */
noinst_LTLIBRARIES = libcnid.la
-libcnid_la_SOURCES = cnid_add.c cnid_close.c cnid_delete.c cnid_get.c cnid_lookup.c cnid_open.c cnid_resolve.c cnid_update.c
+libcnid_la_SOURCES = cnid_add.c cnid_close.c cnid_delete.c cnid_get.c cnid_lookup.c cnid_mangle_add.c cnid_mangle_get.c cnid_open.c cnid_resolve.c cnid_update.c
noinst_HEADERS = cnid_meta.h cnid_private.h
/*
- * $Id: cnid_close.c,v 1.22 2002-02-01 19:51:09 jmarcus Exp $
+ * $Id: cnid_close.c,v 1.23 2002-05-29 18:02:59 jmarcus Exp $
*/
#ifdef HAVE_CONFIG_H
db->db_didname->close(db->db_didname, 0);
db->db_devino->close(db->db_devino, 0);
db->db_cnid->close(db->db_cnid, 0);
+#ifdef FILE_MANGLING
+ db->db_mangle->close(db->db_mangle, 0);
+#endif /* FILE_MANGLING */
db->dbenv->close(db->dbenv, 0);
if (db->lockfd > -1) {
--- /dev/null
+/*
+ * $Id: cnid_mangle_add.c,v 1.1 2002-05-29 18:02:59 jmarcus Exp $
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif /* HAVE_CONFIG_H */
+
+#ifdef FILE_MANGLING
+#include <stdio.h>
+#include <string.h>
+#include <sys/param.h>
+#include <sys/stat.h>
+#include <string.h>
+#include <atalk/logger.h>
+#include <errno.h>
+
+#include <db.h>
+#include <netatalk/endian.h>
+#include <atalk/adouble.h>
+#include <atalk/cnid.h>
+
+#include "cnid_private.h"
+
+/* Add a mangled filename. */
+int
+cnid_mangle_add(void *CNID, char *mfilename, char *filename)
+{
+ CNID_private *db;
+ DBT key, data;
+ DB_TXN *tid;
+ cnid_t id;
+ struct stat st;
+ int rc, ret;
+
+ if (!(db = CNID)) {
+ return -1;
+ }
+
+ memset(&key, 0, sizeof(key));
+ memset(&data, 0, sizeof(data));
+
+ key.data = mfilename;
+ key.size = strlen(mfilename) + 1;
+ data.data = filename;
+ data.size = strlen(filename) + 1;
+
+retry:
+ if ((rc = txn_begin(db->dbenv, NULL, &tid, 0)) != 0) {
+ LOG(log_error, logtype_default, "cnid_mangle_add: Failed to begin transaction: %s", db_strerror(rc));
+ return -1;
+ }
+
+ if ((rc = db->db_mangle->put(db->db_mangle, tid, &key, &data, 0))) {
+ if ((ret = txn_abort(tid)) != 0) {
+ LOG(log_error, logtype_default, "cnid_mangle_add: txn_abort: %s", db_strerror(ret));
+ return -1;
+ }
+ switch (rc) {
+ case DB_LOCK_DEADLOCK:
+ goto retry;
+ default:
+ LOG(log_error, logtype_default, "cnid_mangle_add: Failed to add mangled filename to the database: %s", db_strerror(rc));
+ return -1;
+ }
+ }
+
+ return 0;
+}
+#endif /* FILE_MANGLING */
--- /dev/null
+/*
+ * $Id: cnid_mangle_get.c,v 1.1 2002-05-29 18:02:59 jmarcus Exp $
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif /* HAVE_CONFIG_H */
+
+#ifdef FILE_MANGLING
+#include <stdio.h>
+#include <string.h>
+#include <sys/param.h>
+#include <sys/stat.h>
+#include <string.h>
+#include <atalk/logger.h>
+#include <errno.h>
+
+#include <db.h>
+#include <netatalk/endian.h>
+#include <atalk/adouble.h>
+#include <atalk/cnid.h>
+
+#include "cnid_private.h"
+
+/* Find a mangled filename entry. */
+char *
+cnid_mangle_get(void *CNID, char *mfilename)
+{
+ CNID_private *db;
+ DBT key, data;
+ DB_TXN *tid;
+ cnid_t id;
+ struct stat st;
+ char *filename;
+ int rc;
+
+ if (!(db = CNID)) {
+ return NULL;
+ }
+
+ memset(&key, 0, sizeof(key));
+ memset(&data, 0, sizeof(data));
+
+ key.data = mfilename;
+ key.size = strlen(mfilename) + 1;
+
+ while ((rc = db->db_didname->get(db->db_mangle, NULL, &key, &data, 0))) {
+ if (rc == DB_LOCK_DEADLOCK) {
+ continue;
+ }
+
+ if (rc == DB_NOTFOUND) {
+ return NULL;
+
+ }
+
+ return NULL;
+ }
+
+ filename = strrchr(data.data, '/');
+ filename++; /* Skip the leading '/' */
+
+ if (stat(data.data, &st) < 0) {
+ if (errno == ENOENT) {
+ /* The file no longer exists. Purge it from the database. */
+/*retry:
+ if ((rc = txn_begin(db->dbenv, NULL, &tid, 0)) != 0) {
+ LOG(log_error, logtype_default, "cnid_mangle_get: Failed to begin transaction: %s", db_strerror(rc));
+ return filename;
+ }
+
+ if ((rc = db->db_mangle->del(db->db_mangle, tid, &key, 0))) {
+ int ret;
+ if ((ret = txn_abort(tid)) != 0) {
+ LOG(log_error, logtype_default, "cnid_mangle_get: txn_abort: %s", db_strerror(ret));
+ return filename;
+ }
+ switch (rc) {
+ case DB_LOCK_DEADLOCK:
+ goto retry;
+ default:
+ LOG(log_error, logtype_default, "cnid_mangle_get: Unable to delete mangled file entry: %s", mfilename);
+ return filename;
+ }
+ }*/
+ return NULL;
+ }
+ }
+
+ return filename;
+}
+#endif /* FILE_MANGLING */
/*
- * $Id: cnid_open.c,v 1.38 2002-02-01 19:51:09 jmarcus Exp $
+ * $Id: cnid_open.c,v 1.39 2002-05-29 18:02:59 jmarcus Exp $
*
* Copyright (c) 1999. Adrian Sun (asun@zoology.washington.edu)
* All Rights Reserved. See COPYRIGHT.
#define DBDIDNAME "didname.db" /* did/full name mapping */
#define DBSHORTNAME "shortname.db" /* did/8+3 mapping */
#define DBMACNAME "macname.db" /* did/31 mapping */
+#define DBMANGLE "mangle.db" /* filename mangling */
#define DBLONGNAME "longname.db" /* did/unicode mapping */
#define DBLOCKFILE "cnid.lock"
#define DBRECOVERFILE "cnid.dbrecover"
goto fail_appinit;
}
+#ifdef FILE_MANGLING
+ /* filename mangling database. Use a hash for this one. */
+ if ((rc = db_create(&db->db_mangle, db->dbenv, 0)) != 0) {
+ LOG(log_error, logtype_default, "cnid_open: Failed to create mangle database: %s", db_strerror(rc));
+ db->db_didname->close(db->db_didname, 0);
+ db->db_devino->close(db->db_devino, 0);
+ db->db_cnid->close(db->db_cnid, 0);
+#ifdef EXTENDED_DB
+ db->db_macname->close(db->db_macname, 0);
+ db->db_shortname->close(db->db_shortname, 0);
+ db->db_longname->close(db->db_longname, 0);
+#endif /* EXTENDED_DB */
+ goto fail_appinit;
+ }
+
+ if ((rc = db->db_mangle->open(db->db_mangle, DBMANGLE, NULL, DB_HASH, open_flag, 0666)) != 0) {
+ LOG(log_error, logtype_default, "cnid_open: Failed to open mangle database: %s", db_strerror(rc));
+ db->db_didname->close(db->db_didname, 0);
+ db->db_devino->close(db->db_devino, 0);
+ db->db_cnid->close(db->db_cnid, 0);
+#ifdef EXTENDED_DB
+ db->db_macname->close(db->db_macname, 0);
+ db->db_shortname->close(db->db_shortname, 0);
+ db->db_longname->close(db->db_longname, 0);
+#endif /* EXTENDED_DB */
+ goto fail_appinit;
+ }
+#endif /* FILE_MANGLING */
+
/* Print out the version of DB3 we're linked against. */
LOG(log_info, logtype_default, "CNID DB initialized using %s",
db_version(NULL, NULL, NULL));
/*
- * $Id: cnid_private.h,v 1.9 2002-02-02 19:12:31 jmarcus Exp $
+ * $Id: cnid_private.h,v 1.10 2002-05-29 18:02:59 jmarcus Exp $
*/
#ifndef LIBATALK_CNID_PRIVATE_H
DB *db_cnid;
DB *db_didname;
DB *db_devino;
+ DB *db_mangle;
#ifdef EXTENDED_DB
DB *db_shortname;
DB *db_macname;