X-Git-Url: https://arthur.barton.de/cgi-bin/gitweb.cgi?p=netatalk.git;a=blobdiff_plain;f=etc%2Fafpd%2Fdirectory.c;h=e83e5e76ca45cd29e99faf27e3744914251c4412;hp=7b25849114d0d9c1e079ca3f77446d5ade6fce36;hb=d3dff4ba4b8db3131a16641d35a6554be5fb5160;hpb=25ca059b795321076af8d8d422ba6a473ef04cf6 diff --git a/etc/afpd/directory.c b/etc/afpd/directory.c index 7b258491..e83e5e76 100644 --- a/etc/afpd/directory.c +++ b/etc/afpd/directory.c @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -29,7 +30,9 @@ #include #include #include +#include #include +#include #include "directory.h" #include "dircache.h" @@ -38,7 +41,6 @@ #include "fork.h" #include "file.h" #include "filedir.h" -#include "globals.h" #include "unix.h" #include "mangle.h" #include "hash.h" @@ -132,7 +134,7 @@ static int netatalk_mkdir(const struct vol *vol, const char *name) } /* ------------------- */ -static int deletedir(int dirfd, char *dir) +static int deletedir(const struct vol *vol, int dirfd, char *dir) { char path[MAXPATHLEN + 1]; DIR *dp; @@ -163,11 +165,11 @@ static int deletedir(int dirfd, char *dir) break; } strcpy(path + len, de->d_name); - if (lstatat(dirfd, path, &st)) { + if (ostatat(dirfd, path, &st, vol_syml_opt(vol))) { continue; } if (S_ISDIR(st.st_mode)) { - err = deletedir(dirfd, path); + err = deletedir(vol, dirfd, path); } else { err = netatalk_unlinkat(dirfd, path); } @@ -183,7 +185,7 @@ static int deletedir(int dirfd, char *dir) } /* do a recursive copy. */ -static int copydir(const struct vol *vol, int dirfd, char *src, char *dst) +static int copydir(struct vol *vol, struct dir *ddir, int dirfd, char *src, char *dst) { char spath[MAXPATHLEN + 1], dpath[MAXPATHLEN + 1]; DIR *dp; @@ -229,7 +231,7 @@ static int copydir(const struct vol *vol, int dirfd, char *src, char *dst) } strcpy(spath + slen, de->d_name); - if (lstatat(dirfd, spath, &st) == 0) { + if (ostatat(dirfd, spath, &st, vol_syml_opt(vol)) == 0) { if (strlen(de->d_name) > drem) { err = AFPERR_PARAM; break; @@ -237,9 +239,9 @@ static int copydir(const struct vol *vol, int dirfd, char *src, char *dst) strcpy(dpath + dlen, de->d_name); if (S_ISDIR(st.st_mode)) { - if (AFP_OK != (err = copydir(vol, dirfd, spath, dpath))) + if (AFP_OK != (err = copydir(vol, ddir, dirfd, spath, dpath))) goto copydir_done; - } else if (AFP_OK != (err = copyfile(vol, vol, dirfd, spath, dpath, NULL, NULL))) { + } else if (AFP_OK != (err = copyfile(vol, vol, ddir, dirfd, spath, dpath, NULL, NULL))) { goto copydir_done; } else { @@ -251,7 +253,7 @@ static int copydir(const struct vol *vol, int dirfd, char *src, char *dst) } /* keep the same time stamp. */ - if (lstatat(dirfd, src, &st) == 0) { + if (ostatat(dirfd, src, &st, vol_syml_opt(vol)) == 0) { ut.actime = ut.modtime = st.st_mtime; utime(dst, &ut); } @@ -266,7 +268,7 @@ copydir_done: */ static int diroffcnt(struct dir *dir, struct stat *st) { - return st->st_ctime == dir->ctime; + return st->st_ctime == dir->d_ctime; } /* --------------------- */ @@ -299,13 +301,13 @@ static int set_dir_errors(struct path *path, const char *where, int err) * * @note If the passed ret->m_name is mangled, we'll demangle it */ -static int cname_mtouname(const struct vol *vol, const struct dir *dir, struct path *ret, int toUTF8) +static int cname_mtouname(const struct vol *vol, struct dir *dir, struct path *ret, int toUTF8) { static char temp[ MAXPATHLEN + 1]; char *t; cnid_t fileid = 0; - if (afp_version >= 30) { + if (vol->v_obj->afp_version >= 30) { if (toUTF8) { if (dir->d_did == DIRDID_ROOT_PARENT) { /* @@ -329,6 +331,12 @@ static int cname_mtouname(const struct vol *vol, const struct dir *dir, struct p /* check for OS X mangled filename :( */ t = demangle_osx(vol, ret->m_name, dir->d_did, &fileid); + + if (curdir == NULL) { + /* demangle_osx() calls dirlookup() which might have clobbered curdir */ + movecwd(vol, dir); + } + LOG(log_maxdebug, logtype_afpd, "cname_mtouname('%s',did:%u) {demangled:'%s', fileid:%u}", ret->m_name, ntohl(dir->d_did), t, ntohl(fileid)); @@ -337,7 +345,7 @@ static int cname_mtouname(const struct vol *vol, const struct dir *dir, struct p /* duplicate work but we can't reuse all convert_char we did in demangle_osx * flags weren't the same */ - if ( (t = utompath(vol, ret->u_name, fileid, utf8_encoding())) ) { + if ( (t = utompath(vol, ret->u_name, fileid, utf8_encoding(vol->v_obj))) ) { /* at last got our view of mac name */ strcpy(ret->m_name, t); } @@ -346,7 +354,7 @@ static int cname_mtouname(const struct vol *vol, const struct dir *dir, struct p /* If we haven't got it by now, get it */ if (ret->u_name == NULL) { - if ((ret->u_name = mtoupath(vol, ret->m_name, dir->d_did, utf8_encoding())) == NULL) { + if ((ret->u_name = mtoupath(vol, ret->m_name, dir->d_did, utf8_encoding(vol->v_obj))) == NULL) { afp_errno = AFPERR_PARAM; return -1; } @@ -463,13 +471,25 @@ struct dir *dirlookup_bypath(const struct vol *vol, const char *path) cnid = htonl(2); dir = vol->v_root; + LOG(log_debug, logtype_afpd, "dirlookup_bypath(\"%s\")", path); + + if (strcmp(vol->v_path, path) == 0) + return dir; + EC_NULL(rpath = rel_path_in_vol(path, vol->v_path)); /* 1. */ + + LOG(log_debug, logtype_afpd, "dirlookup_bypath: rpath: \"%s\"", cfrombstr(rpath)); + EC_NULL(statpath = bfromcstr(vol->v_path)); /* 2. */ 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])); + + LOG(log_debug, logtype_afpd, "dirlookup_bypath: statpath: \"%s\"", cfrombstr(statpath)); + EC_ZERO_LOGSTR(lstat(cfrombstr(statpath), &st), "lstat(rpath: %s, elem: %s): %s: %s", cfrombstr(rpath), cfrombstr(l->entry[i]), @@ -481,22 +501,22 @@ struct dir *dirlookup_bypath(const struct vol *vol, const char *path) if ((dir = dircache_search_by_name(vol, /* 5. */ dir, cfrombstr(l->entry[i]), - blength(l->entry[i]), - st.st_ctime)) == NULL) { - if ((cnid = cnid_add(vol->v_cdb, /* 6. */ - &st, - did, - cfrombstr(l->entry[i]), - blength(l->entry[i]), - 0)) == CNID_INVALID) { + blength(l->entry[i]))) == NULL) { + + AFP_CNID_START("cnid_add"); + cnid = cnid_add(vol->v_cdb, /* 6. */ + &st, + did, + cfrombstr(l->entry[i]), + blength(l->entry[i]), + 0); + AFP_CNID_DONE(); + if (cnid == CNID_INVALID) EC_FAIL; - } if ((dir = dirlookup(vol, cnid)) == NULL) /* 7. */ EC_FAIL; } - - EC_ZERO(bcatcstr(statpath, "/")); } EC_CLEANUP: @@ -506,6 +526,9 @@ EC_CLEANUP: if (ret != 0) return NULL; + LOG(log_debug, logtype_afpd, "dirlookup_bypath: result: \"%s\"", + cfrombstr(dir->d_fullpath)); + return dir; } @@ -515,7 +538,7 @@ 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. @@ -540,7 +563,7 @@ struct dir *dirlookup(const struct vol *vol, cnid_t did) 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 */ @@ -558,18 +581,19 @@ struct dir *dirlookup(const struct vol *vol, cnid_t did) /* 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; @@ -586,12 +610,17 @@ struct dir *dirlookup(const struct vol *vol, cnid_t did) goto exit; } - utf8 = utf8_encoding(); + utf8 = utf8_encoding(vol->v_obj); maxpath = (utf8) ? MAXPATHLEN - 7 : 255; /* Get it from the database */ cnid = did; - if ((upath = cnid_resolve(vol->v_cdb, &cnid, buffer, buflen)) == NULL) { + LOG(log_debug, logtype_afpd, "dirlookup(did: %u): querying CNID database", ntohl(did)); + + AFP_CNID_START("cnid_resolve"); + upath = cnid_resolve(vol->v_cdb, &cnid, buffer, buflen); + AFP_CNID_DONE(); + if (upath == NULL) { afp_errno = AFPERR_NOOBJ; err = 1; goto exit; @@ -608,7 +637,8 @@ struct dir *dirlookup(const struct vol *vol, cnid_t did) * - 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; @@ -623,9 +653,10 @@ struct dir *dirlookup(const struct vol *vol, cnid_t did) } /* 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 (ostat(cfrombstr(fullpath), &st, vol_syml_opt(vol)) != 0) { /* 5a */ switch (errno) { case ENOENT: afp_errno = AFPERR_NOOBJ; @@ -656,7 +687,7 @@ struct dir *dirlookup(const struct vol *vol, cnid_t did) } /* 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; @@ -681,7 +712,7 @@ 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; @@ -689,86 +720,6 @@ exit: #define ENUMVETO "./../Network Trash Folder/TheVolumeSettingsFolder/TheFindByContentFolder/:2eDS_Store/Contents/Desktop Folder/Trash/Benutzer/" -int caseenumerate(const struct vol *vol, struct path *path, struct dir *dir) -{ - DIR *dp; - struct dirent *de; - int ret; - static u_int32_t did = 0; - static char cname[MAXPATHLEN]; - static char lname[MAXPATHLEN]; - ucs2_t u2_path[MAXPATHLEN]; - ucs2_t u2_dename[MAXPATHLEN]; - char *tmp, *savepath; - - if (!(vol->v_flags & AFPVOL_CASEINSEN)) - return -1; - - if (veto_file(ENUMVETO, path->u_name)) - return -1; - - savepath = path->u_name; - - /* very simple cache */ - if ( dir->d_did == did && strcmp(lname, path->u_name) == 0) { - path->u_name = cname; - path->d_dir = NULL; - if (of_stat( path ) == 0 ) { - return 0; - } - /* something changed, we cannot stat ... */ - did = 0; - } - - if (NULL == ( dp = opendir( "." )) ) { - LOG(log_debug, logtype_afpd, "caseenumerate: opendir failed: %s", dir->d_u_name); - return -1; - } - - - /* LOG(log_debug, logtype_afpd, "caseenumerate: for %s", path->u_name); */ - if ((size_t) -1 == convert_string(vol->v_volcharset, CH_UCS2, path->u_name, -1, u2_path, sizeof(u2_path)) ) - LOG(log_debug, logtype_afpd, "caseenumerate: conversion failed for %s", path->u_name); - - /*LOG(log_debug, logtype_afpd, "caseenumerate: dir: %s, path: %s", dir->d_u_name, path->u_name); */ - ret = -1; - for ( de = readdir( dp ); de != NULL; de = readdir( dp )) { - if (NULL == check_dirent(vol, de->d_name)) - continue; - - if ((size_t) -1 == convert_string(vol->v_volcharset, CH_UCS2, de->d_name, -1, u2_dename, sizeof(u2_dename)) ) - continue; - - if (strcasecmp_w( u2_path, u2_dename) == 0) { - tmp = path->u_name; - strlcpy(cname, de->d_name, sizeof(cname)); - path->u_name = cname; - path->d_dir = NULL; - if (of_stat( path ) == 0 ) { - LOG(log_debug, logtype_afpd, "caseenumerate: using dir: %s, path: %s", de->d_name, path->u_name); - strlcpy(lname, tmp, sizeof(lname)); - did = dir->d_did; - ret = 0; - break; - } - else - path->u_name = tmp; - } - - } - closedir(dp); - - if (ret) { - /* invalidate cache */ - cname[0] = 0; - did = 0; - path->u_name = savepath; - } - /* LOG(log_debug, logtype_afpd, "caseenumerate: path on ret: %s", path->u_name); */ - return ret; -} - - /*! * @brief Construct struct dir * @@ -779,8 +730,8 @@ int caseenumerate(const struct vol *vol, struct path *path, struct dir *dir) * @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 * @@ -792,7 +743,7 @@ struct dir *dir_new(const char *m_name, cnid_t pdid, cnid_t did, bstring path, - time_t ctime) + struct stat *st) { struct dir *dir; @@ -805,7 +756,7 @@ struct dir *dir_new(const char *m_name, return NULL; } - if (convert_string_allocate( (utf8_encoding()) ? CH_UTF8_MAC : vol->v_maccharset, + if (convert_string_allocate( (utf8_encoding(vol->v_obj)) ? CH_UTF8_MAC : vol->v_maccharset, CH_UCS2, m_name, -1, (char **)&dir->d_m_name_ucs2) == (size_t)-1 ) { @@ -826,7 +777,11 @@ struct dir *dir_new(const char *m_name, 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; } @@ -873,14 +828,14 @@ struct dir *dir_add(struct vol *vol, const struct dir *dir, struct path *path, i cnid_t id; struct adouble ad; struct adouble *adp = NULL; - bstring fullpath; + bstring fullpath = NULL; AFP_ASSERT(vol); AFP_ASSERT(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, @@ -892,8 +847,8 @@ struct dir *dir_add(struct vol *vol, const struct dir *dir, struct path *path, i } /* get_id needs adp for reading CNID from adouble file */ - ad_init(&ad, vol->v_adouble, vol->v_ad_options); - if ((ad_open_metadata(path->u_name, ADFLAGS_DIR, 0, &ad)) == 0) /* 1 */ + ad_init(&ad, vol); + if ((ad_open(&ad, path->u_name, ADFLAGS_HF | ADFLAGS_DIR | ADFLAGS_RDONLY)) == 0) /* 1 */ adp = &ad; /* Get CNID */ @@ -903,11 +858,11 @@ struct dir *dir_add(struct vol *vol, const struct dir *dir, struct path *path, i } if (adp) - ad_close_metadata(adp); + ad_close(adp, ADFLAGS_HF); /* Get macname from unixname */ if (path->m_name == NULL) { - if ((path->m_name = utompath(vol, path->u_name, id, utf8_encoding())) == NULL) { + if ((path->m_name = utompath(vol, path->u_name, id, utf8_encoding(vol->v_obj))) == NULL) { LOG(log_error, logtype_afpd, "dir_add(\"%s\"): can't assign macname", path->u_name); err = 2; goto exit; @@ -924,7 +879,13 @@ struct dir *dir_add(struct vol *vol, const struct dir *dir, struct path *path, i } /* 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; } @@ -940,7 +901,7 @@ exit: cfrombstr(dir->d_u_name), path->u_name, err); if (adp) - ad_close_metadata(adp); + ad_close(adp, ADFLAGS_HF); if (!cdir && fullpath) bdestroy(fullpath); if (cdir) @@ -964,7 +925,7 @@ exit: void dir_free_invalid_q(void) { struct dir *dir; - while (dir = (struct dir *)dequeue(invalid_dircache_entries)) + while ((dir = (struct dir *)dequeue(invalid_dircache_entries))) dir_free(dir); } @@ -1117,8 +1078,8 @@ struct path *cname(struct vol *vol, struct dir *dir, char **cpath) struct dir *cdir; char *data, *p; int len; - u_int32_t hint; - u_int16_t len16; + uint32_t hint; + uint16_t len16; int size = 0; int toUTF8 = 0; @@ -1133,13 +1094,13 @@ struct path *cname(struct vol *vol, struct dir *dir, char **cpath) data++; len = (unsigned char) *data++; size = 2; - if (afp_version >= 30) { + if (vol->v_obj->afp_version >= 30) { ret.m_type = 3; toUTF8 = 1; } break; case 3: - if (afp_version >= 30) { + if (vol->v_obj->afp_version >= 30) { data++; memcpy(&hint, data, sizeof(hint)); hint = ntohl(hint); @@ -1211,6 +1172,14 @@ struct path *cname(struct vol *vol, struct dir *dir, char **cpath) /* the name is illegal */ LOG(log_info, logtype_afpd, "cname: illegal path: '%s'", ret.u_name); afp_errno = AFPERR_PARAM; + if (vol->v_obj->options.flags & OPTION_VETOMSG) { + bstring message = bformat("Attempt to access vetoed file or directory \"%s\" in directory \"%s\"", + ret.u_name, bdata(dir->d_u_name)); + if (setmessage(bdata(message)) == 0) + /* Client may make multiple attempts, only send the message the first time */ + kill(getpid(), SIGUSR2); + bdestroy(message); + } return NULL; } @@ -1233,7 +1202,7 @@ struct path *cname(struct vol *vol, struct dir *dir, char **cpath) * and thus call continue which should terminate the while loop because * len = 0. Ok? */ - if (of_stat(&ret) != 0) { /* 9 */ + if (of_stat(vol, &ret) != 0) { /* 9 */ /* * ret.u_name doesn't exist, might be afp_createfile|dir * that means it should have been the last part @@ -1282,7 +1251,7 @@ struct path *cname(struct vol *vol, struct dir *dir, char **cpath) /* 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 */ @@ -1351,9 +1320,9 @@ int movecwd(const struct vol *vol, struct dir *dir) LOG(log_debug, logtype_afpd, "movecwd(to: did: %u, \"%s\")", ntohl(dir->d_did), cfrombstr(dir->d_fullpath)); - if ((ret = lchdir(cfrombstr(dir->d_fullpath))) != 0 ) { - LOG(log_debug, logtype_afpd, "movecwd(\"%s\"): ret: %u, %s", - cfrombstr(dir->d_fullpath), ret, strerror(errno)); + if ((ret = ochdir(cfrombstr(dir->d_fullpath), vol_syml_opt(vol))) != 0 ) { + LOG(log_debug, logtype_afpd, "movecwd(\"%s\"): %s", + cfrombstr(dir->d_fullpath), strerror(errno)); if (ret == 1) { /* p is a symlink or getcwd failed */ afp_errno = AFPERR_BADTYPE; @@ -1386,11 +1355,8 @@ int movecwd(const struct vol *vol, struct dir *dir) * If we aren't the file's owner we can't change its perms when moving it and smb * nfs,... don't even try. */ -#define AFP_CHECK_ACCESS - -int check_access(char *path, int mode) +int check_access(const AFPObj *obj, struct vol *vol, char *path, int mode) { -#ifdef AFP_CHECK_ACCESS struct maccess ma; char *p; @@ -1398,21 +1364,21 @@ int check_access(char *path, int mode) if (!p) return -1; - accessmode(p, &ma, curdir, NULL); + accessmode(obj, vol, p, &ma, curdir, NULL); if ((mode & OPENACC_WR) && !(ma.ma_user & AR_UWRITE)) return -1; if ((mode & OPENACC_RD) && !(ma.ma_user & AR_UREAD)) return -1; -#endif + return 0; } /* --------------------- */ -int file_access(struct path *path, int mode) +int file_access(const AFPObj *obj, struct vol *vol, struct path *path, int mode) { struct maccess ma; - accessmode(path->u_name, &ma, curdir, &path->st); + accessmode(obj, vol, path->u_name, &ma, curdir, &path->st); LOG(log_debug, logtype_afpd, "file_access(\"%s\"): mapped user mode: 0x%02x", path->u_name, ma.ma_user); @@ -1430,10 +1396,10 @@ int file_access(struct path *path, int mode) } /* --------------------- */ -void setdiroffcnt(struct dir *dir, struct stat *st, u_int32_t count) +void setdiroffcnt(struct dir *dir, struct stat *st, uint32_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; } @@ -1443,7 +1409,7 @@ void setdiroffcnt(struct dir *dir, struct stat *st, u_int32_t count) */ 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); } /* ------------------------------ @@ -1451,8 +1417,9 @@ int dirreenumerate(struct dir *dir, struct stat *st) (name, dir) with curdir:name == dir, from afp_enumerate */ -int getdirparams(const struct vol *vol, - u_int16_t bitmap, struct path *s_path, +int getdirparams(const AFPObj *obj, + const struct vol *vol, + uint16_t bitmap, struct path *s_path, struct dir *dir, char *buf, size_t *buflen ) { @@ -1460,10 +1427,10 @@ int getdirparams(const struct vol *vol, struct adouble ad; char *data, *l_nameoff = NULL, *utf_nameoff = NULL; int bit = 0, isad = 0; - u_int32_t aint; - u_int16_t ashort; + uint32_t aint; + uint16_t ashort; int ret; - u_int32_t utf8 = 0; + uint32_t utf8 = 0; cnid_t pdid; struct stat *st = &s_path->st; char *upath = s_path->u_name; @@ -1474,11 +1441,22 @@ int getdirparams(const struct vol *vol, (1 << DIRPBIT_BDATE) | (1 << DIRPBIT_FINFO)))) { - ad_init(&ad, vol->v_adouble, vol->v_ad_options); - if ( !ad_metadata( upath, ADFLAGS_CREATE|ADFLAGS_DIR, &ad) ) { + ad_init(&ad, vol); + if ( !ad_metadata( upath, ADFLAGS_DIR, &ad) ) { isad = 1; - if (ad.ad_md->adf_flags & O_CREAT) { + if (ad.ad_mdp->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(obj))) == 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, @@ -1508,7 +1486,7 @@ int getdirparams(const struct vol *vol, ashort = htons(ATTRBIT_INVISIBLE); } else ashort = 0; - ashort |= htons(ATTRBIT_SHARED); + ashort &= ~htons(vol->v_ignattr); memcpy( data, &ashort, sizeof( ashort )); data += sizeof( ashort ); break; @@ -1545,10 +1523,6 @@ int getdirparams(const struct vol *vol, memcpy( data, ad_entry( &ad, ADEID_FINDERI ), 32 ); } else { /* no appledouble */ memset( data, 0, 32 ); - /* set default view -- this also gets done in ad_open() */ - ashort = htons(FINDERINFO_CLOSEDVIEW); - memcpy(data + FINDERINFO_FRVIEWOFF, &ashort, sizeof(ashort)); - /* dot files are by default visible */ if (invisible_dots(vol, cfrombstr(dir->d_u_name))) { ashort = htons(FINDERINFO_INVISIBLE); @@ -1562,13 +1536,13 @@ int getdirparams(const struct vol *vol, if (dir->d_m_name) /* root of parent can have a null name */ l_nameoff = data; else - memset(data, 0, sizeof(u_int16_t)); - data += sizeof( u_int16_t ); + memset(data, 0, sizeof(uint16_t)); + data += sizeof( uint16_t ); break; case DIRPBIT_SNAME : - memset(data, 0, sizeof(u_int16_t)); - data += sizeof( u_int16_t ); + memset(data, 0, sizeof(uint16_t)); + data += sizeof( uint16_t ); break; case DIRPBIT_DID : @@ -1582,11 +1556,11 @@ int getdirparams(const struct vol *vol, 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 )); @@ -1606,7 +1580,7 @@ int getdirparams(const struct vol *vol, break; case DIRPBIT_ACCESS : - accessmode( upath, &ma, dir , st); + accessmode(obj, vol, upath, &ma, dir , st); *data++ = ma.ma_user; *data++ = ma.ma_world; @@ -1618,13 +1592,13 @@ int getdirparams(const struct vol *vol, Just pass back the same basic block for all directories. */ case DIRPBIT_PDINFO : - if (afp_version >= 30) { /* UTF8 name */ + if (obj->afp_version >= 30) { /* UTF8 name */ utf8 = kTextEncodingUTF8; if (dir->d_m_name) /* root of parent can have a null name */ utf_nameoff = data; else - memset(data, 0, sizeof(u_int16_t)); - data += sizeof( u_int16_t ); + memset(data, 0, sizeof(uint16_t)); + data += sizeof( uint16_t ); aint = 0; memcpy(data, &aint, sizeof( aint )); data += sizeof( aint ); @@ -1641,6 +1615,9 @@ int getdirparams(const struct vol *vol, break; case DIRPBIT_UNIXPR : + /* accessmode may change st_mode with ACLs */ + accessmode(obj, vol, upath, &ma, dir, st); + aint = htonl(st->st_uid); memcpy( data, &aint, sizeof( aint )); data += sizeof( aint ); @@ -1653,8 +1630,6 @@ int getdirparams(const struct vol *vol, memcpy( data, &aint, sizeof( aint )); data += sizeof( aint ); - accessmode( upath, &ma, dir , st); - *data++ = ma.ma_user; *data++ = ma.ma_world; *data++ = ma.ma_group; @@ -1663,7 +1638,7 @@ int getdirparams(const struct vol *vol, default : if ( isad ) { - ad_close_metadata( &ad ); + ad_close(&ad, ADFLAGS_HF); } return( AFPERR_BITMAP ); } @@ -1681,7 +1656,7 @@ int getdirparams(const struct vol *vol, data = set_name(vol, data, pdid, cfrombstr(dir->d_m_name), dir->d_did, utf8); } if ( isad ) { - ad_close_metadata( &ad ); + ad_close(&ad, ADFLAGS_HF); } *buflen = data - buf; return( AFP_OK ); @@ -1707,8 +1682,8 @@ int afp_setdirparams(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf _U_ struct vol *vol; struct dir *dir; struct path *path; - u_int16_t vid, bitmap; - u_int32_t did; + uint16_t vid, bitmap; + uint32_t did; int rc; *rbuflen = 0; @@ -1759,11 +1734,9 @@ int afp_setdirparams(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf _U_ } /* - * cf AFP3.0.pdf page 244 for change_mdate and change_parent_mdate logic - * * assume path == '\0' eg. it's a directory in canonical form */ -int setdirparams(struct vol *vol, struct path *path, u_int16_t d_bitmap, char *buf ) +int setdirparams(struct vol *vol, struct path *path, uint16_t d_bitmap, char *buf ) { struct maccess ma; struct adouble ad; @@ -1772,19 +1745,21 @@ int setdirparams(struct vol *vol, struct path *path, u_int16_t d_bitmap, char *b char *upath; struct dir *dir; - int bit, isad = 1; + int bit, isad = 0; int cdate, bdate; int owner, group; - u_int16_t ashort, bshort, oshort; + uint16_t ashort, bshort, oshort; int err = AFP_OK; int change_mdate = 0; int change_parent_mdate = 0; int newdate = 0; - u_int16_t bitmap = d_bitmap; + uint16_t bitmap = d_bitmap; u_char finder_buf[32]; - u_int32_t upriv; + uint32_t upriv; mode_t mpriv = 0; - u_int16_t upriv_bit = 0; + bool set_upriv = false, set_maccess = false; + + LOG(log_debug, logtype_afpd, "setdirparams(\"%s\", bitmap: %02x)", path->u_name, bitmap); bit = 0; upath = path->u_name; @@ -1821,33 +1796,27 @@ int setdirparams(struct vol *vol, struct path *path, u_int16_t d_bitmap, char *b buf += 32; break; case DIRPBIT_UID : /* What kind of loser mounts as root? */ - change_parent_mdate = 1; memcpy( &owner, buf, sizeof(owner)); buf += sizeof( owner ); break; case DIRPBIT_GID : - change_parent_mdate = 1; memcpy( &group, buf, sizeof( group )); buf += sizeof( group ); break; case DIRPBIT_ACCESS : + set_maccess = true; change_mdate = 1; - change_parent_mdate = 1; ma.ma_user = *buf++; ma.ma_world = *buf++; ma.ma_group = *buf++; ma.ma_owner = *buf++; mpriv = mtoumode( &ma ) | vol->v_dperm; - if (dir_rx_set(mpriv) && setdirmode( vol, upath, mpriv) < 0 ) { - err = set_dir_errors(path, "setdirmode", errno); - bitmap = 0; - } break; /* Ignore what the client thinks we should do to the ProDOS information block. Skip over the data and report nothing amiss. */ case DIRPBIT_PDINFO : - if (afp_version < 30) { + if (vol->v_obj->afp_version < 30) { buf += 6; } else { @@ -1857,27 +1826,16 @@ int setdirparams(struct vol *vol, struct path *path, u_int16_t d_bitmap, char *b break; case DIRPBIT_UNIXPR : if (vol_unix_priv(vol)) { + set_upriv = true; memcpy( &owner, buf, sizeof(owner)); /* FIXME need to change owner too? */ buf += sizeof( owner ); memcpy( &group, buf, sizeof( group )); buf += sizeof( group ); change_mdate = 1; - change_parent_mdate = 1; memcpy( &upriv, buf, sizeof( upriv )); buf += sizeof( upriv ); upriv = ntohl (upriv) | vol->v_dperm; - if (dir_rx_set(upriv)) { - /* maybe we are trying to set perms back */ - if ( setdirunixmode(vol, upath, upriv) < 0 ) { - bitmap = 0; - err = set_dir_errors(path, "setdirunixmode", errno); - } - } - else { - /* do it later */ - upriv_bit = 1; - } break; } /* fall through */ @@ -1890,33 +1848,17 @@ int setdirparams(struct vol *vol, struct path *path, u_int16_t d_bitmap, char *b bitmap = bitmap>>1; bit++; } - ad_init(&ad, vol->v_adouble, vol->v_ad_options); - if (ad_open_metadata( upath, ADFLAGS_DIR, O_CREAT, &ad) < 0) { - /* - * Check to see what we're trying to set. If it's anything - * but ACCESS, UID, or GID, give an error. If it's any of those - * three, we don't need the ad to be open, so just continue. - * - * note: we also don't need to worry about mdate. also, be quiet - * if we're using the noadouble option. - */ - if (!vol_noadouble(vol) && (d_bitmap & - ~((1<u_name, d_bitmap); return AFPERR_ACCESS; } - - isad = 0; - } else { - /* - * Check to see if a create was necessary. If it was, we'll want - * to set our name, etc. - */ - if ( (ad_get_HF_flags( &ad ) & O_CREAT)) { + if ((ad_get_MD_flags(&ad) & O_CREAT)) { ad_setname(&ad, cfrombstr(curdir->d_m_name)); } + isad = 1; } bit = 0; @@ -1933,6 +1875,7 @@ int setdirparams(struct vol *vol, struct path *path, u_int16_t d_bitmap, char *b ad_getattr(&ad, &bshort); oshort = bshort; if ( ntohs( ashort ) & ATTRBIT_SETCLR ) { + ashort &= ~htons(vol->v_ignattr); bshort |= htons( ntohs( ashort ) & ~ATTRBIT_SETCLR ); } else { bshort &= ~ashort; @@ -1957,9 +1900,12 @@ int setdirparams(struct vol *vol, struct path *path, u_int16_t d_bitmap, char *b case DIRPBIT_FINFO : if (isad) { /* Fixes #2802236 */ - u_int16_t *fflags = (u_int16_t *)(finder_buf + FINDERINFO_FRFLAGOFF); - *fflags &= htons(~FINDERINFO_ISHARED); + uint16_t fflags; + memcpy(&fflags, finder_buf + FINDERINFO_FRFLAGOFF, sizeof(uint16_t)); + fflags &= htons(~FINDERINFO_ISHARED); + memcpy(finder_buf + FINDERINFO_FRFLAGOFF, &fflags, sizeof(uint16_t)); /* #2802236 end */ + if ( dir->d_did == DIRDID_ROOT ) { /* * Alright, we admit it, this is *really* sick! @@ -1978,7 +1924,7 @@ int setdirparams(struct vol *vol, struct path *path, u_int16_t d_bitmap, char *b break; case DIRPBIT_UID : /* What kind of loser mounts as root? */ if ( (dir->d_did == DIRDID_ROOT) && - (setdeskowner( ntohl(owner), -1 ) < 0)) { + (setdeskowner(vol, ntohl(owner), -1 ) < 0)) { err = set_dir_errors(path, "setdeskowner", errno); if (isad && err == AFPERR_PARAM) { err = AFP_OK; /* ???*/ @@ -1994,55 +1940,22 @@ int setdirparams(struct vol *vol, struct path *path, u_int16_t d_bitmap, char *b break; case DIRPBIT_GID : if (dir->d_did == DIRDID_ROOT) - setdeskowner( -1, ntohl(group) ); + setdeskowner(vol, -1, ntohl(group) ); if ( setdirowner(vol, upath, -1, ntohl(group) ) < 0 ) { err = set_dir_errors(path, "setdirowner", errno); goto setdirparam_done; } break; case DIRPBIT_ACCESS : - if (dir->d_did == DIRDID_ROOT) { - setdeskmode(mpriv); - if (!dir_rx_set(mpriv)) { - /* we can't remove read and search for owner on volume root */ - err = AFPERR_ACCESS; - goto setdirparam_done; - } - } - - if (!dir_rx_set(mpriv) && setdirmode( vol, upath, mpriv) < 0 ) { - err = set_dir_errors(path, "setdirmode", errno); - goto setdirparam_done; - } break; case DIRPBIT_PDINFO : - if (afp_version >= 30) { + if (vol->v_obj->afp_version >= 30) { err = AFPERR_BITMAP; goto setdirparam_done; } break; case DIRPBIT_UNIXPR : - if (vol_unix_priv(vol)) { - if (dir->d_did == DIRDID_ROOT) { - if (!dir_rx_set(upriv)) { - /* we can't remove read and search for owner on volume root */ - err = AFPERR_ACCESS; - goto setdirparam_done; - } - setdeskowner( -1, ntohl(group) ); - setdeskmode( upriv ); - } - if ( setdirowner(vol, upath, -1, ntohl(group) ) < 0 ) { - err = set_dir_errors(path, "setdirowner", errno); - goto setdirparam_done; - } - - if ( upriv_bit && setdirunixmode(vol, upath, upriv) < 0 ) { - err = set_dir_errors(path, "setdirunixmode", errno); - goto setdirparam_done; - } - } - else { + if (!vol_unix_priv(vol)) { err = AFPERR_BITMAP; goto setdirparam_done; } @@ -2068,18 +1981,69 @@ setdirparam_done: utime(upath, &ut); } - if ( isad ) { + if (isad) { if (path->st_valid && !path->st_errno) { struct stat *st = &path->st; - if (dir && dir->d_pdid) { ad_setid(&ad, st->st_dev, st->st_ino, dir->d_did, dir->d_pdid, vol->v_stamp); } } - ad_flush( &ad); - ad_close_metadata( &ad); + if (ad_flush(&ad) != 0) { + switch (errno) { + case EACCES: + err = AFPERR_ACCESS; + break; + default: + err = AFPERR_MISC; + break; + } + } + ad_close(&ad, ADFLAGS_HF); + } + + if (err == AFP_OK) { + if (set_maccess == true) { + if (dir->d_did == DIRDID_ROOT) { + setdeskmode(vol, mpriv); + if (!dir_rx_set(mpriv)) { + /* we can't remove read and search for owner on volume root */ + err = AFPERR_ACCESS; + goto setprivdone; + } + } + if (setdirunixmode(vol, upath, mpriv) < 0) { + LOG(log_info, logtype_afpd, "setdirparams(\"%s\"): setdirunixmode: %s", + fullpathname(upath), strerror(errno)); + err = set_dir_errors(path, "setdirmode", errno); + } + } + if ((set_upriv == true) && vol_unix_priv(vol)) { + if (dir->d_did == DIRDID_ROOT) { + if (!dir_rx_set(upriv)) { + /* we can't remove read and search for owner on volume root */ + err = AFPERR_ACCESS; + goto setprivdone; + } + setdeskowner(vol, -1, ntohl(group)); + setdeskmode(vol, upriv); + } + + if (setdirowner(vol, upath, -1, ntohl(group)) < 0) { + LOG(log_info, logtype_afpd, "setdirparams(\"%s\"): setdirowner: %s", + fullpathname(upath), strerror(errno)); + err = set_dir_errors(path, "setdirowner", errno); + goto setprivdone; + } + + if (setdirunixmode(vol, upath, upriv) < 0) { + LOG(log_info, logtype_afpd, "setdirparams(\"%s\"): setdirunixmode: %s", + fullpathname(upath), strerror(errno)); + err = set_dir_errors(path, "setdirunixmode", errno); + } + } } +setprivdone: if (change_parent_mdate && dir->d_did != DIRDID_ROOT && gettimeofday(&tv, NULL) == 0) { if (movecwd(vol, dirlookup(vol, dir->d_pdid)) == 0) { @@ -2090,7 +2054,6 @@ setdirparam_done: /* should we reset curdir ?*/ } } - return err; } @@ -2102,8 +2065,8 @@ int afp_syncdir(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *rbuf _U_, int dfd; struct vol *vol; struct dir *dir; - u_int32_t did; - u_int16_t vid; + uint32_t did; + uint16_t vid; *rbuflen = 0; ibuf += 2; @@ -2191,8 +2154,8 @@ int afp_createdir(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf, size_ struct dir *dir; char *upath; struct path *s_path; - u_int32_t did; - u_int16_t vid; + uint32_t did; + uint16_t vid; int err; *rbuflen = 0; @@ -2230,11 +2193,11 @@ int afp_createdir(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf, size_ return err; } - if (of_stat(s_path) < 0) { + if (of_stat(vol, s_path) < 0) { 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; @@ -2244,23 +2207,20 @@ int afp_createdir(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf, size_ return( AFPERR_PARAM ); } - ad_init(&ad, vol->v_adouble, vol->v_ad_options); - if (ad_open_metadata( ".", ADFLAGS_DIR, O_CREAT, &ad ) < 0) { - if (vol_noadouble(vol)) - goto createdir_done; + ad_init(&ad, vol); + if (ad_open(&ad, ".", ADFLAGS_HF | ADFLAGS_DIR | ADFLAGS_CREATE | ADFLAGS_RDWR, 0777) < 0) { return( AFPERR_ACCESS ); } 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); + fce_register(obj, FCE_DIR_CREATE, bdata(curdir->d_fullpath), NULL); - ad_flush( &ad); - ad_close_metadata( &ad); + ad_flush(&ad); + ad_close(&ad, ADFLAGS_HF); -createdir_done: - memcpy( rbuf, &dir->d_did, sizeof( u_int32_t )); - *rbuflen = sizeof( u_int32_t ); + memcpy( rbuf, &dir->d_did, sizeof( uint32_t )); + *rbuflen = sizeof( uint32_t ); setvoltime(obj, vol ); return( AFP_OK ); } @@ -2271,7 +2231,7 @@ createdir_done: * newparent curdir * dirfd -1 means ignore dirfd (or use AT_FDCWD), otherwise src is relative to dirfd */ -int renamedir(const struct vol *vol, +int renamedir(struct vol *vol, int dirfd, char *src, char *dst, @@ -2297,11 +2257,11 @@ int renamedir(const struct vol *vol, case EXDEV: /* this needs to copy and delete. bleah. that means we have * to deal with entire directory hierarchies. */ - if ((err = copydir(vol, dirfd, src, dst)) < 0) { - deletedir(-1, dst); + if ((err = copydir(vol, newparent, dirfd, src, dst)) < 0) { + deletedir(vol, -1, dst); return err; } - if ((err = deletedir(dirfd, src)) < 0) + if ((err = deletedir(vol, dirfd, src)) < 0) return err; break; default : @@ -2311,12 +2271,12 @@ int renamedir(const struct vol *vol, vol->vfs->vfs_renamedir(vol, dirfd, src, dst); - ad_init(&ad, vol->v_adouble, vol->v_ad_options); + ad_init(&ad, vol); - if (!ad_open_metadata( dst, ADFLAGS_DIR, 0, &ad)) { + if (ad_open(&ad, dst, ADFLAGS_HF | ADFLAGS_DIR | ADFLAGS_RDWR) == 0) { ad_setname(&ad, newname); - ad_flush( &ad); - ad_close_metadata( &ad); + ad_flush(&ad); + ad_close(&ad, ADFLAGS_HF); } return( AFP_OK ); @@ -2328,9 +2288,8 @@ int deletecurdir(struct vol *vol) struct dirent *de; struct stat st; struct dir *fdir, *pdir; - DIR *dp; struct adouble ad; - u_int16_t ashort; + uint16_t ashort; int err; if ((pdir = dirlookup(vol, curdir->d_pdid)) == NULL) { @@ -2339,45 +2298,23 @@ int deletecurdir(struct vol *vol) fdir = curdir; - ad_init(&ad, vol->v_adouble, vol->v_ad_options); + ad_init(&ad, vol); /* we never want to create a resource fork here, we are going to delete it */ if ( ad_metadata( ".", ADFLAGS_DIR, &ad) == 0 ) { ad_getattr(&ad, &ashort); - ad_close_metadata(&ad); - if ((ashort & htons(ATTRBIT_NODELETE))) { + ad_close(&ad, ADFLAGS_HF); + if (!(vol->v_ignattr & ATTRBIT_NODELETE) && (ashort & htons(ATTRBIT_NODELETE))) { return AFPERR_OLOCK; } } err = vol->vfs->vfs_deletecurdir(vol); if (err) { - LOG(log_error, logtype_afpd, "deletecurdir: error deleting .AppleDouble in \"%s\"", - curdir->d_fullpath); + LOG(log_error, logtype_afpd, "deletecurdir: error deleting AppleDouble files in \"%s\"", + cfrombstr(curdir->d_fullpath)); return err; } - /* now get rid of dangling symlinks */ - if ((dp = opendir("."))) { - while ((de = readdir(dp))) { - /* skip this and previous directory */ - if (!strcmp(de->d_name, ".") || !strcmp(de->d_name, "..")) - continue; - - /* bail if it's not a symlink */ - if ((lstat(de->d_name, &st) == 0) && !S_ISLNK(st.st_mode)) { - LOG(log_error, logtype_afpd, "deletecurdir(\"%s\"): not empty", - curdir->d_fullpath); - closedir(dp); - return AFPERR_DIRNEMPT; - } - - if ((err = netatalk_unlink(de->d_name))) { - closedir(dp); - return err; - } - } - } - if (movecwd(vol, pdir) < 0) { err = afp_errno; goto delete_done; @@ -2387,22 +2324,29 @@ int deletecurdir(struct vol *vol) cfrombstr(curdir->d_fullpath)); err = netatalk_rmdir_all_errors(-1, cfrombstr(fdir->d_u_name)); - if ( err == AFP_OK || err == AFPERR_NOOBJ) { - cnid_delete(vol->v_cdb, fdir->d_did); - dir_remove( vol, fdir ); - } else { + + switch (err) { + case AFP_OK: + case AFPERR_NOOBJ: + break; + case AFPERR_DIRNEMPT: + if (delete_vetoed_files(vol, bdata(fdir->d_u_name), false) != 0) + goto delete_done; + err = AFP_OK; + break; + default: LOG(log_error, logtype_afpd, "deletecurdir(\"%s\"): netatalk_rmdir_all_errors error", - curdir->d_fullpath); + cfrombstr(curdir->d_fullpath)); + goto delete_done; } + AFP_CNID_START("cnid_delete"); + cnid_delete(vol->v_cdb, fdir->d_did); + AFP_CNID_DONE(); + + dir_remove( vol, fdir ); + delete_done: - if (dp) { - /* inode is used as key for cnid. - * Close the descriptor only after cnid_delete - * has been called. - */ - closedir(dp); - } return err; } @@ -2411,7 +2355,7 @@ int afp_mapid(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf, size_t *r struct passwd *pw; struct group *gr; char *name; - u_int32_t id; + uint32_t id; int len, sfunc; int utf8 = 0; @@ -2420,7 +2364,7 @@ int afp_mapid(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf, size_t *r *rbuflen = 0; if (sfunc >= 3 && sfunc <= 6) { - if (afp_version < 30) { + if (obj->afp_version < 30) { return( AFPERR_PARAM ); } utf8 = 1; @@ -2460,7 +2404,7 @@ int afp_mapid(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf, size_t *r case 5 : /* UUID -> username */ case 6 : /* UUID -> groupname */ - if ((afp_version < 32) || !(obj->options.flags & OPTION_UUID )) + if ((obj->afp_version < 32) || !(obj->options.flags & OPTION_UUID )) return AFPERR_PARAM; LOG(log_debug, logtype_afpd, "afp_mapid: valid UUID request"); uuidtype_t type; @@ -2492,9 +2436,6 @@ int afp_mapid(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf, size_t *r rbuf += sizeof( id ); *rbuflen = 2 * sizeof( id ); break; - case UUID_LOCAL: - free(name); - return (AFPERR_NOITEM); default: return AFPERR_MISC; } @@ -2508,7 +2449,7 @@ int afp_mapid(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf, size_t *r len = strlen( name ); if (utf8) { - u_int16_t tp = htons(len); + uint16_t tp = htons(len); memcpy(rbuf, &tp, sizeof(tp)); rbuf += sizeof(tp); *rbuflen += 2; @@ -2526,22 +2467,22 @@ int afp_mapid(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf, size_t *r return( AFP_OK ); } -int afp_mapname(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *rbuf, size_t *rbuflen) +int afp_mapname(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf, size_t *rbuflen) { struct passwd *pw; struct group *gr; int len, sfunc; - u_int32_t id; - u_int16_t ulen; + uint32_t id; + uint16_t ulen; ibuf++; sfunc = (unsigned char) *ibuf++; *rbuflen = 0; - LOG(log_debug, logtype_afpd, "afp_mapname: sfunc: %d, afp_version: %d", sfunc, afp_version); + LOG(log_debug, logtype_afpd, "afp_mapname: sfunc: %d", sfunc); switch ( sfunc ) { case 1 : case 2 : /* unicode */ - if (afp_version < 30) { + if (obj->afp_version < 30) { return( AFPERR_PARAM ); } memcpy(&ulen, ibuf, sizeof(ulen)); @@ -2555,7 +2496,7 @@ int afp_mapname(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *rbuf, siz break; case 5 : /* username -> UUID */ case 6 : /* groupname -> UUID */ - if ((afp_version < 32) || !(obj->options.flags & OPTION_UUID )) + if ((obj->afp_version < 32) || !(obj->options.flags & OPTION_UUID )) return AFPERR_PARAM; memcpy(&ulen, ibuf, sizeof(ulen)); len = ntohs(ulen); @@ -2584,12 +2525,12 @@ int afp_mapname(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *rbuf, siz case 2 : /* unicode */ case 4 : - LOG(log_debug, logtype_afpd, "afp_mapname: gettgrnam for name: %s",ibuf); + LOG(log_debug, logtype_afpd, "afp_mapname: getgrnam for name: %s",ibuf); if (NULL == ( gr = (struct group *)getgrnam( ibuf ))) { return( AFPERR_NOITEM ); } id = gr->gr_gid; - LOG(log_debug, logtype_afpd, "afp_mapname: gettgrnam for name: %s -> id: %d",ibuf, id); + LOG(log_debug, logtype_afpd, "afp_mapname: getgrnam for name: %s -> id: %d",ibuf, id); id = htonl(id); memcpy( rbuf, &id, sizeof( id )); *rbuflen = sizeof( id ); @@ -2619,8 +2560,8 @@ int afp_closedir(AFPObj *obj _U_, char *ibuf _U_, size_t ibuflen _U_, char *rbuf #if 0 struct vol *vol; struct dir *dir; - u_int16_t vid; - u_int32_t did; + uint16_t vid; + uint32_t did; #endif /* 0 */ *rbuflen = 0; @@ -2655,8 +2596,8 @@ int afp_opendir(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *rbuf, si struct vol *vol; struct dir *parentdir; struct path *path; - u_int32_t did; - u_int16_t vid; + uint32_t did; + uint16_t vid; *rbuflen = 0; ibuf += 2; @@ -2683,7 +2624,7 @@ int afp_opendir(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *rbuf, si return path_error(path, AFPERR_NOOBJ); } - if ( !path->st_valid && of_stat(path ) < 0 ) { + if ( !path->st_valid && of_stat(vol, path) < 0 ) { return( AFPERR_NOOBJ ); } if ( path->st_errno ) {