From: Frank Lahm Date: Thu, 19 Apr 2012 05:17:21 +0000 (+0200) Subject: Solaris share reservation cross platform locking X-Git-Url: https://arthur.barton.de/cgi-bin/gitweb.cgi?p=netatalk.git;a=commitdiff_plain;h=835046ffee549c23b8500f06b7eb63b62ad13f94 Solaris share reservation cross platform locking --- diff --git a/NEWS b/NEWS index 2091ebdb..50eaf5e5 100644 --- a/NEWS +++ b/NEWS @@ -2,6 +2,9 @@ Changes in 3.0 alpha3 ===================== * NEW: afpd: Per volume "login message", NetAFP bug ID #18 +* NEW: afpd: Cross-platform locking (share modes) on Solaris and derivates + with Solaris CIFS/SMB server. Uses new Solaris fcntl F_SHARE share + reservation locking primitives. * NEW: ad: ad set subcommand for changing Mac metadata on the server * UPD: unix charset is UTF8 by default vol charset is same value as unix charset by default diff --git a/configure.ac b/configure.ac index 484a0ded..76cf8cbe 100644 --- a/configure.ac +++ b/configure.ac @@ -50,6 +50,7 @@ AC_CHECK_HEADERS([sys/mount.h], , , #include #endif ]) +AC_CHECK_TYPES([fshare_t], [], [], [[#include ]]) AC_SYS_LARGEFILE([], AC_MSG_ERROR([AFP 3.x support requires Large File Support.])) diff --git a/etc/afpd/file.c b/etc/afpd/file.c index 7bc98e9a..3c3d15e8 100644 --- a/etc/afpd/file.c +++ b/etc/afpd/file.c @@ -1258,6 +1258,19 @@ int afp_copyfile(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf _U_, si if (ad_open(adp, s_path->u_name, ADFLAGS_DF | ADFLAGS_HF | ADFLAGS_NOHF | ADFLAGS_RDONLY | ADFLAGS_SETSHRMD) < 0) { return AFPERR_DENYCONF; } +#ifdef HAVE_FSHARE_T + fshare_t shmd; + shmd.f_access = F_RDACC; + shmd.f_deny = F_NODNY; + if (fcntl(ad_data_fileno(adp), F_SHARE, &shmd) != 0) { + retvalue = AFPERR_DENYCONF; + goto copy_exit; + } + if (AD_RSRC_OPEN(adp) && fcntl(ad_reso_fileno(adp), F_SHARE, &shmd) != 0) { + retvalue = AFPERR_DENYCONF; + goto copy_exit; + } +#endif denyreadset = (ad_testlock(adp, ADEID_DFORK, AD_FILELOCK_DENY_RD) != 0 || ad_testlock(adp, ADEID_RFORK, AD_FILELOCK_DENY_RD) != 0 ); diff --git a/etc/afpd/fork.c b/etc/afpd/fork.c index 2216a45c..2424a5e4 100644 --- a/etc/afpd/fork.c +++ b/etc/afpd/fork.c @@ -152,6 +152,25 @@ static int fork_setmode(struct adouble *adp, int eid, int access, int ofrefnum) int denyreadset; int denywriteset; +#ifdef HAVE_FSHARE_T + fshare_t shmd; + + 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); } @@ -1076,6 +1095,15 @@ 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"); +#ifdef HAVE_FSHARE_T + 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 + if ( of_closefork( ofork ) < 0 ) { LOG(log_error, logtype_afpd, "afp_closefork(%s): of_closefork: %s", of_name(ofork), strerror(errno) ); return( AFPERR_PARAM );