+ return !(k1->d_parent->d_did == k2->d_parent->d_did && !strcmp(k1->d_u_name, k2->d_u_name));
+}
+
+/* ---------------- */
+hash_t *
+dirhash(void)
+{
+ return hash_create(HASHCOUNT_T_MAX, hash_comp_dir, hash_fun_dir);
+}
+
+/* ------------------ */
+static struct path *invalidate (const struct vol *vol, struct dir *dir, struct path *ret)
+{
+ /* it's tricky:
+ movecwd failed some of dir path are not there anymore.
+ FIXME Is it true with other errors?
+ so we remove dir from the cache
+ */
+ if (dir->d_did == DIRDID_ROOT_PARENT)
+ return NULL;
+ if (afp_errno == AFPERR_ACCESS) {
+ if ( movecwd( vol, dir->d_parent ) < 0 ) {
+ return NULL;
+ }
+ /* FIXME should we set these?, don't need to call stat() after:
+ ret->st_valid = 1;
+ ret->st_errno = EACCES;
+ */
+ ret->m_name = dir->d_m_name;
+ ret->u_name = dir->d_u_name;
+ ret->d_dir = dir;
+ return ret;
+ } else if (afp_errno == AFPERR_NOOBJ) {
+ if ( movecwd( vol, dir->d_parent ) < 0 ) {
+ return NULL;
+ }
+ strcpy(ret->m_name, dir->d_m_name);
+ if (dir->d_m_name == dir->d_u_name) {
+ ret->u_name = ret->m_name;
+ }
+ else {
+ size_t tp = strlen(ret->m_name)+1;
+
+ ret->u_name = ret->m_name +tp;
+ strcpy(ret->u_name, dir->d_u_name);
+ }
+ /* FIXME should we set :
+ ret->st_valid = 1;
+ ret->st_errno = ENOENT;
+ */
+ dir_invalidate(vol, dir);
+ return ret;
+ }
+ dir_invalidate(vol, dir);
+ return NULL;
+}
+
+/* -------------------------------------------------- */
+/* cname
+ return
+ if it's a filename:
+ in extenddir:
+ compute unix name
+ stat the file or errno
+ return
+ filename
+ curdir: filename parent directory
+
+ if it's a dirname:
+ not in the cache
+ in extenddir
+ compute unix name
+ stat the dir or errno
+ return
+ if chdir error
+ dirname
+ curdir: dir parent directory
+ sinon
+ dirname: ""
+ curdir: dir
+ in the cache
+ return
+ if chdir error
+ dirname
+ curdir: dir parent directory
+ else
+ dirname: ""
+ curdir: dir
+
+*/
+struct path *
+cname( vol, dir, cpath )
+const struct vol *vol;
+struct dir *dir;
+char **cpath;
+{
+ struct dir *cdir, *scdir=NULL;
+ static char path[ MAXPATHLEN + 1];
+ static struct path ret;
+
+ char *data, *p;
+ int extend = 0;
+ int len;
+ u_int32_t hint;
+ u_int16_t len16;
+ int size = 0;
+ char sep;
+ int toUTF8 = 0;
+
+ data = *cpath;
+ afp_errno = AFPERR_NOOBJ;
+ memset(&ret, 0, sizeof(ret));
+ switch (ret.m_type = *data) { /* path type */
+ case 2:
+ data++;
+ len = (unsigned char) *data++;
+ size = 2;
+ sep = 0;
+ if (afp_version >= 30) {
+ ret.m_type = 3;
+ toUTF8 = 1;
+ }
+ break;
+ case 3:
+ if (afp_version >= 30) {
+ data++;
+ memcpy(&hint, data, sizeof(hint));
+ hint = ntohl(hint);
+ data += sizeof(hint);
+
+ memcpy(&len16, data, sizeof(len16));
+ len = ntohs(len16);
+ data += 2;
+ size = 7;
+ sep = 0; /* '/';*/
+ break;
+ }
+ /* else it's an error */
+ default:
+ afp_errno = AFPERR_PARAM;
+ return( NULL );
+ }
+ *cpath += len + size;
+ *path = '\0';
+ ret.m_name = path;