X-Git-Url: https://arthur.barton.de/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=etc%2Fafpd%2Ffork.c;h=c7025a8f479fe8b5399b68a8c9201ca4d3dd1316;hb=aa105c51d67fe1ab7cfde61d6cd27ceeed3284db;hp=9b41b956a0158ef3367617d0f150186f714a8bbb;hpb=080aff015fa627cab032d6009ff3b27e7c2a46d6;p=netatalk.git diff --git a/etc/afpd/fork.c b/etc/afpd/fork.c index 9b41b956..c7025a8f 100644 --- a/etc/afpd/fork.c +++ b/etc/afpd/fork.c @@ -25,6 +25,7 @@ #include #include #include +#include #include "fork.h" #include "file.h" @@ -143,7 +144,7 @@ static int sum_neg(int is64, off_t offset, off_t reqcount) return 0; } -static int fork_setmode(struct adouble *adp, int eid, int access, int ofrefnum) +static int fork_setmode(const AFPObj *obj, struct adouble *adp, int eid, int access, int ofrefnum) { int ret; int readset; @@ -151,6 +152,27 @@ static int fork_setmode(struct adouble *adp, int eid, int access, int ofrefnum) int denyreadset; int denywriteset; +#ifdef HAVE_FSHARE_T + fshare_t shmd; + + if (obj->options.flags & OPTION_SHARE_RESERV) { + shmd.f_access = (access & OPENACC_RD ? F_RDACC : 0) | (access & OPENACC_WR ? F_WRACC : 0); + if (shmd.f_access == 0) + /* we must give an access mode, otherwise fcntl will complain */ + shmd.f_access = F_RDACC; + shmd.f_deny = (access & OPENACC_DRD ? F_RDDNY : F_NODNY) | (access & OPENACC_DWR) ? F_WRDNY : 0; + shmd.f_id = ofrefnum; + + int fd = (eid == ADEID_DFORK) ? ad_data_fileno(adp) : ad_reso_fileno(adp); + + if (fd != -1 && fd != -2 && fcntl(fd, F_SHARE, &shmd) != 0) { + LOG(log_debug, logtype_afpd, "fork_setmode: fcntl: %s", strerror(errno)); + errno = EACCES; + return -1; + } + } +#endif + if (! (access & (OPENACC_WR | OPENACC_RD | OPENACC_DWR | OPENACC_DRD))) { return ad_lock(adp, eid, ADLOCK_RD | ADLOCK_FILELOCK, AD_FILELOCK_OPEN_NONE, 1, ofrefnum); } @@ -435,7 +457,7 @@ int afp_openfork(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *rbuf, si ad_getattr(ofork->of_ad, &bshort); if ((bshort & htons(ATTRBIT_NOWRITE)) && (access & OPENACC_WR)) { ad_close( ofork->of_ad, adflags | ADFLAGS_SETSHRMD); - of_dealloc( ofork ); + of_dealloc(obj, ofork ); ofrefnum = 0; memcpy(rbuf, &ofrefnum, sizeof(ofrefnum)); return(AFPERR_OLOCK); @@ -450,13 +472,13 @@ int afp_openfork(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *rbuf, si if ((eid == ADEID_DFORK) || (ad_reso_fileno(ofork->of_ad) != -1) || (ofork->of_ad->ad_vers == AD_VERSION_EA)) { - ret = fork_setmode(ofork->of_ad, eid, access, ofrefnum); + ret = fork_setmode(obj, ofork->of_ad, eid, access, ofrefnum); /* can we access the fork? */ if (ret < 0) { ofork->of_flags |= AFPFORK_ERROR; ret = errno; ad_close( ofork->of_ad, adflags | ADFLAGS_SETSHRMD); - of_dealloc( ofork ); + of_dealloc(obj, ofork ); switch (ret) { case EAGAIN: /* return data anyway */ case EACCES: @@ -482,7 +504,7 @@ int afp_openfork(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *rbuf, si return( AFP_OK ); openfork_err: - of_dealloc( ofork ); + of_dealloc(obj, ofork); if (errno == EACCES) return (access & OPENACC_WR) ? AFPERR_LOCK : AFPERR_ACCESS; return ret; @@ -573,15 +595,8 @@ int afp_setforkparams(AFPObj *obj, char *ibuf, size_t ibuflen, char *rbuf _U_, s ad_tmplock(ofork->of_ad, eid, ADLOCK_WR, size, st_size -size, ofork->of_refnum) < 0) { goto afp_setfork_err; } - if (ofork->of_ad->ad_vers == AD_VERSION_EA) { -#if HAVE_EAFD - err = sys_lremovexattr(of_name(ofork), AD_EA_RESO); -#else - err = unlink(ofork->of_vol->ad_path(of_name(ofork), 0)); -#endif - } else { - err = ad_rtruncate(ofork->of_ad, size); - } + + err = ad_rtruncate(ofork->of_ad, size); if (st_size > size) ad_tmplock(ofork->of_ad, eid, ADLOCK_CLR, size, st_size -size, ofork->of_refnum); if (err < 0) @@ -885,22 +900,22 @@ static int read_fork(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf, si /* due to the nature of afp packets, we have to exit if we get an error. we can't do this with translation on. */ #ifdef WITH_SENDFILE - int fd; - - fd = ad_readfile_init(ofork->of_ad, eid, &offset, 0); - - if (dsi_stream_read_file(dsi, fd, offset, dsi->datasize) < 0) { - if (errno == EINVAL || errno == ENOSYS) - goto afp_read_loop; - else { - LOG(log_error, logtype_afpd, "afp_read(%s): ad_readfile: %s", of_name(ofork), strerror(errno)); - goto afp_read_exit; + if (!(obj->options.flags & OPTION_NOSENDFILE)) { + int fd = ad_readfile_init(ofork->of_ad, eid, &offset, 0); + if (dsi_stream_read_file(dsi, fd, offset, dsi->datasize) < 0) { + switch (errno) { + case EINVAL: + case ENOSYS: + goto afp_read_loop; + default: + LOG(log_error, logtype_afpd, "afp_read(%s): ad_readfile: %s", of_name(ofork), strerror(errno)); + goto afp_read_exit; + } } - } - - dsi_readdone(dsi); - goto afp_read_done; + dsi_readdone(dsi); + goto afp_read_done; + } afp_read_loop: #endif @@ -1065,7 +1080,7 @@ int flushfork(struct ofork *ofork) return( err ); } -int afp_closefork(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *rbuf _U_, size_t *rbuflen) +int afp_closefork(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf _U_, size_t *rbuflen) { struct ofork *ofork; uint16_t ofrefnum; @@ -1082,7 +1097,7 @@ int afp_closefork(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *rbuf _U LOG(log_debug, logtype_afpd, "afp_closefork(fork: %s)", (ofork->of_flags & AFPFORK_DATA) ? "d" : "r"); - if ( of_closefork( ofork ) < 0 ) { + if (of_closefork(obj, ofork) < 0 ) { LOG(log_error, logtype_afpd, "afp_closefork(%s): of_closefork: %s", of_name(ofork), strerror(errno) ); return( AFPERR_PARAM ); } @@ -1214,29 +1229,27 @@ static int write_fork(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf, s offset += cc; #if 0 /*def HAVE_SENDFILE_WRITE*/ - if (!(obj->options.flags & OPTION_DEBUG)) { - if ((cc = ad_writefile(ofork->of_ad, eid, dsi->socket, - offset, dsi->datasize)) < 0) { - switch (errno) { - case EDQUOT : - case EFBIG : - case ENOSPC : - cc = AFPERR_DFULL; - break; - default : - LOG(log_error, logtype_afpd, "afp_write: ad_writefile: %s", strerror(errno) ); - goto afp_write_loop; - } - dsi_writeflush(dsi); - *rbuflen = 0; - ad_tmplock(ofork->of_ad, eid, ADLOCK_CLR, saveoff, - reqcount, ofork->of_refnum); - return cc; + if ((cc = ad_writefile(ofork->of_ad, eid, dsi->socket, + offset, dsi->datasize)) < 0) { + switch (errno) { + case EDQUOT: + case EFBIG: + case ENOSPC: + cc = AFPERR_DFULL; + break; + default: + LOG(log_error, logtype_afpd, "afp_write: ad_writefile: %s", strerror(errno) ); + goto afp_write_loop; } - - offset += cc; - goto afp_write_done; + dsi_writeflush(dsi); + *rbuflen = 0; + ad_tmplock(ofork->of_ad, eid, ADLOCK_CLR, saveoff, + reqcount, ofork->of_refnum); + return cc; } + + offset += cc; + goto afp_write_done; #endif /* 0, was HAVE_SENDFILE_WRITE */ /* loop until everything gets written. currently