]> arthur.barton.de Git - netatalk.git/commitdiff
Fix fce merge conflict
authorFrank Lahm <franklahm@googlemail.com>
Tue, 24 May 2011 12:32:02 +0000 (14:32 +0200)
committerFrank Lahm <franklahm@googlemail.com>
Tue, 24 May 2011 12:32:02 +0000 (14:32 +0200)
1  2 
etc/afpd/afp_options.c
etc/afpd/directory.c
etc/afpd/file.c
etc/afpd/filedir.c
etc/afpd/fork.c
etc/afpd/fork.h
etc/afpd/ofork.c

index f3724c13cdbd6d05f8403b6a753839e9c1f207c0,ff807404b36df7955379934ff0738544446bf3da..9bb48042fa1e98ffdb5033edf70173995c310740
  #include "globals.h"
  #include "status.h"
  #include "auth.h"
 +#include "dircache.h"
+ #include "fce_api.h"
  
 -#include <atalk/compat.h>
 -
 -#ifdef ADMIN_GRP
 -#include <grp.h>
 -#include <sys/types.h>
 -#endif /* ADMIN_GRP */
 -
  #ifndef MIN
  #define MIN(a, b)  ((a) < (b) ? (a) : (b))
  #endif /* MIN */
@@@ -469,15 -449,16 +470,24 @@@ int afp_options_parseline(char *buf, st
      if ((c = getoption(buf, "-ntseparator")) && (opt = strdup(c)))
         options->ntseparator = opt;
  
 -
 +    if ((c = getoption(buf, "-dircachesize")))
 +        options->dircachesize = atoi(c);
 +     
 +    if ((c = getoption(buf, "-tcpsndbuf")))
 +        options->tcp_sndbuf = atoi(c);
 +
 +    if ((c = getoption(buf, "-tcprcvbuf")))
 +        options->tcp_rcvbuf = atoi(c);
 +
+       if ((c = getoption(buf, "-fcelistener"))) {
+               LOG(log_note, logtype_afpd, "Adding fce listener \"%s\"", c);
+               fce_add_udp_socket(c);
+       }
+       if ((c = getoption(buf, "-fcecoalesce"))) {
+               LOG(log_ote, logtype_afpd, "Fce coalesce: %s", c);
+               fce_set_coalesce(c);
+       }
      return 1;
  }
  
index b981af66c03fb6c4b94cff562402dcc78dbcd13d,4544d28e153084897194e44f1286c0952f501aba..06ad94f3f10768e5fb9d380237c501ad14839b99
  #include "unix.h"
  #include "mangle.h"
  #include "hash.h"
+ #include "fce_api.h"
  
 -#ifdef HAVE_NFSv4_ACLS
 -extern void addir_inherit_acl(const struct vol *vol);
 -#endif
 -
 -/* 
 - * Directory caches
 - * ================
 - *
 - * There are currently two cache structures where afpd caches directory information
 - * a) a DID/dirname cache in a hashtable 
 - * b) a (red-black) tree with CNIDs as key
 - *
 - * a) is for searching by DID/dirname
 - * b) is for searching by CNID
 - *
 - * Through additional parent, child, previous and next pointers, b) is also used to
 - * represent the on-disk layout of the filesystem. parent and child point to parent
 - * and child directory respectively, linking 2 or more subdirectories in one
 - * directory with previous and next pointers.
 - *
 - * Usage examples, highlighting the main functions:
 - * 
 - * a) is eg used in enumerate():
 - * if IS_DIR
 - *     dir = dirsearch_byname() // search in cache
 - *     if (dir == NULL)         // not found
 - *         dir = adddir()       // add to cache
 - *      getdirparams()
 - *
 - * b) is eg used in afp_getfildirparams()
 - * dirlookup()             // wrapper for cache and db search
 - *   => dir = dirsearch()  // search in cache
 - *      if (dir)           // found
 - *          return
 - *      else               // not found,
 - *          cnid_resolve() // resolve with CNID database
 - *      cname()            // add to cache
 +/*
 + * FIXMEs, loose ends after the dircache rewrite:
 + * o merge dircache_search_by_name and dir_add ??
 + * o case-insensitivity is gone from cname
   */
  
 -struct dir  *curdir;
 -int         afp_errno;
 -
 -#define SENTINEL (&sentinel)
 -static struct dir sentinel = { SENTINEL, SENTINEL, NULL, /* left, right, back */
 -                               DIRTREE_COLOR_BLACK,      /* color */
 -                               NULL, NULL,               /* parent, child */
 -                               NULL, NULL,               /* previous, next */
 -                               NULL, 0, 0,               /* oforks, did, flags */
 -                               0, 0,                     /* ctime, offcnt */
 -                               NULL, NULL, NULL};        /* mname, uname, ucs2-name */
 -static struct dir rootpar  = { SENTINEL, SENTINEL, NULL,
 -                               0,
 -                               NULL, NULL,
 -                               NULL, NULL,
 -                               NULL, 0, 0,
 -                               0, 0,
 -                               NULL, NULL, NULL};
 -
 -/* (from IM: Toolbox Essentials)
 - * dirFinderInfo (DInfo) fields:
 - * field        bytes
 - * frRect       8    folder's window rectangle
 - * frFlags      2    flags
 - * frLocation   4    folder's location in window
 - * frView       2    folder's view (default == closedView (256))
 - *
 - * extended dirFinderInfo (DXInfo) fields:
 - * frScroll     4    scroll position
 - * frOpenChain: 4    directory ID chain of open folders
 - * frScript:    1    script flag and code
 - * frXFlags:    1    reserved
 - * frComment:   2    comment ID
 - * frPutAway:   4    home directory ID
 - */
  
 -static struct dir *
 -vol_tree_root(const struct vol *vol, u_int32_t did)
 -{
 -    struct dir *dir;
 +/*******************************************************************************************
 + * Globals
 + ******************************************************************************************/
  
 -    if (vol->v_curdir && vol->v_curdir->d_did == did) {
 -        dir = vol->v_curdir;
 -    }
 -    else {
 -        dir = vol->v_root;
 -    }
 -    return dir;
 -}
 +int         afp_errno;
 +/* As long as directory.c hasn't got its own init call, this get initialized in dircache_init */
 +struct dir rootParent  = {
 +    NULL, NULL, NULL, NULL,          /* path, d_m_name, d_u_name, d_m_name_ucs2 */
 +    NULL, 0, 0,                      /* qidx_node, ctime, d_flags */
 +    0, 0, 0, 0                       /* pdid, did, offcnt, d_vid */
 +};
 +struct dir  *curdir = &rootParent;
 +struct path Cur_Path = {
 +    0,
 +    "",  /* mac name */
 +    ".", /* unix name */
 +    0,   /* id */
 +    NULL,/* struct dir * */
 +    0,   /* stat is not set */
 +    0,   /* errno */
 +    {0} /* struct stat */
 +};
  
  /*
 - * redid did assignment for directories. now we use red-black trees.
 - * how exciting.
 + * dir_remove queues struct dirs to be freed here. We can't just delete them immeidately
 + * eg in dircache_search_by_id, because a caller somewhere up the stack might be
 + * referencing it.
 + * So instead:
 + * - we mark it as invalid by setting d_did to CNID_INVALID (ie 0)
 + * - queue it in "invalid_dircache_entries" queue
 + * - which is finally freed at the end of every AFP func in afp_dsi.c.
   */
 -struct dir *
 -dirsearch(const struct vol *vol, u_int32_t did)
 -{
 -    struct dir  *dir;
 +q_t *invalid_dircache_entries;
  
  
 -    /* check for 0 did */
 -    if (!did) {
 -        afp_errno = AFPERR_PARAM;
 -        return NULL;
 -    }
 -    if ( did == DIRDID_ROOT_PARENT ) {
 -        if (!rootpar.d_did)
 -            rootpar.d_did = DIRDID_ROOT_PARENT;
 -        rootpar.d_child = vol->v_dir;
 -        return( &rootpar );
 -    }
 -
 -    dir = vol_tree_root(vol, did);
 +/*******************************************************************************************
 + * Locals
 + ******************************************************************************************/
  
 -    afp_errno = AFPERR_NOOBJ;
 -    while ( dir != SENTINEL ) {
 -        if (dir->d_did == did)
 -            return dir->d_m_name ? dir : NULL;
 -        dir = (dir->d_did > did) ? dir->d_left : dir->d_right;
 -    }
 -    return NULL;
 -}
  
 -/* ------------------- */
 -int get_afp_errno(const int param)
 +/* -------------------------
 +   appledouble mkdir afp error code.
 +*/
 +static int netatalk_mkdir(const struct vol *vol, const char *name)
  {
 -    if (afp_errno != AFPERR_DID1)
 -        return afp_errno;
 -    return param;
 -}
 +    int ret;
 +    struct stat st;
  
 -/* ------------------- */
 -struct dir *
 -dirsearch_byname( const struct vol *vol, struct dir *cdir, char *name)
 -{
 -    struct dir *dir = NULL;
 +    if (vol->v_flags & AFPVOL_UNIX_PRIV) {
 +        if (lstat(".", &st) < 0)
 +            return AFPERR_MISC;
 +        int mode = (DIRBITS & (~S_ISGID & st.st_mode)) | (0777 & ~vol->v_umask);
 +        LOG(log_maxdebug, logtype_afpd, "netatalk_mkdir(\"%s\") {parent mode: %04o, vol umask: %04o}",
 +            name, st.st_mode, vol->v_umask);
  
 -    if ((cdir->d_did != DIRDID_ROOT_PARENT) && (cdir->d_child)) {
 -        struct dir key;
 -        hnode_t *hn;
 +        ret = mkdir(name, mode);
 +    } else {
 +        ret = ad_mkdir(name, DIRBITS | 0777);
 +    }
  
 -        key.d_parent = cdir;
 -        key.d_u_name = name;
 -        hn = hash_lookup(vol->v_hash, &key);
 -        if (hn) {
 -            dir = hnode_get(hn);
 +    if (ret < 0) {
 +        switch ( errno ) {
 +        case ENOENT :
 +            return( AFPERR_NOOBJ );
 +        case EROFS :
 +            return( AFPERR_VLOCK );
 +        case EPERM:
 +        case EACCES :
 +            return( AFPERR_ACCESS );
 +        case EEXIST :
 +            return( AFPERR_EXIST );
 +        case ENOSPC :
 +        case EDQUOT :
 +            return( AFPERR_DFULL );
 +        default :
 +            return( AFPERR_PARAM );
          }
      }
 -    return dir;
 +    return AFP_OK;
  }
  
 -/* -----------------------------------------
 - * if did is not in the cache resolve it with cnid
 - *
 - * FIXME
 - * OSX call it with bogus id, ie file ID not folder ID,
 - * and we are really bad in this case.
 - */
 -struct dir *
 -dirlookup( struct vol *vol, u_int32_t did)
 +/* ------------------- */
 +static int deletedir(int dirfd, char *dir)
  {
 -    struct dir   *ret;
 -    char     *upath;
 -    cnid_t       id, cnid;
 -    static char  path[MAXPATHLEN + 1];
 -    size_t len,  pathlen;
 -    char         *ptr;
 -    static char  buffer[12 + MAXPATHLEN + 1];
 -    int          buflen = 12 + MAXPATHLEN + 1;
 -    char         *mpath;
 -    int          utf8;
 -    size_t       maxpath;
 +    char path[MAXPATHLEN + 1];
 +    DIR *dp;
 +    struct dirent   *de;
 +    struct stat st;
 +    size_t len;
 +    int err = AFP_OK;
 +    size_t remain;
  
 -    ret = dirsearch(vol, did);
 -    if (ret != NULL || afp_errno == AFPERR_PARAM)
 -        return ret;
 +    if ((len = strlen(dir)) +2 > sizeof(path))
 +        return AFPERR_PARAM;
  
 -    utf8 = utf8_encoding();
 -    maxpath = (utf8)?MAXPATHLEN -7:255;
 -    id = did;
 -    if (NULL == (upath = cnid_resolve(vol->v_cdb, &id, buffer, buflen)) ) {
 -        afp_errno = AFPERR_NOOBJ;
 -        return NULL;
 -    }
 -    ptr = path + MAXPATHLEN;
 -    if (NULL == ( mpath = utompath(vol, upath, did, utf8) ) ) {
 -        afp_errno = AFPERR_NOOBJ;
 -        return NULL;
 -    }
 -    len = strlen(mpath);
 -    pathlen = len;          /* no 0 in the last part */
 +    /* already gone */
 +    if ((dp = opendirat(dirfd, dir)) == NULL)
 +        return AFP_OK;
 +
 +    strcpy(path, dir);
 +    strcat(path, "/");
      len++;
 -    strcpy(ptr - len, mpath);
 -    ptr -= len;
 -    while (1) {
 -        ret = dirsearch(vol,id);
 -        if (ret != NULL) {
 +    remain = sizeof(path) -len -1;
 +    while ((de = readdir(dp)) && err == AFP_OK) {
 +        /* skip this and previous directory */
 +        if (!strcmp(de->d_name, ".") || !strcmp(de->d_name, ".."))
 +            continue;
 +
 +        if (strlen(de->d_name) > remain) {
 +            err = AFPERR_PARAM;
              break;
          }
 -        cnid = id;
 -        if ( NULL == (upath = cnid_resolve(vol->v_cdb, &id, buffer, buflen))
 -             ||
 -             NULL == (mpath = utompath(vol, upath, cnid, utf8))
 -            ) {
 -            afp_errno = AFPERR_NOOBJ;
 -            return NULL;
 +        strcpy(path + len, de->d_name);
 +        if (lstatat(dirfd, path, &st)) {
 +            continue;
          }
 -
 -        len = strlen(mpath) + 1;
 -        pathlen += len;
 -        if (pathlen > maxpath) {
 -            afp_errno = AFPERR_PARAM;
 -            return NULL;
 +        if (S_ISDIR(st.st_mode)) {
 +            err = deletedir(dirfd, path);
 +        } else {
 +            err = netatalk_unlinkat(dirfd, path);
          }
 -        strcpy(ptr - len, mpath);
 -        ptr -= len;
 -    }
 -
 -    /* fill the cache, another place where we know about the path type */
 -    if (utf8) {
 -        u_int16_t temp16;
 -        u_int32_t temp;
 -
 -        ptr -= 2;
 -        temp16 = htons(pathlen);
 -        memcpy(ptr, &temp16, sizeof(temp16));
 -
 -        temp = htonl(kTextEncodingUTF8);
 -        ptr -= 4;
 -        memcpy(ptr, &temp, sizeof(temp));
 -        ptr--;
 -        *ptr = 3;
 -    }
 -    else {
 -        ptr--;
 -        *ptr = (unsigned char)pathlen;
 -        ptr--;
 -        *ptr = 2;
      }
 -    /* cname is not efficient */
 -    if (cname( vol, ret, &ptr ) == NULL )
 -        return NULL;
 -
 -    return dirsearch(vol, did);
 -}
 +    closedir(dp);
  
 -/* child addition/removal */
 -static void dirchildadd(const struct vol *vol, struct dir *a, struct dir *b)
 -{
 -    if (!a->d_child)
 -        a->d_child = b;
 -    else {
 -        b->d_next = a->d_child;
 -        b->d_prev = b->d_next->d_prev;
 -        b->d_next->d_prev = b;
 -        b->d_prev->d_next = b;
 -    }
 -    if (!hash_alloc_insert(vol->v_hash, b, b)) {
 -        LOG(log_error, logtype_afpd, "dirchildadd: can't hash %s", b->d_u_name);
 +    /* okay. the directory is empty. delete it. note: we already got rid
 +       of .AppleDouble.  */
 +    if (err == AFP_OK) {
 +        err = netatalk_rmdir(dirfd, dir);
      }
 +    return err;
  }
  
 -static void dirchildremove(struct dir *a,struct dir *b)
 -{
 -    if (a->d_child == b)
 -        a->d_child = (b == b->d_next) ? NULL : b->d_next;
 -    b->d_next->d_prev = b->d_prev;
 -    b->d_prev->d_next = b->d_next;
 -    b->d_next = b->d_prev = b;
 -}
 -
 -/* --------------------------- */
 -/* rotate the tree to the left */
 -static void dir_leftrotate(struct vol *vol, struct dir *dir)
 +/* do a recursive copy. */
 +static int copydir(const struct vol *vol, int dirfd, char *src, char *dst)
  {
 -    struct dir *right = dir->d_right;
 +    char spath[MAXPATHLEN + 1], dpath[MAXPATHLEN + 1];
 +    DIR *dp;
 +    struct dirent   *de;
 +    struct stat st;
 +    struct utimbuf      ut;
 +    size_t slen, dlen;
 +    size_t srem, drem;
 +    int err;
  
 -    /* whee. move the right's left tree into dir's right tree */
 -    dir->d_right = right->d_left;
 -    if (right->d_left != SENTINEL)
 -        right->d_left->d_back = dir;
 +    /* doesn't exist or the path is too long. */
 +    if (((slen = strlen(src)) > sizeof(spath) - 2) ||
 +        ((dlen = strlen(dst)) > sizeof(dpath) - 2) ||
 +        ((dp = opendirat(dirfd, src)) == NULL))
 +        return AFPERR_PARAM;
  
 -    if (right != SENTINEL) {
 -        right->d_back = dir->d_back;
 -        right->d_left = dir;
 +    /* try to create the destination directory */
 +    if (AFP_OK != (err = netatalk_mkdir(vol, dst)) ) {
 +        closedir(dp);
 +        return err;
      }
  
 -    if (!dir->d_back) /* no parent. move the right tree to the top. */
 -        vol->v_root = right;
 -    else if (dir == dir->d_back->d_left) /* we were on the left */
 -        dir->d_back->d_left = right;
 -    else
 -        dir->d_back->d_right = right; /* we were on the right */
 -
 -    /* re-insert dir on the left tree */
 -    if (dir != SENTINEL)
 -        dir->d_back = right;
 -}
 -
 -
 -
 -/* rotate the tree to the right */
 -static void dir_rightrotate(struct vol *vol, struct dir *dir)
 -{
 -    struct dir *left = dir->d_left;
 -
 -    /* whee. move the left's right tree into dir's left tree */
 -    dir->d_left = left->d_right;
 -    if (left->d_right != SENTINEL)
 -        left->d_right->d_back = dir;
 +    /* set things up to copy */
 +    strcpy(spath, src);
 +    strcat(spath, "/");
 +    slen++;
 +    srem = sizeof(spath) - slen -1;
  
 -    if (left != SENTINEL) {
 -        left->d_back = dir->d_back;
 -        left->d_right = dir;
 -    }
 +    strcpy(dpath, dst);
 +    strcat(dpath, "/");
 +    dlen++;
 +    drem = sizeof(dpath) - dlen -1;
  
 -    if (!dir->d_back) /* no parent. move the left tree to the top. */
 -        vol->v_root = left;
 -    else if (dir == dir->d_back->d_right) /* we were on the right */
 -        dir->d_back->d_right = left;
 -    else
 -        dir->d_back->d_left = left; /* we were on the left */
 +    err = AFP_OK;
 +    while ((de = readdir(dp))) {
 +        /* skip this and previous directory */
 +        if (!strcmp(de->d_name, ".") || !strcmp(de->d_name, ".."))
 +            continue;
  
 -    /* re-insert dir on the right tree */
 -    if (dir != SENTINEL)
 -        dir->d_back = left;
 -}
 +        if (strlen(de->d_name) > srem) {
 +            err = AFPERR_PARAM;
 +            break;
 +        }
 +        strcpy(spath + slen, de->d_name);
  
 -#if 0
 -/* recolor after a removal */
 -static struct dir *dir_rmrecolor(struct vol *vol, struct dir *dir)
 -{
 -    struct dir *leaf;
 -
 -    while ((dir != vol->v_root) && (dir->d_color == DIRTREE_COLOR_BLACK)) {
 -        /* are we on the left tree? */
 -        if (dir == dir->d_back->d_left) {
 -            leaf = dir->d_back->d_right; /* get right side */
 -            if (leaf->d_color == DIRTREE_COLOR_RED) {
 -                /* we're red. we need to change to black. */
 -                leaf->d_color = DIRTREE_COLOR_BLACK;
 -                dir->d_back->d_color = DIRTREE_COLOR_RED;
 -                dir_leftrotate(vol, dir->d_back);
 -                leaf = dir->d_back->d_right;
 +        if (lstatat(dirfd, spath, &st) == 0) {
 +            if (strlen(de->d_name) > drem) {
 +                err = AFPERR_PARAM;
 +                break;
              }
 +            strcpy(dpath + dlen, de->d_name);
  
 -            /* right leaf has black end nodes */
 -            if ((leaf->d_left->d_color == DIRTREE_COLOR_BLACK) &&
 -                (leaf->d_right->d_color = DIRTREE_COLOR_BLACK)) {
 -                leaf->d_color = DIRTREE_COLOR_RED; /* recolor leaf as red */
 -                dir = dir->d_back; /* ascend */
 -            } else {
 -                if (leaf->d_right->d_color == DIRTREE_COLOR_BLACK) {
 -                    leaf->d_left->d_color = DIRTREE_COLOR_BLACK;
 -                    leaf->d_color = DIRTREE_COLOR_RED;
 -                    dir_rightrotate(vol, leaf);
 -                    leaf = dir->d_back->d_right;
 -                }
 -                leaf->d_color = dir->d_back->d_color;
 -                dir->d_back->d_color = DIRTREE_COLOR_BLACK;
 -                leaf->d_right->d_color = DIRTREE_COLOR_BLACK;
 -                dir_leftrotate(vol, dir->d_back);
 -                dir = vol->v_root;
 -            }
 -        } else { /* right tree */
 -            leaf = dir->d_back->d_left; /* left tree */
 -            if (leaf->d_color == DIRTREE_COLOR_RED) {
 -                leaf->d_color = DIRTREE_COLOR_BLACK;
 -                dir->d_back->d_color = DIRTREE_COLOR_RED;
 -                dir_rightrotate(vol, dir->d_back);
 -                leaf = dir->d_back->d_left;
 -            }
 +            if (S_ISDIR(st.st_mode)) {
 +                if (AFP_OK != (err = copydir(vol, dirfd, spath, dpath)))
 +                    goto copydir_done;
 +            } else if (AFP_OK != (err = copyfile(vol, vol, dirfd, spath, dpath, NULL, NULL))) {
 +                goto copydir_done;
  
 -            /* left leaf has black end nodes */
 -            if ((leaf->d_right->d_color == DIRTREE_COLOR_BLACK) &&
 -                (leaf->d_left->d_color = DIRTREE_COLOR_BLACK)) {
 -                leaf->d_color = DIRTREE_COLOR_RED; /* recolor leaf as red */
 -                dir = dir->d_back; /* ascend */
              } else {
 -                if (leaf->d_left->d_color == DIRTREE_COLOR_BLACK) {
 -                    leaf->d_right->d_color = DIRTREE_COLOR_BLACK;
 -                    leaf->d_color = DIRTREE_COLOR_RED;
 -                    dir_leftrotate(vol, leaf);
 -                    leaf = dir->d_back->d_left;
 -                }
 -                leaf->d_color = dir->d_back->d_color;
 -                dir->d_back->d_color = DIRTREE_COLOR_BLACK;
 -                leaf->d_left->d_color = DIRTREE_COLOR_BLACK;
 -                dir_rightrotate(vol, dir->d_back);
 -                dir = vol->v_root;
 +                /* keep the same time stamp. */
 +                ut.actime = ut.modtime = st.st_mtime;
 +                utime(dpath, &ut);
              }
          }
      }
diff --cc etc/afpd/file.c
index f7df604982f3b966f102d96125479c358f5952a4,4aea84dde1dcfc59bdbb56db2fd2c4ba96a44f25..8257d18b5fa115ecafea861bb11dbf855ee6bd6b
@@@ -750,18 -704,10 +751,21 @@@ int afp_createfile(AFPObj *obj, char *i
  
      path = s_path->m_name;
      ad_setname(adp, path);
 +
 +    struct stat st;
 +    if (lstat(upath, &st) != 0) {
 +        LOG(log_error, logtype_afpd, "afp_createfile(\"%s\"): stat: %s",
 +            upath, strerror(errno));
 +        ad_close( adp, ADFLAGS_DF|ADFLAGS_HF);
 +        return AFPERR_MISC;
 +    }
 +
 +    (void)get_id(vol, adp, &st, dir->d_did, upath, strlen(upath));
 +
      ad_flush( adp);
+     fce_register_new_file(s_path);
      ad_close( adp, ADFLAGS_DF|ADFLAGS_HF );
  
  createfile_done:
index 8eb8bb4d8d12ede44f8550bf43207d4656b3416c,469586966ea53680094d79e180aade23f09ad828..d3976119444440fbc07a8422b4c4c12c57bf043b
@@@ -601,10 -560,19 +602,16 @@@ int afp_delete(AFPObj *obj, char *ibuf
  
      upath = s_path->u_name;
      if ( path_isadir( s_path) ) {
 -      if (*s_path->m_name != '\0') {
 -          rc = AFPERR_ACCESS;
 -      }
 -      else 
 -              {
 -
 -                      /* we have to cache this, the structs are lost in deletcurdir*/
 -                      /* but we need the positive returncode to send our event */
 -                      char dname[256];
 -                      strncpy(dname,  curdir->d_u_name, 255 );
 -            if ((rc = deletecurdir(vol)) == AFP_OK)
 -                              fce_register_delete_dir(dname);
 -        }
 +        if (*s_path->m_name != '\0' || curdir->d_did == DIRDID_ROOT)
 +            rc = AFPERR_ACCESS;
-         else
-             rc = deletecurdir( vol);
++    } else  {
++        /* we have to cache this, the structs are lost in deletcurdir*/
++        /* but we need the positive returncode to send our event */
++        char dname[256];
++        strncpy(dname,  curdir->d_u_name, 255 );
++        if ((rc = deletecurdir(vol)) == AFP_OK)
++            fce_register_delete_dir(dname);
++    }
      } else if (of_findname(s_path)) {
          rc = AFPERR_BUSY;
      } else {
           */
          if (s_path->st_valid && s_path->st_errno == ENOENT) {
              rc = AFPERR_NOOBJ;
-         }
-         else {
-             rc = deletefile(vol, -1, upath, 1);
+         } else {
+             if ((rc = deletefile(vol, -1, upath, 1)) === AFP_OK)
+                               fce_register_delete_file( s_path );
 +
 +            struct dir *cachedfile;
 +            if ((cachedfile = dircache_search_by_name(vol, dir, upath, strlen(upath), s_path->st.st_ctime))) {
 +                dircache_remove(vol, cachedfile, DIRCACHE | DIDNAME_INDEX | QUEUE_INDEX);
 +                dir_free(cachedfile);
 +            }
          }
      }
      if ( rc == AFP_OK ) {
diff --cc etc/afpd/fork.c
Simple merge
diff --cc etc/afpd/fork.h
Simple merge
Simple merge