]> arthur.barton.de Git - netatalk.git/commitdiff
Solaris share reservation cross platform locking
authorFrank Lahm <franklahm@googlemail.com>
Thu, 19 Apr 2012 05:17:21 +0000 (07:17 +0200)
committerFrank Lahm <franklahm@googlemail.com>
Thu, 19 Apr 2012 05:17:21 +0000 (07:17 +0200)
NEWS
configure.ac
etc/afpd/file.c
etc/afpd/fork.c

diff --git a/NEWS b/NEWS
index 2091ebdb866de6017cf83832a1a5454378221a1a..50eaf5e542454457729dc7b7bd4b10ded820b96d 100644 (file)
--- 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: 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
 * 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
index 484a0dedf8f72eec16f52a88100b55b3cc9c4fb4..76cf8cbe6cba9b10983b056b13051ab3facb7d85 100644 (file)
@@ -50,6 +50,7 @@ AC_CHECK_HEADERS([sys/mount.h], , ,
 #include <sys/param.h>
 #endif
 ])
 #include <sys/param.h>
 #endif
 ])
+AC_CHECK_TYPES([fshare_t], [], [], [[#include <fcntl.h>]])
 
 AC_SYS_LARGEFILE([], AC_MSG_ERROR([AFP 3.x support requires Large File Support.]))
 
 
 AC_SYS_LARGEFILE([], AC_MSG_ERROR([AFP 3.x support requires Large File Support.]))
 
index 7bc98e9a97233e6ea1d92a233140e072f4f7b43f..3c3d15e8cddd95e70b840ef420f051864a107bcd 100644 (file)
@@ -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;
     }
     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 );
 
     denyreadset = (ad_testlock(adp, ADEID_DFORK, AD_FILELOCK_DENY_RD) != 0 || 
                   ad_testlock(adp, ADEID_RFORK, AD_FILELOCK_DENY_RD) != 0 );
 
index 2216a45c1b32a0d40be5b89698a9a95bc8553ffc..2424a5e4e22823aaaa30bf3f1062de18901d82b8 100644 (file)
@@ -152,6 +152,25 @@ static int fork_setmode(struct adouble *adp, int eid, int access, int ofrefnum)
     int denyreadset;
     int denywriteset;
 
     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);
     }
     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");
 
     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 );
     if ( of_closefork( ofork ) < 0 ) {
         LOG(log_error, logtype_afpd, "afp_closefork(%s): of_closefork: %s", of_name(ofork), strerror(errno) );
         return( AFPERR_PARAM );