+/* ------------------ */
+static hash_val_t hash_fun_dir(const void *key)
+{
+const struct dir *k = key;
+
+ static unsigned long randbox[] = {
+ 0x49848f1bU, 0xe6255dbaU, 0x36da5bdcU, 0x47bf94e9U,
+ 0x8cbcce22U, 0x559fc06aU, 0xd268f536U, 0xe10af79aU,
+ 0xc1af4d69U, 0x1d2917b5U, 0xec4c304dU, 0x9ee5016cU,
+ 0x69232f74U, 0xfead7bb3U, 0xe9089ab6U, 0xf012f6aeU,
+ };
+
+ const unsigned char *str = k->d_u_name;
+ hash_val_t acc = 0;
+
+ while (*str) {
+ acc ^= randbox[(*str + acc) & 0xf];
+ acc = (acc << 1) | (acc >> 31);
+ acc &= 0xffffffffU;
+ acc ^= randbox[((*str++ >> 4) + acc) & 0xf];
+ acc = (acc << 2) | (acc >> 30);
+ acc &= 0xffffffffU;
+ }
+ return acc;
+}
+
+/* ---------------- */
+static int hash_comp_dir(const void *key1, const void *key2)
+{
+const struct dir *k1 = key1;
+const struct dir *k2 = key2;
+
+ 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;
+}
+