]> arthur.barton.de Git - netatalk.git/commitdiff
New global option "solaris share reservations"
authorFrank Lahm <franklahm@googlemail.com>
Thu, 19 Apr 2012 10:41:30 +0000 (12:41 +0200)
committerFrank Lahm <franklahm@googlemail.com>
Thu, 19 Apr 2012 10:41:30 +0000 (12:41 +0200)
NEWS
etc/afpd/afp_dsi.c
etc/afpd/auth.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 50eaf5e542454457729dc7b7bd4b10ded820b96d..fec9ef872566143f8aa0bd5f6e1370dba0bba278 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -4,7 +4,8 @@ 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.
+       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 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 2424a5e4e22823aaaa30bf3f1062de18901d82b8..c7025a8f479fe8b5399b68a8c9201ca4d3dd1316 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;
@@ -155,22 +155,24 @@ static int fork_setmode(struct adouble *adp, int eid, int access, int ofrefnum)
 #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;
+    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);
+        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;
+        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);
     }
@@ -455,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);
@@ -470,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:
@@ -502,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;
@@ -1078,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;
@@ -1095,16 +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");
 
-#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 ) {
+    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..ed0be2c6a76ec8f7f5cf8aba3c49e46e22334cfd 100644 (file)
@@ -57,7 +57,7 @@ extern struct ofork *of_alloc    (struct vol *, struct dir *,
                                                       char *, uint16_t *, const int,
                                                       struct adouble *,
                                                       struct stat *);
-extern void         of_dealloc   (struct ofork *);
+extern void         of_dealloc   (const AFPObj *obj, struct ofork *);
 extern struct ofork *of_find     (const uint16_t);
 extern struct ofork *of_findname (struct path *);
 extern int          of_rename    (const struct vol *,
@@ -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..10cdfc232b153d4022ecae125e94ea1bc2da3205 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(const AFPObj *obj,  struct ofork *of)
 {
     if (!oforks)
         return;
@@ -380,13 +380,23 @@ void of_dealloc( struct ofork *of)
         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);
+#ifdef HAVE_FSHARE_T
+        if (obj->options.flags & OPTION_SHARE_RESERV) {
+            fshare_t shmd;
+            shmd.f_id = of->of_refnum;
+            if (AD_DATA_OPEN(of->of_ad))
+                fcntl(ad_data_fileno(of->of_ad), F_UNSHARE, &shmd);
+            if (AD_RSRC_OPEN(of->of_ad))
+                fcntl(ad_reso_fileno(of->of_ad), F_UNSHARE, &shmd);
+        }
+#endif
     }
 
     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 +422,13 @@ int of_closefork(struct ofork *ofork)
         fce_register_file_modification(ofork);
     }
 
+    of_dealloc(obj, ofork);
+
     ret = 0;
     if ( ad_close( ofork->of_ad, adflags | ADFLAGS_SETSHRMD) < 0 ) {
         ret = -1;
     }
 
-    of_dealloc( ofork );
     return ret;
 }
 
@@ -441,7 +452,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 +461,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 +472,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 +481,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 f7909e8d1b830cde2c23bb13c0f6b11726bc3e9e..787c8d2d8149ae89412daf1abf86368cbfe07857 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))