--- /dev/null
+Workaround for Network Trash and system without byte locking (broken nfs/afs)
+mangle OS9 "Network Trash Folder/Trash Can #2" name to
+"Network Trash Folder/Trash Can #2.<client ip>.<tcp port>"
+So multiple clients can share the same volume and have a working trash.
+
+Index: etc/afpd/directory.c
+===================================================================
+RCS file: /cvsroot/netatalk/netatalk/etc/afpd/directory.c,v
+retrieving revision 1.71.2.4.2.12
+diff -u -r1.71.2.4.2.12 directory.c
+--- etc/afpd/directory.c 11 Mar 2004 16:16:40 -0000 1.71.2.4.2.12
++++ etc/afpd/directory.c 21 Apr 2004 12:42:03 -0000
+@@ -554,6 +554,7 @@
+ * attempt to extend the current dir. tree to include path
+ * as a side-effect, movecwd to that point and return the new dir
+ */
++
+ static struct dir *
+ extenddir( vol, dir, path )
+ struct vol *vol;
+@@ -563,7 +564,25 @@
+ char *save_m_name;
+
+ if ( path->u_name == NULL) {
+- path->u_name = mtoupath(vol, path->m_name, dir->d_did, (path->m_type==3) );
++#ifdef DISABLE_LOCKING
++ int l = strlen(TRASH_PREFIX);
++ /* XXX replace mac name with unix name */
++ if (vol->v_trash_id && vol->v_trash_id == dir->d_did && vol->v_ip &&
++ !strncmp(TRASH_PREFIX , path->m_name, l ) )
++ {
++ static char temp[MAXPATHLEN + 1];
++ char *u;
++
++ strcpy(temp, path->m_name);
++ u = temp +l;
++ strcat(temp, ".");
++ strcat(temp, vol->v_ip);
++ path->u_name = temp;
++
++ }
++ else
++#endif
++ path->u_name = mtoupath(vol, path->m_name, dir->d_did, (path->m_type==3) );
+ }
+ path->dir = NULL;
+
+Index: etc/afpd/enumerate.c
+===================================================================
+RCS file: /cvsroot/netatalk/netatalk/etc/afpd/enumerate.c,v
+retrieving revision 1.39.2.2.2.4
+diff -u -r1.39.2.2.2.4 enumerate.c
+--- etc/afpd/enumerate.c 11 Mar 2004 02:01:59 -0000 1.39.2.2.2.4
++++ etc/afpd/enumerate.c 21 Apr 2004 12:42:04 -0000
+@@ -54,9 +54,39 @@
+ if (id == 0) {
+ return NULL;
+ }
++
++#ifdef DISABLE_LOCKING
++ if (!path->m_name) {
++ int l = strlen(TRASH_PREFIX);
++ /* XXX */
++ if (vol->v_trash_id && vol->v_trash_id == dir->d_did && vol->v_ip &&
++ !strncmp(TRASH_PREFIX , upath, l ) )
++ {
++ static char temp[MAXPATHLEN + 1];
++ char *u;
++
++ strcpy(temp, upath);
++ u = temp +l;
++
++ while (*u >= '0' && *u <= '9') {
++ u++;
++ }
++ if (*u == '.') {
++ *u = '\0';
++ }
++ path->m_name = temp;
++ }
++
++ else if(!(path->m_name = utompath(vol, upath, id , utf8_encoding()))) {
++ return NULL;
++ }
++ }
++#else
+ if (!path->m_name && !(path->m_name = utompath(vol, upath, id , utf8_encoding()))) {
+- return NULL;
++ return NULL;
+ }
++#endif
++
+ name = path->m_name;
+ if ((cdir = dirnew(name, upath)) == NULL) {
+ LOG(log_error, logtype_afpd, "adddir: malloc: %s", strerror(errno) );
+@@ -185,6 +215,32 @@
+ return name;
+ }
+
++#ifdef DISABLE_LOCKING
++/* ----------------------------- */
++int check_trash(const struct vol *vol, char *name)
++{
++int l = strlen(TRASH_PREFIX);
++char *u;
++
++ if (strncmp(TRASH_PREFIX , name, l))
++ return 0;
++ /* */
++ u = name +l;
++ while (*u >= '0' && *u <= '9') {
++ u++;
++ }
++
++ if (u == name +l)
++ return 0;
++
++ if (*u == '.' && !strcmp(vol->v_ip, u +1)) {
++ return 0;
++ }
++ /* hide this one */
++ return 1;
++}
++#endif
++
+ /* ----------------------------- */
+ int
+ for_each_dirent(const struct vol *vol, char *name, dir_loop fn, void *data)
+@@ -193,15 +249,28 @@
+ struct dirent *de;
+ char *m_name;
+ int ret;
++#ifdef DISABLE_LOCKING
++ int mangle_trash = 0;
++#endif
+
+ if (NULL == ( dp = opendir( name)) ) {
+ return -1;
+ }
++
++#ifdef DISABLE_LOCKING
++ if (vol->v_trash_id && vol->v_trash_id == curdir->d_did && !strcmp(name, ".")) {
++ mangle_trash = 1;
++ }
++#endif
+ ret = 0;
+ for ( de = readdir( dp ); de != NULL; de = readdir( dp )) {
+ if (!(m_name = check_dirent(vol, de->d_name)))
+ continue;
+
++#ifdef DISABLE_LOCKING
++ if (mangle_trash && check_trash(vol, de->d_name))
++ continue;
++#endif
+ ret++;
+ if (fn && fn(de,m_name, data) < 0) {
+ closedir(dp);
+Index: etc/afpd/volume.c
+===================================================================
+RCS file: /cvsroot/netatalk/netatalk/etc/afpd/volume.c,v
+retrieving revision 1.51.2.7.2.28
+diff -u -r1.51.2.7.2.28 volume.c
+--- etc/afpd/volume.c 6 Apr 2004 23:29:37 -0000 1.51.2.7.2.28
++++ etc/afpd/volume.c 21 Apr 2004 12:42:05 -0000
+@@ -73,7 +73,11 @@
+
+ static struct vol *Volumes = NULL;
+ static u_int16_t lastvid = 0;
+-static char *Trash = "\02\024Network Trash Folder";
++
++/* type, len, name */
++static char *Trash2 = "\02\024Network Trash Folder";
++/* type, hint (4 bytes), len (2bytes), name */
++static char *Trash3 = "\03\0\0\0\0\0\024Network Trash Folder";
+
+ static struct extmap *Extmap = NULL, *Defextmap = NULL;
+ static int Extmap_cnt;
+@@ -1038,6 +1042,10 @@
+ free(vol->v_forceuid);
+ free(vol->v_forcegid);
+ #endif /* FORCE_UIDGID */
++
++#ifdef DISABLE_LOCKING
++ free(vol->v_ip);
++#endif
+ }
+
+ /* ------------------------------- */
+@@ -1730,9 +1738,31 @@
+ goto openvol_err;
+ }
+ }
+- else {
+- p = Trash;
+- cname( volume, volume->v_dir, &p );
++#ifndef DISABLE_LOCKING
++ else
++#endif
++ {
++ struct path *s_path;
++
++ /* use the right name format */
++ p = (afp_version>= 30)?Trash3:Trash2;
++ s_path = cname( volume, volume->v_dir, &p );
++#ifdef DISABLE_LOCKING
++ if (s_path && *s_path->m_name == '\0' ) {
++ /* XXXX should do the same with ASP, could use volxlate but there's ':' in $p */
++ if (obj->proto == AFPPROTO_DSI) {
++ DSI *dsi = obj->handle;
++
++ /* cname moved into dest folder */
++ volume->v_trash_id = curdir->d_did;
++ volume->v_ip = malloc(MAXPATHLEN +1);
++ if (volume->v_ip) {
++ sprintf(volume->v_ip, "%s.%u", inet_ntoa(dsi->client.sin_addr),
++ ntohs(dsi->client.sin_port));
++ }
++ }
++ }
++#endif
+ }
+ return( AFP_OK );
+ }
+Index: etc/afpd/volume.h
+===================================================================
+RCS file: /cvsroot/netatalk/netatalk/etc/afpd/volume.h,v
+retrieving revision 1.19.2.5.2.6
+diff -u -r1.19.2.5.2.6 volume.h
+--- etc/afpd/volume.h 11 Mar 2004 02:02:04 -0000 1.19.2.5.2.6
++++ etc/afpd/volume.h 21 Apr 2004 12:42:05 -0000
+@@ -81,6 +81,12 @@
+ /* adouble indirection */
+ int (*validupath)(const struct vol *, const char *);
+ char *(*ad_path)(const char *, int);
++
++#ifdef DISABLE_LOCKING
++ /* for OS 9 trash when there's no working byte locking (afs, nfs) */
++ cnid_t v_trash_id;
++ char *v_ip;
++#endif
+ };
+
+ #ifdef NO_LARGE_VOL_SUPPORT
+@@ -167,6 +173,8 @@
+ #define VOLPBIT_BSIZE 11 /* block size */
+
+
++#define TRASH_PREFIX "Trash Can #"
++
+ #define vol_noadouble(vol) (((vol)->v_flags & AFPVOL_NOADOUBLE) ? \
+ ADFLAGS_NOADOUBLE : 0)
+ #ifdef AFP3x