X-Git-Url: https://arthur.barton.de/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=etc%2Fafpd%2Ffiledir.c;h=c6bcc34e19181b50f61c9dee6adc91072f79e7f1;hb=b362b6f7b22b6e4e9e74760989f389149677917b;hp=be7056a796ab9c0729d1b8d4307c54ca5f3818d8;hpb=ff3b4646472add7902b0d36dd1a941ec1a54e999;p=netatalk.git diff --git a/etc/afpd/filedir.c b/etc/afpd/filedir.c index be7056a7..c6bcc34e 100644 --- a/etc/afpd/filedir.c +++ b/etc/afpd/filedir.c @@ -40,6 +40,8 @@ char *strchr (), *strrchr (); #include #include #include +#include +#include #include "directory.h" #include "dircache.h" @@ -47,7 +49,6 @@ char *strchr (), *strrchr (); #include "volume.h" #include "fork.h" #include "file.h" -#include "globals.h" #include "filedir.h" #include "unix.h" @@ -93,28 +94,33 @@ int matchfile2dirperms( if ( uid != sb.st_uid ) { seteuid(0); - if (lchown(upath, sb.st_uid, sb.st_gid) < 0) + if (ochown(upath, sb.st_uid, sb.st_gid, vol_syml_opt(vol)) < 0) { LOG(log_error, logtype_afpd, "matchfile2dirperms(%s): Error changing owner/gid: %s", upath, strerror(errno)); ret = AFPERR_ACCESS; } - else if ((!S_ISLNK(st->st_mode)) && (chmod(upath,(st.st_mode&~default_options.umask)| S_IRGRP| S_IROTH) < 0)) - { + else if (ochmod(upath, + (st.st_mode & ~default_options.umask) | S_IRGRP | S_IROTH, + &sb, + vol_syml_opt(vol) | O_NETATALK_ACL) < 0) { LOG(log_error, logtype_afpd, "matchfile2dirperms(%s): Error adding file read permissions: %s", upath, strerror(errno)); ret = AFPERR_ACCESS; } - else if (lchown(adpath, sb.st_uid, sb.st_gid) < 0) + else if (ochown(adpath, sb.st_uid, sb.st_gid, vol_syml_opt(vol)) < 0) { LOG(log_error, logtype_afpd, "matchfile2dirperms(%s): Error changing AppleDouble owner/gid: %s", adpath, strerror(errno)); ret = AFPERR_ACCESS; } - else if (chmod(adpath, (st.st_mode&~default_options.umask)| S_IRGRP| S_IROTH) < 0) + else if (ochmod(adpath, + (st.st_mode & ~default_options.umask) | S_IRGRP| S_IROTH, + &st, + vol_syml_opt(vol) | O_NETATALK_ACL) < 0) { LOG(log_error, logtype_afpd, "matchfile2dirperms(%s): Error adding AD file read permissions: %s", @@ -328,7 +334,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; @@ -340,48 +346,52 @@ static int moveandrename(const struct vol *vol, cnid_t id; 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 */ @@ -393,7 +403,7 @@ static int moveandrename(const struct vol *vol, goto exit; } } - if (!ad_metadata(p, adflags, adp)) { + if (!ad_metadata(oldunixname, adflags, adp)) { u_int16_t bshort; ad_getattr(adp, &bshort); @@ -429,7 +439,7 @@ static int moveandrename(const struct vol *vol, } 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 */ rc = AFPERR_EXIST; goto exit; @@ -444,15 +454,15 @@ static int moveandrename(const struct vol *vol, if ( !isdir ) { path.st_valid = 1; path.st_errno = errno; - if (of_findname(&path)) { + if (of_findname(vol, &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 */ @@ -468,6 +478,13 @@ static int moveandrename(const struct vol *vol, (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)); } @@ -475,6 +492,8 @@ static int moveandrename(const struct vol *vol, exit: if (cwd_fd != -1) close(cwd_fd); + if (oldunixname) + free(oldunixname); return rc; } @@ -588,11 +607,19 @@ int afp_delete(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf _U_, size upath = s_path->u_name; if ( path_isadir( s_path) ) { - if (*s_path->m_name != '\0' || curdir->d_did == DIRDID_ROOT) + if (*s_path->m_name != '\0' || curdir->d_did == DIRDID_ROOT) { rc = AFPERR_ACCESS; - else - rc = deletecurdir( vol); - } else if (of_findname(s_path)) { + } else { + /* we have to cache this, the structs are lost in deletcurdir*/ + /* but we need the positive returncode to send our event */ + bstring dname; + if ((dname = bstrcpy(curdir->d_u_name)) == NULL) + return AFPERR_MISC; + if ((rc = deletecurdir(vol)) == AFP_OK) + fce_register_delete_dir(cfrombstr(dname)); + bdestroy(dname); + } + } else if (of_findname(vol, s_path)) { rc = AFPERR_BUSY; } else { /* it's a file st_valid should always be true @@ -601,19 +628,23 @@ 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 ); + if (vol->v_tm_used < s_path->st.st_size) + vol->v_tm_used = 0; + else + vol->v_tm_used -= s_path->st.st_size; + } struct dir *cachedfile; - if ((cachedfile = dircache_search_by_name(vol, dir, upath, strlen(upath), s_path->st.st_ctime))) { + if ((cachedfile = dircache_search_by_name(vol, dir, upath, strlen(upath)))) { dircache_remove(vol, cachedfile, DIRCACHE | DIDNAME_INDEX | QUEUE_INDEX); dir_free(cachedfile); } } } if ( rc == AFP_OK ) { - curdir->offcnt--; + curdir->d_offcnt--; setvoltime(obj, vol ); } @@ -712,7 +743,7 @@ int afp_moveandrename(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf _U 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 @@ -754,8 +785,8 @@ int afp_moveandrename(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf _U rc = AFPERR_PARAM; goto exit; } - curdir->offcnt++; - sdir->offcnt--; + curdir->d_offcnt++; + sdir->d_offcnt--; #ifdef DROPKLUDGE if (vol->v_flags & AFPVOL_DROPBOX) { /* FIXME did is not always the source id */ @@ -770,14 +801,14 @@ int afp_moveandrename(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf _U if (!isdir && !vol_unix_priv(vol)) { int admode = ad_mode("", 0777) | vol->v_fperm; - setfilmode(upath, admode, NULL, vol->v_umask); - vol->vfs->vfs_setfilmode(vol, upath, admode, NULL); + setfilmode(vol, upath, admode, path->st_valid ? &path->st : NULL); + vol->vfs->vfs_setfilmode(vol, upath, admode, path->st_valid ? &path->st : NULL); } setvoltime(obj, vol ); } exit: -#ifdef HAVE_RENAMEAT +#ifdef HAVE_ATFUNCS if (sdir_fd != -1) close(sdir_fd); #endif