X-Git-Url: https://arthur.barton.de/cgi-bin/gitweb.cgi?p=netatalk.git;a=blobdiff_plain;f=etc%2Fafpd%2Ffiledir.c;h=d3976119444440fbc07a8422b4c4c12c57bf043b;hp=bf3a8c0681c1fea7b5ab371ef53a923923716998;hb=5116ed2346ea7ee6e5a9858dee94f3eacdc00d7e;hpb=8f6bea54f2115259a524ebade0fa346be1e0c2dd diff --git a/etc/afpd/filedir.c b/etc/afpd/filedir.c index bf3a8c06..d3976119 100644 --- a/etc/afpd/filedir.c +++ b/etc/afpd/filedir.c @@ -1,6 +1,4 @@ /* - * $Id: filedir.c,v 1.73 2010/03/12 15:16:49 franklahm Exp $ - * * Copyright (c) 1990,1993 Regents of The University of Michigan. * All Rights Reserved. See COPYRIGHT. */ @@ -41,6 +39,7 @@ char *strchr (), *strrchr (); #include #include #include +#include #include "directory.h" #include "dircache.h" @@ -51,6 +50,7 @@ char *strchr (), *strrchr (); #include "globals.h" #include "filedir.h" #include "unix.h" +#include "fce_api.h" #ifdef DROPKLUDGE int matchfile2dirperms( @@ -176,7 +176,7 @@ int afp_getfildirparams(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *r LOG(log_debug, logtype_afpd, "getfildirparams(vid:%u, did:%u, f/d:%04x/%04x) {cwdid:%u, cwd: %s, name:'%s'}", ntohs(vid), ntohl(dir->d_did), fbitmap, dbitmap, - ntohl(curdir->d_did), cfrombstring(curdir->d_fullpath), s_path->u_name); + ntohl(curdir->d_did), cfrombstr(curdir->d_fullpath), s_path->u_name); st = &s_path->st; if (!s_path->st_valid) { @@ -329,7 +329,7 @@ static int moveandrename(const struct vol *vol, char *newname, int isdir) { - char *p; + char *oldunixname = NULL; char *upath; int rc; struct stat *st, nst; @@ -339,97 +339,112 @@ static int moveandrename(const struct vol *vol, struct ofork *opened = NULL; struct path path; cnid_t id; - int cwd_fd; + int cwd_fd = -1; + + LOG(log_debug, logtype_afpd, + "moveandrename: [\"%s\"/\"%s\"] -> \"%s\"", + cfrombstr(sdir->d_u_name), oldname, newname); ad_init(&ad, vol->v_adouble, vol->v_ad_options); adp = &ad; adflags = 0; if (!isdir) { - if ((p = mtoupath(vol, oldname, sdir->d_did, utf8_encoding())) == NULL) + if ((oldunixname = strdup(mtoupath(vol, oldname, sdir->d_did, utf8_encoding()))) == NULL) return AFPERR_PARAM; /* can't convert */ + id = cnid_get(vol->v_cdb, sdir->d_did, oldunixname, strlen(oldunixname)); -#ifndef HAVE_RENAMEAT +#ifndef HAVE_ATFUNCS /* Need full path */ - id = cnid_get(vol->v_cdb, sdir->d_did, p, strlen(p)); - p = ctoupath( vol, sdir, oldname ); - if (!p) + free(oldunixname); + if ((oldunixname = strdup(ctoupath(vol, sdir, oldname))) == NULL) return AFPERR_PARAM; /* pathname too long */ -#endif /* HAVE_RENAMEAT */ +#endif /* HAVE_ATFUNCS */ path.st_valid = 0; - path.u_name = p; -#ifdef HAVE_RENAMEAT + path.u_name = oldunixname; + +#ifdef HAVE_ATFUNCS opened = of_findnameat(sdir_fd, &path); #else opened = of_findname(&path); -#endif /* HAVE_RENAMEAT */ +#endif /* HAVE_ATFUNCS */ + if (opened) { /* reuse struct adouble so it won't break locks */ adp = opened->of_ad; } } else { id = sdir->d_did; /* we already have the CNID */ - p = ctoupath( vol, dirlookup(vol, sdir->d_pdid), oldname ); - if (!p) { + if ((oldunixname = strdup(ctoupath( vol, dirlookup(vol, sdir->d_pdid), oldname))) == NULL) return AFPERR_PARAM; - } adflags = ADFLAGS_DIR; } /* - * p now points to either + * oldunixname now points to either * a) full pathname of the source fs object (if renameat is not available) * b) the oldname (renameat is available) * we are in the dest folder so we need to use - * a) p for ad_open + * a) oldunixname for ad_open * b) fchdir sdir_fd before eg ad_open or use *at functions where appropiate */ if (sdir_fd != -1) { if ((cwd_fd = open(".", O_RDONLY)) == -1) return AFPERR_MISC; - if (fchdir(sdir_fd) != 0) - return AFPERR_MISC; + if (fchdir(sdir_fd) != 0) { + rc = AFPERR_MISC; + goto exit; + } } - if (!ad_metadata(p, adflags, adp)) { + if (!ad_metadata(oldunixname, adflags, adp)) { u_int16_t bshort; ad_getattr(adp, &bshort); ad_close_metadata( adp); - if ((bshort & htons(ATTRBIT_NORENAME))) - return(AFPERR_OLOCK); + if ((bshort & htons(ATTRBIT_NORENAME))) { + rc = AFPERR_OLOCK; + goto exit; + } } if (sdir_fd != -1) { if (fchdir(cwd_fd) != 0) { LOG(log_error, logtype_afpd, "moveandrename: %s", strerror(errno) ); - return AFPERR_MISC; + rc = AFPERR_MISC; + goto exit; } } - if (NULL == (upath = mtoupath(vol, newname, curdir->d_did, utf8_encoding()))){ - return AFPERR_PARAM; + if (NULL == (upath = mtoupath(vol, newname, curdir->d_did, utf8_encoding()))){ + rc = AFPERR_PARAM; + goto exit; } path.u_name = upath; st = &path.st; if (0 != (rc = check_name(vol, upath))) { - return rc; + goto exit; } /* source == destination. we just silently accept this. */ if ((!isdir && curdir == sdir) || (isdir && curdir->d_did == sdir->d_pdid)) { - if (strcmp(oldname, newname) == 0) - return AFP_OK; + if (strcmp(oldname, newname) == 0) { + rc = AFP_OK; + goto exit; + } if (stat(upath, st) == 0 || caseenumerate(vol, &path, curdir) == 0) { - if (!stat(p, &nst) && !(nst.st_dev == st->st_dev && nst.st_ino == st->st_ino) ) { + if (!stat(oldunixname, &nst) && !(nst.st_dev == st->st_dev && nst.st_ino == st->st_ino) ) { /* not the same file */ - return AFPERR_EXIST; + rc = AFPERR_EXIST; + goto exit; } errno = 0; } - } else if (stat(upath, st ) == 0 || caseenumerate(vol, &path, curdir) == 0) - return AFPERR_EXIST; + } else if (stat(upath, st ) == 0 || caseenumerate(vol, &path, curdir) == 0) { + rc = AFPERR_EXIST; + goto exit; + } if ( !isdir ) { path.st_valid = 1; @@ -437,22 +452,43 @@ static int moveandrename(const struct vol *vol, if (of_findname(&path)) { rc = AFPERR_EXIST; /* was AFPERR_BUSY; */ } else { - rc = renamefile(vol, sdir_fd, p, upath, newname, adp ); + rc = renamefile(vol, sdir_fd, oldunixname, upath, newname, adp ); if (rc == AFP_OK) of_rename(vol, opened, sdir, oldname, curdir, newname); } } else { - rc = renamedir(vol, sdir_fd, p, upath, sdir, curdir, newname); + rc = renamedir(vol, sdir_fd, oldunixname, upath, sdir, curdir, newname); } if ( rc == AFP_OK && id ) { /* renaming may have moved the file/dir across a filesystem */ - if (stat(upath, st) < 0) - return AFPERR_MISC; + if (stat(upath, st) < 0) { + rc = AFPERR_MISC; + goto exit; + } + + /* Remove it from the cache */ + struct dir *cacheddir = dircache_search_by_did(vol, id); + if (cacheddir) { + LOG(log_warning, logtype_afpd,"Still cached: \"%s/%s\"", getcwdpath(), upath); + (void)dir_remove(vol, cacheddir); + } + + /* Fixup adouble info */ + if (!ad_metadata(upath, adflags, adp)) { + ad_setid(adp, st->st_dev, st->st_ino, id, curdir->d_did, vol->v_stamp); + ad_flush(adp); + ad_close_metadata(adp); + } /* fix up the catalog entry */ cnid_update(vol->v_cdb, id, st, curdir->d_did, upath, strlen(upath)); } +exit: + if (cwd_fd != -1) + close(cwd_fd); + if (oldunixname) + free(oldunixname); return rc; } @@ -511,7 +547,7 @@ int afp_rename(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf _U_, size if ( movecwd( vol, dirlookup(vol, sdir->d_pdid) ) < 0 ) { return afp_errno; } - memcpy(oldname, cfrombstring(sdir->d_m_name), blength(sdir->d_m_name) +1); + memcpy(oldname, cfrombstr(sdir->d_m_name), blength(sdir->d_m_name) +1); } /* another place where we know about the path type */ @@ -568,8 +604,14 @@ int afp_delete(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf _U_, size if ( path_isadir( s_path) ) { 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 { @@ -579,13 +621,13 @@ int afp_delete(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf _U_, size */ 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))) { - dircache_remove(vol, dir, DIRCACHE | DIDNAME_INDEX | QUEUE_INDEX); + 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); } } @@ -615,9 +657,9 @@ char *absupath(const struct vol *vol, struct dir *dir, char *u) if (path->slen > MAXPATHLEN) return NULL; - LOG(log_debug, logtype_afpd, "absupath: %s", cfrombstring(path)); + LOG(log_debug, logtype_afpd, "absupath: %s", cfrombstr(path)); - strncpy(pathbuf, cfrombstring(path), blength(path) + 1); + strncpy(pathbuf, cfrombstr(path), blength(path) + 1); bdestroy(path); return(pathbuf); @@ -687,10 +729,10 @@ int afp_moveandrename(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf _U } strcpy(oldname, path->m_name); /* an extra copy for of_rename */ } else { - memcpy(oldname, cfrombstring(sdir->d_m_name), blength(sdir->d_m_name) + 1); + memcpy(oldname, cfrombstr(sdir->d_m_name), blength(sdir->d_m_name) + 1); } -#ifdef HAVE_RENAMEAT +#ifdef HAVE_ATFUNCS if ((sdir_fd = open(".", O_RDONLY)) == -1) return AFPERR_MISC; #endif @@ -755,7 +797,7 @@ int afp_moveandrename(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf _U } exit: -#ifdef HAVE_RENAMEAT +#ifdef HAVE_ATFUNCS if (sdir_fd != -1) close(sdir_fd); #endif