+ ret = ret;
+ goto exit;
+ }
+
+ utf8 = utf8_encoding();
+ maxpath = (utf8) ? MAXPATHLEN - 7 : 255;
+
+ /* Get it from the database */
+ cnid = did;
+ if ((upath = cnid_resolve(vol->v_cdb, &cnid, buffer, buflen)) == NULL) {
+ afp_errno = AFPERR_NOOBJ;
+ err = 1;
+ goto exit;
+ }
+ if ((upath = strdup(upath)) == NULL) { /* 3 */
+ afp_errno = AFPERR_NOOBJ;
+ err = 1;
+ goto exit;
+ }
+ pdid = cnid;
+
+ /*
+ * Recurse up the tree, terminates in dirlookup when either
+ * - DIRDID_ROOT is hit
+ * - a cached entry is found
+ */
+ LOG(log_debug, logtype_afpd, "dirlookup(did: %u) {recursion for did: %u}", ntohl(pdid));
+ if ((pdir = dirlookup(vol, pdid)) == NULL) {
+ err = 1;
+ goto exit;
+ }
+
+ /* build the fullpath */
+ if ((fullpath = bstrcpy(pdir->d_fullpath)) == NULL
+ || bconchar(fullpath, '/') != BSTR_OK
+ || bcatcstr(fullpath, upath) != BSTR_OK) {
+ err = 1;
+ goto exit;
+ }
+
+ /* stat it and check if it's a dir */
+ LOG(log_debug, logtype_afpd, "dirlookup: {stating %s}", cfrombstr(fullpath));
+
+ if (stat(cfrombstr(fullpath), &st) != 0) { /* 5a */
+ switch (errno) {
+ case ENOENT:
+ afp_errno = AFPERR_NOOBJ;
+ err = 1;
+ goto exit;
+ case EPERM:
+ afp_errno = AFPERR_ACCESS;
+ err = 1;
+ goto exit;
+ default:
+ afp_errno = AFPERR_MISC;
+ err = 1;
+ goto exit;
+ }
+ } else {
+ if ( ! S_ISDIR(st.st_mode)) { /* 5b */
+ afp_errno = AFPERR_BADTYPE;
+ err = 1;
+ goto exit;
+ }
+ }
+
+ /* Get macname from unix name */
+ if ( (mpath = utompath(vol, upath, did, utf8)) == NULL ) {
+ afp_errno = AFPERR_NOOBJ;
+ err = 1;
+ goto exit;
+ }
+
+ /* Create struct dir */
+ if ((ret = dir_new(mpath, upath, vol, pdid, did, fullpath, st.st_ctime)) == NULL) { /* 6 */
+ LOG(log_error, logtype_afpd, "dirlookup(did: %u) {%s, %s}: %s", ntohl(did), mpath, upath, strerror(errno));
+ err = 1;
+ goto exit;
+ }
+
+ /* Add it to the cache only if it's a dir */
+ if (dircache_add(vol, ret) != 0) { /* 7 */
+ err = 1;
+ goto exit;