]> arthur.barton.de Git - netatalk.git/commitdiff
Merge branch 'develop' of netafp.com:git/netatalk into develop
authorFrank Lahm <franklahm@googlemail.com>
Thu, 19 Apr 2012 13:06:05 +0000 (15:06 +0200)
committerFrank Lahm <franklahm@googlemail.com>
Thu, 19 Apr 2012 13:06:05 +0000 (15:06 +0200)
13 files changed:
NEWS
configure.ac
etc/afpd/afp_dsi.c
etc/afpd/auth.c
etc/afpd/file.c
etc/afpd/fork.c
etc/afpd/fork.h
etc/afpd/ofork.c
etc/afpd/volume.c
etc/afpd/volume.h
include/atalk/globals.h
include/atalk/netatalk_conf.h
libatalk/util/netatalk_conf.c

diff --git a/NEWS b/NEWS
index 2091ebdb866de6017cf83832a1a5454378221a1a..fec9ef872566143f8aa0bd5f6e1370dba0bba278 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -2,6 +2,10 @@ 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. Enabled by default, set global
+       "solaris share reservations" option to false to disable it.
 * 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
 ])
+AC_CHECK_TYPES([fshare_t], [], [], [[#include <fcntl.h>]])
 
 AC_SYS_LARGEFILE([], AC_MSG_ERROR([AFP 3.x support requires Large File Support.]))
 
index fdd0418915f91a2b19abb80a441794f50bc567ed..f1e371676eac9d1213dbc7b667e6cc8c35cd9a9c 100644 (file)
@@ -92,7 +92,7 @@ static void afp_dsi_close(AFPObj *obj)
         }
     }
 
-    close_all_vol();
+    close_all_vol(obj);
     if (obj->logout)
         (*obj->logout)();
 
index e8fc49eb0a957180e41a8ded07c9694641299df9..6c81b5e482301c9e4197642e6aec179bbde3e443 100644 (file)
@@ -854,8 +854,8 @@ int afp_logout(AFPObj *obj, char *ibuf _U_, size_t ibuflen  _U_, char *rbuf  _U_
     DSI *dsi = (DSI *)(obj->dsi);
 
     LOG(log_note, logtype_afpd, "AFP logout by %s", obj->username);
-    of_close_all_forks();
-    close_all_vol();
+    of_close_all_forks(obj);
+    close_all_vol(obj);
     dsi->flags = DSI_AFP_LOGGED_OUT;
     *rbuflen = 0;
     return AFP_OK;
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;
     }
+#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 );
 
index 2216a45c1b32a0d40be5b89698a9a95bc8553ffc..96ac39363ad09930ca6b19255f69cda8e7ace4b8 100644 (file)
@@ -144,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;
@@ -152,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);
     }
@@ -436,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(ofork);
             ofrefnum = 0;
             memcpy(rbuf, &ofrefnum, sizeof(ofrefnum));
             return(AFPERR_OLOCK);
@@ -451,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(ofork);
             switch (ret) {
             case EAGAIN: /* return data anyway */
             case EACCES:
@@ -483,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(ofork);
     if (errno == EACCES)
         return (access & OPENACC_WR) ? AFPERR_LOCK : AFPERR_ACCESS;
     return ret;
@@ -1059,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;
@@ -1076,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 );
     }
index f586118067919322d084329ee7400e0e4dd72eb6..d7120e4778b163927bd17b31c2f5ffd4872aa3a9 100644 (file)
@@ -67,9 +67,9 @@ extern int          of_rename    (const struct vol *,
 extern int          of_flush     (const struct vol *);
 extern int          of_stat      (struct path *);
 extern int          of_statdir   (struct vol *vol, struct path *);
-extern int          of_closefork (struct ofork *ofork);
-extern void         of_closevol  (const struct vol *vol);
-extern void         of_close_all_forks(void);
+extern int          of_closefork (const AFPObj *obj, struct ofork *ofork);
+extern void         of_closevol  (const AFPObj *obj, const struct vol *vol);
+extern void         of_close_all_forks(const AFPObj *obj);
 extern struct adouble *of_ad     (const struct vol *, struct path *, struct adouble *);
 
 #ifdef HAVE_ATFUNCS
index fc91c03b18fa51f44f48be121d1672a2e6f5ab84..3d690079ba84f7136575afa593e79ad2a3c6425a 100644 (file)
@@ -364,7 +364,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,15 +378,13 @@ 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;
@@ -412,12 +410,26 @@ int of_closefork(struct ofork *ofork)
         fce_register_file_modification(ofork);
     }
 
+    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;
     if ( ad_close( ofork->of_ad, adflags | ADFLAGS_SETSHRMD) < 0 ) {
         ret = -1;
     }
 
-    of_dealloc( ofork );
+    of_dealloc(ofork);
+
     return ret;
 }
 
@@ -441,7 +453,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 +462,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 +473,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 +482,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) );
             }
         }
index 23dfc7d7cbe6aeb7b03c1cb74275c7569014bd8a..3b02b2390a467dd81de3319fa757ceb709434844 100644 (file)
@@ -872,7 +872,7 @@ int afp_openvol(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf, size_t
             }
         }
 
-        char *msg;
+        const char *msg;
         if ((msg = iniparser_getstring(obj->iniconfig, volume->v_configname, "login message",  NULL)) != NULL)
             setmessage(msg);
 
@@ -894,14 +894,14 @@ openvol_err:
     return ret;
 }
 
-void closevol(struct vol *vol)
+void closevol(const AFPObj *obj, struct vol *vol)
 {
     if (!vol)
         return;
 
     vol->v_flags &= ~AFPVOL_OPEN;
 
-    of_closevol(vol);
+    of_closevol(obj, vol);
 
     dir_free( vol->v_root );
     vol->v_root = NULL;
@@ -919,20 +919,20 @@ void closevol(struct vol *vol)
 }
 
 /* ------------------------- */
-void close_all_vol(void)
+void close_all_vol(const AFPObj *obj)
 {
     struct vol  *ovol;
     curdir = NULL;
     for ( ovol = getvolumes(); ovol; ovol = ovol->v_next ) {
         if ( (ovol->v_flags & AFPVOL_OPEN) ) {
             ovol->v_flags &= ~AFPVOL_OPEN;
-            closevol(ovol);
+            closevol(obj, ovol);
         }
     }
 }
 
 /* ------------------------- */
-int afp_closevol(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *rbuf _U_, size_t *rbuflen)
+int afp_closevol(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf _U_, size_t *rbuflen)
 {
     struct vol  *vol;
     uint16_t   vid;
@@ -946,7 +946,7 @@ int afp_closevol(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *rbuf _U_
 
     (void)chdir("/");
     curdir = NULL;
-    closevol(vol);
+    closevol(obj, vol);
 
     return( AFP_OK );
 }
index b1c750a5727375c7a9e8fa8e2a478fef2ba0b081..3bca88214bfee50687bc7dc052d5e70a9bb8c948 100644 (file)
@@ -29,6 +29,6 @@ int afp_getsrvrparms (AFPObj *obj, char *ibuf, size_t ibuflen, char *rbuf,  size
 int afp_closevol     (AFPObj *obj, char *ibuf, size_t ibuflen, char *rbuf,  size_t *rbuflen);
 
 /* netatalk functions */
-extern void close_all_vol(void);
-extern void closevol(struct vol *vol);
+extern void close_all_vol(const AFPObj *obj);
+extern void closevol(const AFPObj *obj, struct vol *vol);
 #endif
index e34f4ee829e33ccef3842880511c89abfb08a863..e25efdbd12fd585cb66e3de7e38f6e6e47e194f1 100644 (file)
@@ -44,6 +44,7 @@
 #define OPTION_ACL2MACCESS   (1 << 8)
 #define OPTION_NOZEROCONF    (1 << 9)
 #define OPTION_KEEPSESSIONS  (1 << 10) /* preserve sessions across master afpd restart with SIGQUIT */
+#define OPTION_SHARE_RESERV  (1 << 11) /* whether to use Solaris fcntl F_SHARE locks */
 
 #define PASSWD_NONE     0
 #define PASSWD_SET     (1 << 0)
index a9ece1a1c6fafeea75011e6f3a526c26da5b66b5..22ecab790055392350697460373299f46ebadb2b 100644 (file)
@@ -23,7 +23,7 @@
 extern int        afp_config_parse(AFPObj *obj, char *processname);
 
 extern int        load_charset(struct vol *vol);
-extern int        load_volumes(AFPObj *obj, void (*delvol_fn)(struct vol *));
+extern int        load_volumes(AFPObj *obj, void (*delvol_fn)(const AFPObj *obj, struct vol *));
 extern void       unload_volumes(AFPObj *obj);
 extern struct vol *getvolumes(void);
 extern struct vol *getvolbyvid(const uint16_t);
index e58f9a5fe5e47b927876222d74d1cdbeec05e7fd..c61ebe6f3071e435baa3b3d494743f5808155d7b 100644 (file)
@@ -1124,7 +1124,7 @@ int load_charset(struct vol *vol)
  * @param obj       (r) handle
  * @param delvol_fn (r) callback called for deleted volumes
  */
-int load_volumes(AFPObj *obj, void (*delvol_fn)(struct vol *))
+int load_volumes(AFPObj *obj, void (*delvol_fn)(const AFPObj *obj, struct vol *))
 {
     EC_INIT;
     int fd = -1;
@@ -1180,7 +1180,7 @@ int load_volumes(AFPObj *obj, void (*delvol_fn)(struct vol *))
         if (vol->v_deleted) {
             LOG(log_debug, logtype_afpd, "load_volumes: deleted: %s", vol->v_localname);
             if (delvol_fn)
-                delvol_fn(vol);
+                delvol_fn(obj, vol);
             vol = Volumes;
         }
     }
@@ -1440,6 +1440,8 @@ int afp_config_parse(AFPObj *AFPObj, char *processname)
         options->flags |= OPTION_SERVERNOTIF;
     if (!iniparser_getboolean(config, INISEC_GLOBAL, "use sendfile", 1))
         options->flags |= OPTION_NOSENDFILE;
+    if (iniparser_getboolean(config, INISEC_GLOBAL, "solaris share reservations", 1))
+        options->flags |= OPTION_SHARE_RESERV;
     if (!iniparser_getboolean(config, INISEC_GLOBAL, "save password", 1))
         options->passwdbits |= PASSWD_NOSAVE;
     if (iniparser_getboolean(config, INISEC_GLOBAL, "set password", 0))