#include <atalk/bstrlib.h>
#include <atalk/bstradd.h>
#include <atalk/errchk.h>
+#include <atalk/globals.h>
+#include <atalk/fce_api.h>
#include "directory.h"
#include "dircache.h"
#include "fork.h"
#include "file.h"
#include "filedir.h"
-#include "globals.h"
#include "unix.h"
#include "mangle.h"
#include "hash.h"
*/
static int diroffcnt(struct dir *dir, struct stat *st)
{
- return st->st_ctime == dir->ctime;
+ return st->st_ctime == dir->d_ctime;
}
/* --------------------- */
l = bsplit(rpath, '/');
for (int i = 0; i < l->qty ; i++) { /* 3. */
did = cnid;
+ EC_ZERO(bcatcstr(statpath, "/"));
EC_ZERO(bconcat(statpath, l->entry[i]));
EC_ZERO_LOGSTR(lstat(cfrombstr(statpath), &st),
"lstat(rpath: %s, elem: %s): %s: %s",
if ((dir = dircache_search_by_name(vol, /* 5. */
dir,
cfrombstr(l->entry[i]),
- blength(l->entry[i]),
- st.st_ctime)) == NULL) {
+ blength(l->entry[i]))) == NULL) {
if ((cnid = cnid_add(vol->v_cdb, /* 6. */
&st,
did,
if ((dir = dirlookup(vol, cnid)) == NULL) /* 7. */
EC_FAIL;
}
-
- EC_ZERO(bcatcstr(statpath, "/"));
}
EC_CLEANUP:
* Resolve a DID, allocate a struct dir for it
* 1. Check for special CNIDs 0 (invalid), 1 and 2.
* 2a. Check if the DID is in the cache.
- * 2b. Check if it's really a dir (d_fullpath != NULL) because we cache files too.
+ * 2b. Check if it's really a dir because we cache files too.
* 3. If it's not in the cache resolve it via the database.
* 4. Build complete server-side path to the dir.
* 5. Check if it exists and is a directory.
int utf8;
int err = 0;
- LOG(log_debug, logtype_afpd, "dirlookup(did: %u)", ntohl(did));
+ LOG(log_debug, logtype_afpd, "dirlookup(did: %u): START", ntohl(did));
/* check for did 0, 1 and 2 */
if (did == 0 || vol == NULL) { /* 1 */
/* Search the cache */
if ((ret = dircache_search_by_did(vol, did)) != NULL) { /* 2a */
- if (ret->d_fullpath == NULL) { /* 2b */
+ if (ret->d_flags & DIRF_ISFILE) { /* 2b */
afp_errno = AFPERR_BADTYPE;
ret = NULL;
goto exit;
}
if (lstat(cfrombstr(ret->d_fullpath), &st) != 0) {
- LOG(log_debug, logtype_afpd, "dirlookup(did: %u) {lstat: %s}", ntohl(did), strerror(errno));
+ LOG(log_debug, logtype_afpd, "dirlookup(did: %u, path: \"%s\"): lstat: %s",
+ ntohl(did), cfrombstr(ret->d_fullpath), strerror(errno));
switch (errno) {
case ENOENT:
case ENOTDIR:
/* It's not there anymore, so remove it */
- LOG(log_debug, logtype_afpd, "dirlookup(did: %u) {calling dir_remove()}", ntohl(did));
+ LOG(log_debug, logtype_afpd, "dirlookup(did: %u): calling dir_remove", ntohl(did));
dir_remove(vol, ret);
afp_errno = AFPERR_NOOBJ;
ret = NULL;
/* Get it from the database */
cnid = did;
+ LOG(log_debug, logtype_afpd, "dirlookup(did: %u): querying CNID database", ntohl(did));
if ((upath = cnid_resolve(vol->v_cdb, &cnid, buffer, buflen)) == NULL) {
afp_errno = AFPERR_NOOBJ;
err = 1;
* - DIRDID_ROOT is hit
* - a cached entry is found
*/
- LOG(log_debug, logtype_afpd, "dirlookup(did: %u) {recursion for did: %u}", ntohl(pdid));
+ LOG(log_debug, logtype_afpd, "dirlookup(did: %u): recursion for did: %u",
+ ntohl(did), ntohl(pdid));
if ((pdir = dirlookup(vol, pdid)) == NULL) {
err = 1;
goto exit;
}
/* stat it and check if it's a dir */
- LOG(log_debug, logtype_afpd, "dirlookup: {stating %s}", cfrombstr(fullpath));
+ LOG(log_debug, logtype_afpd, "dirlookup(did: %u): stating \"%s\"",
+ ntohl(did), cfrombstr(fullpath));
- if (stat(cfrombstr(fullpath), &st) != 0) { /* 5a */
+ if (lstat(cfrombstr(fullpath), &st) != 0) { /* 5a */
switch (errno) {
case ENOENT:
afp_errno = AFPERR_NOOBJ;
}
/* Create struct dir */
- if ((ret = dir_new(mpath, upath, vol, pdid, did, fullpath, st.st_ctime)) == NULL) { /* 6 */
+ if ((ret = dir_new(mpath, upath, vol, pdid, did, fullpath, &st)) == NULL) { /* 6 */
LOG(log_error, logtype_afpd, "dirlookup(did: %u) {%s, %s}: %s", ntohl(did), mpath, upath, strerror(errno));
err = 1;
goto exit;
}
}
if (ret)
- LOG(log_debug, logtype_afpd, "dirlookup(did: %u): pdid: %u, \"%s\"",
+ LOG(log_debug, logtype_afpd, "dirlookup(did: %u): RESULT: pdid: %u, path: \"%s\"",
ntohl(ret->d_did), ntohl(ret->d_pdid), cfrombstr(ret->d_fullpath));
return ret;
* @param vol (r) pointer to struct vol
* @param pdid (r) Parent CNID
* @param did (r) CNID
- * @param path (r) Full unix path to dir or NULL for files
- * @param ctime (r) st_ctime from stat
+ * @param path (r) Full unix path to object
+ * @param st (r) struct stat of object
*
* @returns pointer to new struct dir or NULL on error
*
cnid_t pdid,
cnid_t did,
bstring path,
- time_t ctime)
+ struct stat *st)
{
struct dir *dir;
dir->d_pdid = pdid;
dir->d_vid = vol->v_vid;
dir->d_fullpath = path;
- dir->ctime_dircache = ctime;
+ dir->dcache_ctime = st->st_ctime;
+ dir->dcache_ino = st->st_ino;
+ if (!S_ISDIR(st->st_mode))
+ dir->d_flags = DIRF_ISFILE;
+ dir->d_rights_cache = 0xffffffff;
return dir;
}
AFP_ASSERT(path);
AFP_ASSERT(len > 0);
- if ((cdir = dircache_search_by_name(vol, dir, path->u_name, strlen(path->u_name), path->st.st_ctime)) != NULL) {
+ if ((cdir = dircache_search_by_name(vol, dir, path->u_name, strlen(path->u_name))) != NULL) {
/* there's a stray entry in the dircache */
LOG(log_debug, logtype_afpd, "dir_add(did:%u,'%s/%s'): {stray cache entry: did:%u,'%s', removing}",
ntohl(dir->d_did), cfrombstr(dir->d_fullpath), path->u_name,
}
/* Allocate and initialize struct dir */
- if ((cdir = dir_new( path->m_name, path->u_name, vol, dir->d_did, id, fullpath, path->st.st_ctime)) == NULL) { /* 3 */
+ if ((cdir = dir_new(path->m_name,
+ path->u_name,
+ vol,
+ dir->d_did,
+ id,
+ fullpath,
+ &path->st)) == NULL) { /* 3 */
err = 4;
goto exit;
}
/* Search the cache */
int unamelen = strlen(ret.u_name);
- cdir = dircache_search_by_name(vol, dir, ret.u_name, unamelen, ret.st.st_ctime); /* 14 */
+ cdir = dircache_search_by_name(vol, dir, ret.u_name, unamelen); /* 14 */
if (cdir == NULL) {
/* Not in cache, create one */
if ((cdir = dir_add(vol, dir, &ret, unamelen)) == NULL) { /* 15 */
/* --------------------- */
void setdiroffcnt(struct dir *dir, struct stat *st, u_int32_t count)
{
- dir->offcnt = count;
- dir->ctime = st->st_ctime;
+ dir->d_offcnt = count;
+ dir->d_ctime = st->st_ctime;
dir->d_flags &= ~DIRF_CNID;
}
*/
int dirreenumerate(struct dir *dir, struct stat *st)
{
- return st->st_ctime == dir->ctime && (dir->d_flags & DIRF_CNID);
+ return st->st_ctime == dir->d_ctime && (dir->d_flags & DIRF_CNID);
}
/* ------------------------------
isad = 1;
if (ad.ad_md->adf_flags & O_CREAT) {
/* We just created it */
+ if (s_path->m_name == NULL) {
+ if ((s_path->m_name = utompath(vol,
+ upath,
+ dir->d_did,
+ utf8_encoding())) == NULL) {
+ LOG(log_error, logtype_afpd,
+ "getdirparams(\"%s\"): can't assign macname",
+ cfrombstr(dir->d_fullpath));
+ return AFPERR_MISC;
+ }
+ }
ad_setname(&ad, s_path->m_name);
ad_setid( &ad,
s_path->st.st_dev,
ashort = 0;
/* this needs to handle current directory access rights */
if (diroffcnt(dir, st)) {
- ashort = (dir->offcnt > 0xffff)?0xffff:dir->offcnt;
+ ashort = (dir->d_offcnt > 0xffff)?0xffff:dir->d_offcnt;
}
else if ((ret = for_each_dirent(vol, upath, NULL,NULL)) >= 0) {
setdiroffcnt(dir, st, ret);
- ashort = (dir->offcnt > 0xffff)?0xffff:dir->offcnt;
+ ashort = (dir->d_offcnt > 0xffff)?0xffff:dir->d_offcnt;
}
ashort = htons( ashort );
memcpy( data, &ashort, sizeof( ashort ));
return AFPERR_MISC;
}
- curdir->offcnt++;
+ curdir->d_offcnt++;
if ((dir = dir_add(vol, curdir, s_path, strlen(s_path->u_name))) == NULL) {
return AFPERR_MISC;
ad_setname(&ad, s_path->m_name);
ad_setid( &ad, s_path->st.st_dev, s_path->st.st_ino, dir->d_did, did, vol->v_stamp);
+ fce_register_new_dir(s_path);
+
ad_flush( &ad);
ad_close_metadata( &ad);
rbuf += sizeof( id );
*rbuflen = 2 * sizeof( id );
break;
- case UUID_LOCAL:
- free(name);
- return (AFPERR_NOITEM);
default:
return AFPERR_MISC;
}