#include <assert.h>#include <errno.h>#include <grp.h>#include <pwd.h>#include <stdbool.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#include <sys/param.h>#include <sys/stat.h>#include <utime.h>#include <bstrlib.h>#include <atalk/adouble.h>#include <atalk/afp.h>#include <atalk/cnid.h>#include <atalk/errchk.h>#include <atalk/fce_api.h>#include <atalk/globals.h>#include <atalk/logger.h>#include <atalk/netatalk_conf.h>#include <atalk/unix.h>#include <atalk/util.h>#include <atalk/uuid.h>#include <atalk/vfs.h>#include "desktop.h"#include "dircache.h"#include "directory.h"#include "file.h"#include "filedir.h"#include "fork.h"#include "hash.h"#include "mangle.h"#include "unix.h"#include "volume.h"Macros | |
| #define | DIRLOOKUP_LOG_FMT "dirlookup_internal(did:%u)" |
Functions | |
| static int | netatalk_mkdir (const struct vol *vol, const char *name) |
| static int | deletedir (const struct vol *vol, int dirfd, char *dir) |
| static int | copydir (struct vol *vol, struct dir *ddir, int dirfd, char *src, char *dst) |
| static int | diroffcnt (struct dir *dir, struct stat *st) |
| static int | invisible_dots (const struct vol *vol, const char *name) |
| static int | set_dir_errors (struct path *path, const char *where, int err) |
| static int | cname_mtouname (const struct vol *vol, struct dir *dir, struct path *ret, int toUTF8) |
| Convert name in client encoding to server encoding. | |
| static struct path * | path_from_dir (struct vol *vol, struct dir *dir, struct path *ret) |
| Build struct path from struct dir. | |
| int | get_afp_errno (const int param) |
| static struct dir * | dirlookup_internal (const struct vol *vol, cnid_t did, int retry, int strict) |
| Internal CNID (Directory ID) resolution with retry control. | |
| static struct dir * | dirlookup_internal_retry (const struct vol *vol, cnid_t did, int strict, bstring *fullpath_ptr, char **upath_ptr) |
| Retry helper for dirlookup_internal on ENOENT. | |
| struct dir * | dirlookup (const struct vol *vol, cnid_t did) |
| Public CNID (Directory ID) resolution (supports files and directories). | |
| struct dir * | dirlookup_strict (const struct vol *vol, cnid_t did) |
| Strict DID resolution with inode validation. | |
| struct dir * | dir_new (const char *m_name, const char *u_name, const struct vol *vol, cnid_t pdid, cnid_t did, bstring path, struct stat *st) |
| Construct struct dir. | |
| void | dir_free (struct dir *dir) |
| Free a struct dir and all its members. | |
| struct dir * | dir_add (struct vol *vol, const struct dir *dir, struct path *path, int len) |
| Create struct dir from struct path. | |
| void | dir_free_invalid_q (void) |
| Free the queue with invalid struct dirs. | |
| int | dir_remove (const struct vol *vol, struct dir *dir) |
| Remove a file/directory from dircache with automatic curdir recovery. | |
| struct path * | cname (struct vol *vol, struct dir *dir, char **cpath) |
| Resolve a catalog node name path. | |
| int | movecwd (const struct vol *vol, struct dir *dir) |
| chdir() to dir | |
| int | check_access (const AFPObj *obj, struct vol *vol, char *path, int mode) |
| int | file_access (const AFPObj *obj, struct vol *vol, struct path *path, int mode) |
| void | setdiroffcnt (struct dir *dir, struct stat *st, uint32_t count) |
| int | dirreenumerate (struct dir *dir, struct stat *st) |
| int | getdirparams (const AFPObj *obj, const struct vol *vol, uint16_t bitmap, struct path *s_path, struct dir *dir, char *buf, size_t *buflen) |
| int | path_error (struct path *path, int error) |
| int | afp_setdirparams (AFPObj *obj, char *ibuf, size_t ibuflen, char *rbuf, size_t *rbuflen) |
| int | setdirparams (struct vol *vol, struct path *path, uint16_t d_bitmap, char *buf) |
| int | afp_syncdir (AFPObj *obj, char *ibuf, size_t ibuflen, char *rbuf, size_t *rbuflen) |
| int | afp_createdir (AFPObj *obj, char *ibuf, size_t ibuflen, char *rbuf, size_t *rbuflen) |
| int | renamedir (struct vol *vol, int dirfd, char *src, char *dst, struct dir *newparent, char *newname) |
| Rename a directory. | |
| int | deletecurdir (struct vol *vol) |
| int | afp_mapid (AFPObj *obj, char *ibuf, size_t ibuflen, char *rbuf, size_t *rbuflen) |
| int | afp_mapname (AFPObj *obj, char *ibuf, size_t ibuflen, char *rbuf, size_t *rbuflen) |
| int | afp_closedir (AFPObj *obj, char *ibuf, size_t ibuflen, char *rbuf, size_t *rbuflen) |
| int | afp_opendir (AFPObj *obj, char *ibuf, size_t ibuflen, char *rbuf, size_t *rbuflen) |
Variables | |
| int | afp_errno |
| struct dir | rootParent |
| struct dir * | curdir = &rootParent |
| struct path | Cur_Path |
| q_t * | invalid_dircache_entries |
| #define DIRLOOKUP_LOG_FMT "dirlookup_internal(did:%u)" |
| int afp_closedir | ( | AFPObj * | obj, |
| char * | ibuf, | ||
| size_t | ibuflen, | ||
| char * | rbuf, | ||
| size_t * | rbuflen ) |
| int afp_createdir | ( | AFPObj * | obj, |
| char * | ibuf, | ||
| size_t | ibuflen, | ||
| char * | rbuf, | ||
| size_t * | rbuflen ) |
| int afp_mapid | ( | AFPObj * | obj, |
| char * | ibuf, | ||
| size_t | ibuflen, | ||
| char * | rbuf, | ||
| size_t * | rbuflen ) |
| int afp_mapname | ( | AFPObj * | obj, |
| char * | ibuf, | ||
| size_t | ibuflen, | ||
| char * | rbuf, | ||
| size_t * | rbuflen ) |
| int afp_opendir | ( | AFPObj * | obj, |
| char * | ibuf, | ||
| size_t | ibuflen, | ||
| char * | rbuf, | ||
| size_t * | rbuflen ) |
| int afp_setdirparams | ( | AFPObj * | obj, |
| char * | ibuf, | ||
| size_t | ibuflen, | ||
| char * | rbuf, | ||
| size_t * | rbuflen ) |
| int afp_syncdir | ( | AFPObj * | obj, |
| char * | ibuf, | ||
| size_t | ibuflen, | ||
| char * | rbuf, | ||
| size_t * | rbuflen ) |
We can't use unix file's perm to support Apple's inherited protection modes. If we aren't the file's owner we can't change its perms when moving it and smb nfs,... don't even try.
Resolve a catalog node name path.
|
static |
Convert name in client encoding to server encoding.
Convert ret->m_name to ret->u_name from client encoding to server encoding. This only gets called from cname().
do a recursive copy.
| int deletecurdir | ( | struct vol * | vol | ) |
delete an empty directory
|
static |
Create struct dir from struct path.
Create a new struct dir from struct path. Then add it to the cache.
| [in] | vol | pointer to struct vol, possibly modified in callee |
| [in] | dir | pointer to parent directory |
| [in,out] | path | pointer to struct path with valid path->u_name |
| [in] | len | strlen of path->u_name |
| void dir_free | ( | struct dir * | dir | ) |
Free a struct dir and all its members.
| dir | (rw) pointer to struct dir |
| void dir_free_invalid_q | ( | void | ) |
Free the queue with invalid struct dirs.
| struct dir * dir_new | ( | const char * | m_name, |
| const char * | u_name, | ||
| const struct vol * | vol, | ||
| cnid_t | pdid, | ||
| cnid_t | did, | ||
| bstring | path, | ||
| struct stat * | st ) |
Construct struct dir.
Construct struct dir from parameters.
| [in] | m_name | directory name in UTF8-dec |
| [in] | u_name | directory name in server side encoding |
| [in] | vol | pointer to struct vol |
| [in] | pdid | Parent CNID |
| [in] | did | CNID |
| [in] | path | Full unix path to object |
| [in] | st | struct stat of object |
Remove a file/directory from dircache with automatic curdir recovery.
This function centralizes global curdir safety for all callers. When removing a cache entry that is curdir, it attempts curdir recovery via CNID database and falls back to volume root if recovery fails.
| [in] | vol | volume pointer |
| [in,out] | dir | directory/file entry to remove from cache |
Public CNID (Directory ID) resolution (supports files and directories).
Resolves a CNID (Directory ID) to its cached entry. This function supports both files and directories since DID can refer to either type. If cache hit, returns cache entry, if cache miss, returns CNID database record and updates cache
| [in] | vol | pointer to struct vol |
| [in] | did | DID to resolve |
|
static |
Internal CNID (Directory ID) resolution with retry control.
Resolve a CNID (Directory ID), allocate a struct dir for it.
Algorithm:
On ENOENT during stat (step 5), if retry=1:
| [in] | vol | pointer to struct vol |
| [in] | did | CNID to resolve |
| [in] | retry | 1 = allow one retry on ENOENT, 0 = no retry |
| [in] | strict | 1 = strict dircache lookup (validate with stat+inode), 0 = optimistic |
|
static |
Retry helper for dirlookup_internal on ENOENT.
When stat() fails with ENOENT, this function cleans stale cache entries and retries the lookup via CNID database. This handles race conditions where directories are renamed/moved by external processes between cache and stat.
| [in] | vol | Volume |
| [in] | did | Target DID that failed stat |
| [in] | strict | Validation mode (0=initial target, 1=parent recursion) |
| [in,out] | fullpath_ptr | Pointer to fullpath to cleanup |
| [in,out] | upath_ptr | Pointer to upath to cleanup |
Strict DID resolution with inode validation.
Like dirlookup(), but performs additional validation to ensure the cached directory entry matches the actual filesystem state. This prevents race conditions where a directory has been renamed/moved but the cache entry still points to the old path/has become stale.
Use this for destructive operations (delete, rename, move) where operating on the wrong object could cause data loss.
| [in] | vol | pointer to struct vol |
| [in] | did | DID to resolve |
|
static |
is our cached offspring count valid?
| int dirreenumerate | ( | struct dir * | dir, |
| struct stat * | st ) |
| int get_afp_errno | ( | const int | param | ) |
| int getdirparams | ( | const AFPObj * | obj, |
| const struct vol * | vol, | ||
| uint16_t | bitmap, | ||
| struct path * | s_path, | ||
| struct dir * | dir, | ||
| char * | buf, | ||
| size_t * | buflen ) |
|
static |
chdir() to dir
| [in] | vol | pointer to struct vol |
| [in] | dir | pointer to struct dir |
|
static |
| int path_error | ( | struct path * | path, |
| int | error ) |
Build struct path from struct dir.
The final movecwd in cname failed, possibly with EPERM or ENOENT. We:
| int renamedir | ( | struct vol * | vol, |
| int | dirfd, | ||
| char * | src, | ||
| char * | dst, | ||
| struct dir * | newparent, | ||
| char * | newname ) |
Rename a directory.
| vol | volume |
| dirfd | -1 means ignore dirfd (or use AT_FDCWD), otherwise src is relative to dirfd |
| src | old unix filename (not a pathname) |
| dst | new unix filename (not a pathname) |
| newparent | curdir |
| newname | new mac name |
|
static |
| void setdiroffcnt | ( | struct dir * | dir, |
| struct stat * | st, | ||
| uint32_t | count ) |
| int afp_errno |
| struct path Cur_Path |
| struct dir* curdir = &rootParent |
| q_t* invalid_dircache_entries |
| struct dir rootParent |