*
* @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;
/* 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));
cfrombstr(l->entry[i]),
blength(l->entry[i]))) == NULL) {
- if ((cnid = cnid_add(vol->v_cdb, /* 6. */
- &st,
- did,
- cfrombstr(l->entry[i]),
- blength(l->entry[i]),
- 0)) == CNID_INVALID)
+ 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. */
/* 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_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;
cnid_t id;
struct adouble ad;
struct adouble *adp = NULL;
- bstring fullpath;
+ bstring fullpath = NULL;
AFP_ASSERT(vol);
AFP_ASSERT(dir);
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);
}
/* 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;
}
ashort = htons(ATTRBIT_INVISIBLE);
} else
ashort = 0;
+ ashort &= ~htons(vol->v_ignattr);
memcpy( data, &ashort, sizeof( ashort ));
data += sizeof( ashort );
break;
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);
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;
ad_flush(&ad);
ad_close(&ad, ADFLAGS_HF);
-createdir_done:
memcpy( rbuf, &dir->d_did, sizeof( uint32_t ));
*rbuflen = sizeof( uint32_t );
setvoltime(obj, vol );
struct dirent *de;
struct stat st;
struct dir *fdir, *pdir;
- DIR *dp;
struct adouble ad;
uint16_t ashort;
int err;
ad_getattr(&ad, &ashort);
ad_close(&ad, ADFLAGS_HF);
- if ((ashort & htons(ATTRBIT_NODELETE))) {
+ 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\"",
+ 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",
- bdata(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;
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",
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;
}