X-Git-Url: https://arthur.barton.de/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=etc%2Fafpd%2Fofork.c;h=59e9f153041d4da0768055a9f548ada9dd594171;hb=HEAD;hp=fc91c03b18fa51f44f48be121d1672a2e6f5ab84;hpb=080aff015fa627cab032d6009ff3b27e7c2a46d6;p=netatalk.git diff --git a/etc/afpd/ofork.c b/etc/afpd/ofork.c index fc91c03b..59e9f153 100644 --- a/etc/afpd/ofork.c +++ b/etc/afpd/ofork.c @@ -23,10 +23,12 @@ #include #include #include +#include #include "volume.h" #include "directory.h" #include "fork.h" +#include "desktop.h" /* we need to have a hashed list of oforks (by dev inode) */ #define OFORK_HASHSIZE 64 @@ -228,14 +230,14 @@ struct ofork *of_find(const uint16_t ofrefnum ) } /* -------------------------- */ -int of_stat(struct path *path) +int of_stat(const struct vol *vol, struct path *path) { int ret; path->st_errno = 0; path->st_valid = 1; - if ((ret = lstat(path->u_name, &path->st)) < 0) { + if ((ret = ostat(path->u_name, &path->st, vol_syml_opt(vol))) < 0) { LOG(log_debug, logtype_afpd, "of_stat('%s/%s': %s)", cfrombstr(curdir->d_fullpath), path->u_name, strerror(errno)); path->st_errno = errno; @@ -274,7 +276,7 @@ int of_statdir(struct vol *vol, struct path *path) if (*path->m_name) { /* not curdir */ - return of_stat (path); + return of_stat(vol, path); } path->st_errno = 0; path->st_valid = 1; @@ -286,7 +288,7 @@ int of_statdir(struct vol *vol, struct path *path) LOG(log_debug, logtype_afpd, "of_statdir: stating: '%s'", pathname); - if (!(ret = lstat(pathname, &path->st))) + if (!(ret = ostat(pathname, &path->st, vol_syml_opt(vol)))) return 0; path->st_errno = errno; @@ -297,7 +299,7 @@ int of_statdir(struct vol *vol, struct path *path) return -1; path->st_errno = 0; - if ((ret = lstat(cfrombstr(path->d_dir->d_u_name), &path->st)) < 0) + if ((ret = ostat(cfrombstr(path->d_dir->d_u_name), &path->st, vol_syml_opt(vol))) < 0) path->st_errno = errno; } @@ -305,13 +307,13 @@ int of_statdir(struct vol *vol, struct path *path) } /* -------------------------- */ -struct ofork *of_findname(struct path *path) +struct ofork *of_findname(const struct vol *vol, struct path *path) { struct ofork *of; struct file_key key; if (!path->st_valid) { - of_stat(path); + of_stat(vol, path); } if (path->st_errno) @@ -364,7 +366,7 @@ struct ofork *of_findnameat(int dirfd, struct path *path) } #endif -void of_dealloc( struct ofork *of) +void of_dealloc(struct ofork *of) { if (!oforks) return; @@ -378,19 +380,19 @@ void of_dealloc( struct ofork *of) if ( of->of_ad->ad_refcount <= 0) { free( of->of_ad->ad_name ); free( of->of_ad); - } else {/* someone's still using it. just free this user's locks */ - ad_unlock(of->of_ad, of->of_refnum, of->of_flags & AFPFORK_ERROR ? 0 : 1); } free( of ); } /* --------------------------- */ -int of_closefork(struct ofork *ofork) +int of_closefork(const AFPObj *obj, struct ofork *ofork) { struct timeval tv; int adflags = 0; int ret; + struct dir *dir; + bstring forkpath = NULL; adflags = 0; if (ofork->of_flags & AFPFORK_DATA) @@ -407,17 +409,74 @@ int of_closefork(struct ofork *ofork) } } + dir = dirlookup(ofork->of_vol, ofork->of_did); + if (dir == NULL) { + LOG(log_debug, logtype_afpd, "dirlookup failed for %ju", (uintmax_t)ofork->of_did); + } + + if (dir) { + forkpath = bformat("%s/%s", bdata(dir->d_fullpath), of_name(ofork)); + } + /* Somone has used write_fork, we assume file was changed, register it to file change event api */ - if (ofork->of_flags & AFPFORK_MODIFIED) { - fce_register_file_modification(ofork); + if ((ofork->of_flags & AFPFORK_MODIFIED) && (forkpath)) { + fce_register(obj, FCE_FILE_MODIFY, bdata(forkpath), NULL); } + ad_unlock(ofork->of_ad, ofork->of_refnum, ofork->of_flags & AFPFORK_ERROR ? 0 : 1); + +#ifdef HAVE_FSHARE_T + if (obj->options.flags & OPTION_SHARE_RESERV) { + fshare_t shmd; + shmd.f_id = ofork->of_refnum; + if (AD_DATA_OPEN(ofork->of_ad)) + fcntl(ad_data_fileno(ofork->of_ad), F_UNSHARE, &shmd); + if (AD_RSRC_OPEN(ofork->of_ad)) + fcntl(ad_reso_fileno(ofork->of_ad), F_UNSHARE, &shmd); + } +#endif + ret = 0; + + /* + * Check for 0 byte size resource forks, delete them. + * Here's the deal: + * (1) the size must be 0 + * (2) the fork must refer to a resource fork + * (3) the refcount must be 1 which means this fork has the last + * reference to the adouble struct and the subsequent + * ad_close() will close the assoiciated fd. + * (4) nobody else has the resource fork open + * + * We only do this for ._ AppleDouble resource forks, not for + * xattr resource forks, because the test-suite then fails several + * tests on Solaris, the reason for that still needs to be + * determined. + */ + if ((ofork->of_ad->ad_rlen == 0) + && (ofork->of_flags & AFPFORK_RSRC) + && (ofork->of_ad->ad_rfp->adf_refcount == 1) + && (ad_openforks(ofork->of_ad, ATTRBIT_DOPEN) == 0)) { + +#ifndef HAVE_EAFD + (void)unlink(ofork->of_ad->ad_ops->ad_path( + mtoupath(ofork->of_vol, + of_name(ofork), + ofork->of_did, + utf8_encoding(obj)), + 0)); +#endif + } + if ( ad_close( ofork->of_ad, adflags | ADFLAGS_SETSHRMD) < 0 ) { ret = -1; } - of_dealloc( ofork ); + of_dealloc(ofork); + + if (forkpath) + bdestroy(forkpath); + return ret; } @@ -429,7 +488,7 @@ struct adouble *of_ad(const struct vol *vol, struct path *path, struct adouble * struct ofork *of; struct adouble *adp; - if ((of = of_findname(path))) { + if ((of = of_findname(vol, path))) { adp = of->of_ad; } else { ad_init(ad, vol); @@ -441,7 +500,7 @@ struct adouble *of_ad(const struct vol *vol, struct path *path, struct adouble * /* ---------------------- close all forks for a volume */ -void of_closevol(const struct vol *vol) +void of_closevol(const AFPObj *obj, const struct vol *vol) { int refnum; @@ -450,7 +509,7 @@ void of_closevol(const struct vol *vol) for ( refnum = 0; refnum < nforks; refnum++ ) { if (oforks[ refnum ] != NULL && oforks[refnum]->of_vol == vol) { - if (of_closefork( oforks[ refnum ]) < 0 ) { + if (of_closefork(obj, oforks[ refnum ]) < 0 ) { LOG(log_error, logtype_afpd, "of_closevol: %s", strerror(errno) ); } } @@ -461,7 +520,7 @@ void of_closevol(const struct vol *vol) /* ---------------------- close all forks for a volume */ -void of_close_all_forks(void) +void of_close_all_forks(const AFPObj *obj) { int refnum; @@ -470,7 +529,7 @@ void of_close_all_forks(void) for ( refnum = 0; refnum < nforks; refnum++ ) { if (oforks[ refnum ] != NULL) { - if (of_closefork( oforks[ refnum ]) < 0 ) { + if (of_closefork(obj, oforks[ refnum ]) < 0 ) { LOG(log_error, logtype_afpd, "of_close_all_forks: %s", strerror(errno) ); } }