Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package seadrive-fuse for openSUSE:Factory 
checked in at 2026-08-04 23:28:30
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/seadrive-fuse (Old)
 and      /work/SRC/openSUSE:Factory/.seadrive-fuse.new.16738 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "seadrive-fuse"

Tue Aug  4 23:28:30 2026 rev:12 rq:1369443 version:3.0.24

Changes:
--------
--- /work/SRC/openSUSE:Factory/seadrive-fuse/seadrive-fuse.changes      
2026-06-08 14:28:24.384739166 +0200
+++ /work/SRC/openSUSE:Factory/.seadrive-fuse.new.16738/seadrive-fuse.changes   
2026-08-04 23:28:33.782097302 +0200
@@ -1,0 +2,12 @@
+Tue Aug  4 08:32:21 UTC 2026 - Paolo Stivanin <[email protected]>
+
+- update to 3.0.24:
+  * Skip lock file when flock is not implemented (#40)
+  * fuse-ops.c: populate st_blocks (#41)
+  * Use queue to update mount path xattr (#38)
+  * Set proxy to websockets (#42)
+  * Fix set ca path error (#43)
+- add lws-socks5.patch: only use the lws SOCKS5 proxy fields when
+  libwebsockets is built with LWS_WITH_SOCKS5.
+
+-------------------------------------------------------------------

Old:
----
  seadrive-fuse-3.0.23.tar.gz

New:
----
  lws-socks5.patch
  seadrive-fuse-3.0.24.tar.gz

----------(New B)----------
  New:  * Fix set ca path error (#43)
- add lws-socks5.patch: only use the lws SOCKS5 proxy fields when
  libwebsockets is built with LWS_WITH_SOCKS5.
----------(New E)----------

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ seadrive-fuse.spec ++++++
--- /var/tmp/diff_new_pack.uqSrkn/_old  2026-08-04 23:28:34.746131391 +0200
+++ /var/tmp/diff_new_pack.uqSrkn/_new  2026-08-04 23:28:34.746131391 +0200
@@ -17,13 +17,14 @@
 
 
 Name:           seadrive-fuse
-Version:        3.0.23
+Version:        3.0.24
 Release:        0
 Summary:        SeaDrive daemon with FUSE interface
 License:        GPL-2.0-only
 URL:            https://github.com/haiwen/seadrive-fuse/
 Source0:        
https://github.com/haiwen/seadrive-fuse/archive/v%{version}.tar.gz#/%{name}-%{version}.tar.gz
 Patch0:         fuse3.patch
+Patch1:         lws-socks5.patch
 BuildRequires:  argon2-devel
 BuildRequires:  autoconf
 BuildRequires:  automake

++++++ fuse3.patch ++++++
--- /var/tmp/diff_new_pack.uqSrkn/_old  2026-08-04 23:28:34.778132523 +0200
+++ /var/tmp/diff_new_pack.uqSrkn/_new  2026-08-04 23:28:34.782132665 +0200
@@ -4,10 +4,10 @@
 
     Port to fuse3
 
-Index: seadrive-fuse-3.0.21/README.md
+Index: seadrive-fuse-3.0.24/README.md
 ===================================================================
---- seadrive-fuse-3.0.21.orig/README.md
-+++ seadrive-fuse-3.0.21/README.md
+--- seadrive-fuse-3.0.24.orig/README.md
++++ seadrive-fuse-3.0.24/README.md
 @@ -4,7 +4,7 @@ SeaDrive daemon with FUSE interface
  # Building
  ## Ubuntu Linux
@@ -17,10 +17,10 @@
  ```
  
  First, you shoud get the latest source of 
[libsearpc](https://github.com/haiwen/libsearpc) with `v3.2-latest` tag and 
[seadrive-fuse](https://github.com/haiwen/seadrive-fuse).
-Index: seadrive-fuse-3.0.21/configure.ac
+Index: seadrive-fuse-3.0.24/configure.ac
 ===================================================================
---- seadrive-fuse-3.0.21.orig/configure.ac
-+++ seadrive-fuse-3.0.21/configure.ac
+--- seadrive-fuse-3.0.24.orig/configure.ac
++++ seadrive-fuse-3.0.24/configure.ac
 @@ -154,7 +154,7 @@ GLIB_REQUIRED=2.16.0
  SEARPC_REQUIRED=1.0
  JANSSON_REQUIRED=2.2.1
@@ -39,10 +39,10 @@
     AC_SUBST(FUSE_CFLAGS)
     AC_SUBST(FUSE_LIBS)
  fi
-Index: seadrive-fuse-3.0.21/src/fuse-ops.c
+Index: seadrive-fuse-3.0.24/src/fuse-ops.c
 ===================================================================
---- seadrive-fuse-3.0.21.orig/src/fuse-ops.c
-+++ seadrive-fuse-3.0.21/src/fuse-ops.c
+--- seadrive-fuse-3.0.24.orig/src/fuse-ops.c
++++ seadrive-fuse-3.0.24/src/fuse-ops.c
 @@ -2,8 +2,8 @@
  
  #if defined __linux__ || defined __APPLE__
@@ -74,7 +74,7 @@
      FusePathComps comps;
      int ret = 0;
      uid_t uid;
-@@ -441,7 +442,7 @@ readdir_root_accounts (void *buf, fuse_f
+@@ -446,7 +447,7 @@ readdir_root_accounts (void *buf, fuse_f
      }
      for (ptr = accounts; ptr; ptr = ptr->next) {
          account = ptr->data;
@@ -83,7 +83,7 @@
      }
      g_list_free_full (accounts, (GDestroyNotify)seaf_account_free);
  
-@@ -462,10 +463,10 @@ readdir_root (AccountInfo *account, void
+@@ -467,10 +468,10 @@ readdir_root (AccountInfo *account, void
          type_str = ptr->data;
  #ifdef __APPLE__
          dname_nfd = g_utf8_normalize (type_str, -1, G_NORMALIZE_NFD);
@@ -96,7 +96,7 @@
  #endif
      }
  
-@@ -501,10 +502,10 @@ readdir_category (AccountInfo *account,
+@@ -506,10 +507,10 @@ readdir_category (AccountInfo *account,
          dname = g_path_get_basename (info->display_name);
  #ifdef __APPLE__
          dname_nfd = g_utf8_normalize (dname, -1, G_NORMALIZE_NFD);
@@ -109,7 +109,7 @@
  #endif
  
          g_free (dname);
-@@ -553,7 +554,7 @@ readdir_repo (const char *repo_id, const
+@@ -558,7 +559,7 @@ readdir_repo (const char *repo_id, const
          if (seaf_repo_manager_is_path_invisible (seaf->repo_mgr, repo_id, 
dname)) {
              continue;
          }
@@ -118,7 +118,7 @@
      }
      g_hash_table_destroy (dirents);
  
-@@ -565,8 +566,10 @@ out:
+@@ -570,8 +571,10 @@ out:
  int
  seadrive_fuse_readdir(const char *path, void *buf,
                        fuse_fill_dir_t filler, off_t offset,
@@ -130,7 +130,7 @@
      FusePathComps comps;
      int ret = 0;
  
-@@ -575,8 +578,8 @@ seadrive_fuse_readdir(const char *path,
+@@ -580,8 +583,8 @@ seadrive_fuse_readdir(const char *path,
      if (!seaf->started)
          return 0;
  
@@ -141,7 +141,7 @@
  
      memset (&comps, 0, sizeof(comps));
  
-@@ -1228,8 +1231,11 @@ out:
+@@ -1233,8 +1236,11 @@ out:
      return ret;
  }
  
@@ -154,7 +154,7 @@
      FusePathComps comps1, comps2;
      int ret = 0;
  
-@@ -1559,8 +1565,9 @@ int seadrive_fuse_release (const char *p
+@@ -1564,8 +1570,9 @@ int seadrive_fuse_release (const char *p
  }
  
  int
@@ -165,7 +165,7 @@
      FusePathComps comps;
      char *repo_id, *file_path;
      FileCacheStat st;
-@@ -1700,8 +1707,9 @@ seadrive_fuse_statfs (const char *path,
+@@ -1705,8 +1712,9 @@ seadrive_fuse_statfs (const char *path,
  }
  
  int
@@ -176,7 +176,7 @@
      RepoTreeStat tree_st;
      char *repo_id = NULL, *file_path = NULL;
      SeafRepo *repo = NULL;
-@@ -1766,8 +1774,9 @@ out:
+@@ -1776,8 +1784,9 @@ out:
  }
  
  int
@@ -187,10 +187,10 @@
      RepoTreeStat tree_st;
      char *repo_id = NULL, *file_path = NULL;
      SeafRepo *repo = NULL;
-Index: seadrive-fuse-3.0.21/src/fuse-ops.h
+Index: seadrive-fuse-3.0.24/src/fuse-ops.h
 ===================================================================
---- seadrive-fuse-3.0.21.orig/src/fuse-ops.h
-+++ seadrive-fuse-3.0.21/src/fuse-ops.h
+--- seadrive-fuse-3.0.24.orig/src/fuse-ops.h
++++ seadrive-fuse-3.0.24/src/fuse-ops.h
 @@ -3,13 +3,17 @@
  
  #if defined __linux__ || defined __APPLE__
@@ -238,10 +238,10 @@
  
  int seadrive_fuse_symlink (const char *from, const char *to);
  
-Index: seadrive-fuse-3.0.21/src/seadrive.c
+Index: seadrive-fuse-3.0.24/src/seadrive.c
 ===================================================================
---- seadrive-fuse-3.0.21.orig/src/seadrive.c
-+++ seadrive-fuse-3.0.21/src/seadrive.c
+--- seadrive-fuse-3.0.24.orig/src/seadrive.c
++++ seadrive-fuse-3.0.24/src/seadrive.c
 @@ -41,9 +41,9 @@ static void print_version ()
  #include <fcntl.h>
  #include <sys/file.h>

++++++ lws-socks5.patch ++++++
Author: Paolo Stivanin <[email protected]>
Subject: Only use the lws SOCKS5 proxy fields when libwebsockets provides them

struct lws_context_creation_info only has the socks_proxy_address and
socks_proxy_port members when libwebsockets is built with LWS_WITH_SOCKS5.
openSUSE's libwebsockets is built without it, so compilation fails with:

    notif-mgr.c:901:22: error: 'struct lws_context_creation_info' has no
    member named 'socks_proxy_address'; did you mean 'ss_proxy_address'?

Guard the SOCKS branch with the macro (defined by the installed
lws_config.h, which libwebsockets.h includes) and warn at runtime instead.
The HTTP proxy branch is unaffected.

Index: seadrive-fuse-3.0.24/src/notif-mgr.c
===================================================================
--- seadrive-fuse-3.0.24.orig/src/notif-mgr.c
+++ seadrive-fuse-3.0.24/src/notif-mgr.c
@@ -896,12 +896,17 @@ lws_context_new (gboolean use_ssl)
             info.http_proxy_port = has_auth ? 0 :
                                    (seaf->http_proxy_port > 0 ? 
seaf->http_proxy_port : 80);
         } else if (g_strcmp0 (seaf->http_proxy_type, PROXY_TYPE_SOCKS) == 0) {
+#if defined(LWS_WITH_SOCKS5)
             if (seaf->http_proxy_port >= 0) {
                 socks_proxy_addr = has_auth ? build_proxy_address (1080) : 
g_strdup (seaf->http_proxy_addr);
                 info.socks_proxy_address = socks_proxy_addr;
                 info.socks_proxy_port = has_auth ? 0 :
                                     (seaf->http_proxy_port > 0 ? 
seaf->http_proxy_port : 1080);
             }
+#else
+            seaf_warning ("libwebsockets was built without SOCKS5 support, "
+                          "not using SOCKS proxy for notifications.\n");
+#endif
         }
     }


++++++ seadrive-fuse-3.0.23.tar.gz -> seadrive-fuse-3.0.24.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/seadrive-fuse-3.0.23/configure.ac 
new/seadrive-fuse-3.0.24/configure.ac
--- old/seadrive-fuse-3.0.23/configure.ac       2026-06-04 04:55:24.000000000 
+0200
+++ new/seadrive-fuse-3.0.24/configure.ac       2026-07-29 05:48:24.000000000 
+0200
@@ -2,7 +2,7 @@
 
 
 AC_PREREQ(2.61)
-AC_INIT([seadrive], [3.0.23], [[email protected]])
+AC_INIT([seadrive], [3.0.24], [[email protected]])
 AC_CONFIG_HEADER([config.h])
 
 AC_CONFIG_MACRO_DIR([m4])
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/seadrive-fuse-3.0.23/debian/changelog 
new/seadrive-fuse-3.0.24/debian/changelog
--- old/seadrive-fuse-3.0.23/debian/changelog   2026-06-04 04:55:24.000000000 
+0200
+++ new/seadrive-fuse-3.0.24/debian/changelog   2026-07-29 05:48:24.000000000 
+0200
@@ -1,3 +1,9 @@
+seadrive-daemon (3.0.24) unstable; urgency=low
+
+  * new upstream release
+
+ -- Jonathan Xu <[email protected]>  Wed, 29 Jul 2026 10:30:00 +0800
+
 seadrive-daemon (3.0.23) unstable; urgency=low
 
   * new upstream release
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/seadrive-fuse-3.0.23/src/fuse-ops.c 
new/seadrive-fuse-3.0.24/src/fuse-ops.c
--- old/seadrive-fuse-3.0.23/src/fuse-ops.c     2026-06-04 04:55:24.000000000 
+0200
+++ new/seadrive-fuse-3.0.24/src/fuse-ops.c     2026-07-29 05:48:24.000000000 
+0200
@@ -362,6 +362,7 @@
         stbuf->st_mode = S_IFDIR | 0755;
         stbuf->st_nlink = 2;
         stbuf->st_size = 4096;
+        stbuf->st_blocks = 8;
         stbuf->st_uid = uid;
         stbuf->st_gid = gid;
         if (comps.multi_account && comps.account_info)
@@ -372,6 +373,7 @@
         stbuf->st_mode = S_IFDIR | 0755;
         stbuf->st_nlink = 2;
         stbuf->st_size = 4096;
+        stbuf->st_blocks = 8;
         stbuf->st_uid = uid;
         stbuf->st_gid = gid;
         stbuf->st_mtime = get_category_dir_mtime (comps.account_info->server, 
comps.account_info->username, comps.repo_type);
@@ -380,6 +382,7 @@
         stbuf->st_mode = S_IFDIR | 0755;
         stbuf->st_nlink = 2;
         stbuf->st_size = 4096;
+        stbuf->st_blocks = 8;
         stbuf->st_mtime = comps.repo_info->mtime;
         stbuf->st_uid = uid;
         stbuf->st_gid = gid;
@@ -404,12 +407,14 @@
                                                                        
comps.repo_path));
         if (S_ISDIR(st.mode)) {
             stbuf->st_size = 4096;
+            stbuf->st_blocks = 8;
             if (is_writable)
                 stbuf->st_mode = S_IFDIR | 0755;
             else
                 stbuf->st_mode = S_IFDIR | 0555;
         } else {
             stbuf->st_size = st.size;
+            stbuf->st_blocks = (st.size + 511) / 512;
             if (is_writable)
                 stbuf->st_mode = S_IFREG | 0644;
             else
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/seadrive-fuse-3.0.23/src/http-tx-mgr.c 
new/seadrive-fuse-3.0.24/src/http-tx-mgr.c
--- old/seadrive-fuse-3.0.23/src/http-tx-mgr.c  2026-06-04 04:55:24.000000000 
+0200
+++ new/seadrive-fuse-3.0.24/src/http-tx-mgr.c  2026-07-29 05:48:24.000000000 
+0200
@@ -385,30 +385,14 @@
 
 #ifndef USE_GPL_CRYPTO
 
-char *ca_paths[] = {
-    "/etc/ssl/certs/ca-certificates.crt",
-    "/etc/ssl/certs/ca-bundle.crt",
-    "/etc/pki/tls/certs/ca-bundle.crt",
-    "/usr/share/ssl/certs/ca-bundle.crt",
-    "/usr/local/share/certs/ca-root-nss.crt",
-    "/etc/ssl/cert.pem",
-};
-
 static void
 load_ca_bundle(CURL *curl)
 {
     const char *env_ca_path = seaf->http_tx_mgr->priv->env_ca_bundle_path;
     int i;
     const char *ca_path;
-    gboolean found = FALSE;
 
-    for (i = 0; i < sizeof(ca_paths) / sizeof(ca_paths[0]); i++) {
-        ca_path = ca_paths[i];
-        if (seaf_util_exists (ca_path)) {
-            found = TRUE;
-            break;
-        }
-    }
+    ca_path = load_ca_bundle_path ();
 
     if (env_ca_path) {
         if (seaf_util_exists (env_ca_path)) {
@@ -417,7 +401,7 @@
         }
     }
 
-    if (found)
+    if (ca_path)
         curl_easy_setopt (curl, CURLOPT_CAINFO, ca_path);
 }
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/seadrive-fuse-3.0.23/src/notif-mgr.c 
new/seadrive-fuse-3.0.24/src/notif-mgr.c
--- old/seadrive-fuse-3.0.23/src/notif-mgr.c    2026-06-04 04:55:24.000000000 
+0200
+++ new/seadrive-fuse-3.0.24/src/notif-mgr.c    2026-07-29 05:48:24.000000000 
+0200
@@ -6,6 +6,7 @@
 #include <glib.h>
 
 #include "seafile-session.h"
+#include "seafile-config.h"
 #include "notif-mgr.h"
 #include "sync-mgr.h"
 
@@ -19,7 +20,6 @@
 #define STATUS_DISCONNECTED 0
 #define STATUS_CONNECTED    1
 #define STATUS_ERROR        2
-#define STATUS_CANCELLED    3
 
 typedef struct NotifServer {
     struct lws_context *context;
@@ -28,8 +28,7 @@
 
     // status of the notification server.
     int      status;
-    // whether to close the connection to the server.
-    gboolean close;
+    gboolean reconnect;
 
     GHashTable *subscriptions;
     pthread_mutex_t sub_lock;
@@ -47,6 +46,8 @@
 struct _SeafNotifManagerPriv {
     pthread_mutex_t server_lock;
     GHashTable *servers;
+
+    char *ca_bundle_path;
 };
 
 // The Message structure is used to send messages to the server.
@@ -97,6 +98,17 @@
     mgr->priv->servers = g_hash_table_new_full (g_str_hash, g_str_equal,
                                             g_free, NULL);
 
+    const char *ca_path = NULL;
+#ifndef USE_GPL_CRYPTO
+    ca_path = load_ca_bundle_path ();
+#endif
+    const char *env_ca_path = g_getenv("SEAFILE_SSL_CA_PATH");
+    if (env_ca_path && seaf_util_exists (env_ca_path)) {
+        mgr->priv->ca_bundle_path = g_strdup (env_ca_path);
+    } else if (ca_path) {
+        mgr->priv->ca_bundle_path = g_strdup (ca_path);
+    }
+
     return mgr;
 }
 
@@ -158,13 +170,62 @@
 notif_server_ref (NotifServer *server);
 
 static struct lws_context *
-lws_context_new (int port);
+lws_context_new (gboolean use_ssl);
+
+static void
+init_client_connect_info (NotifServer *server);
+
+static gboolean
+proxy_has_auth (void)
+{
+    return seaf->http_proxy_username && seaf->http_proxy_password &&
+           seaf->http_proxy_username[0] != '\0' &&
+           seaf->http_proxy_password[0] != '\0';
+}
+
+static char *
+build_proxy_address (int default_port)
+{
+    char *escaped_user = NULL;
+    char *escaped_pass = NULL;
+    char *proxy = NULL;
+    int port = seaf->http_proxy_port > 0 ? seaf->http_proxy_port : 
default_port;
+
+    escaped_user = g_uri_escape_string (seaf->http_proxy_username, NULL, 
FALSE);
+    escaped_pass = g_uri_escape_string (seaf->http_proxy_password, NULL, 
FALSE);
+    proxy = g_strdup_printf ("%s:%s@%s:%d",
+                             escaped_user,
+                             escaped_pass,
+                             seaf->http_proxy_addr,
+                             port);
+    g_free (escaped_user);
+    g_free (escaped_pass);
+
+    return proxy;
+}
+
+static int
+reset_lws_context (NotifServer *server)
+{
+    if (server->context) {
+        lws_context_destroy (server->context);
+        server->context = NULL;
+    }
+
+    server->wsi = NULL;
+
+    server->context = lws_context_new (server->use_ssl);
+    if (!server->context)
+        return -1;
+
+    init_client_connect_info (server);
+    return 0;
+}
 
 static NotifServer*
 notif_new_server (const char *server_url, gboolean use_notif_server_port)
 {
     NotifServer *server = NULL;
-    static struct lws_context *context;
     URI *uri = NULL;
     int port = NOTIF_PORT;
     gboolean use_ssl = FALSE;
@@ -186,20 +247,10 @@
     }
     
 
-    context = lws_context_new (use_ssl);
-    if (!context) {
-        g_free (uri->scheme);
-        g_free (uri->host);
-        g_free (uri);
-        seaf_warning ("failed to create libwebsockets context\n");
-        return NULL;
-    }
-
     server = g_new0 (NotifServer, 1);
 
     server->messages = g_async_queue_new ();
 
-    server->context = context;
     server->server_url = g_strdup (server_url);
     server->addr = g_strdup (uri->host);
     server->use_ssl = use_ssl;
@@ -225,6 +276,10 @@
 {
     NotifServer *server = NULL;
 
+    if (!url) {
+        return NULL;
+    }
+
     pthread_mutex_lock (&mgr->priv->server_lock);
     server = g_hash_table_lookup (mgr->priv->servers, url);
     if (!server) {
@@ -277,9 +332,6 @@
         notif_server_free (server);
 }
 
-static void
-init_client_connect_info (NotifServer *server);
-
 static void *
 notification_worker (void *vdata);
 
@@ -305,8 +357,6 @@
     if (!server)
         return;
 
-    init_client_connect_info (server);
-
     rc = pthread_create (&tid, NULL, notification_worker, server);
     if (rc != 0) {
         seaf_warning ("Failed to create event notification new thread: %s.\n", 
strerror(rc));
@@ -321,12 +371,30 @@
     return;
 }
 
-static void
-disconnect_server (NotifServer *server)
+void
+seaf_notif_manager_reconnect_servers (SeafNotifManager *mgr)
 {
-    // lws_cancel_service will produce a cancel event to break out of 
lws_service loop.
-    lws_cancel_service (server->context);
-    server->close = TRUE;
+    GHashTableIter iter;
+    gpointer key, value;
+
+    if (!mgr->priv)
+        return;
+
+    pthread_mutex_lock (&mgr->priv->server_lock);
+    g_hash_table_iter_init (&iter, mgr->priv->servers);
+    while (g_hash_table_iter_next (&iter, &key, &value)) {
+        NotifServer *server = value;
+
+        if (!server || !server->context)
+            continue;
+
+        server->reconnect = TRUE;
+
+        // Call lws_cancel_service() to wake up lws_service() and make it 
process events immediately.
+        if (server->context)
+            lws_cancel_service (server->context);
+    }
+    pthread_mutex_unlock (&mgr->priv->server_lock);
 }
 
 // This policy will send a ping packet to the server per second.
@@ -382,6 +450,7 @@
     switch (reason) {
     case LWS_CALLBACK_CLIENT_APPEND_HANDSHAKE_HEADER:
     {
+        // this callback happens when a client handshake is being compiled.
         unsigned char **p = (unsigned char **)in, *end = (*p) + len;
 
         if (lws_add_http_header_by_token(wsi, WSI_TOKEN_HTTP_USER_AGENT,
@@ -390,15 +459,24 @@
         break;
     }
     case LWS_CALLBACK_CLIENT_CONNECTION_ERROR:
+        // the request client connection has been unable to complete a 
handshake with the remote server.
         server->status = STATUS_ERROR;
         seaf_debug ("websocket connection error: %s\n",
             in ? (char *)in : "(null)");
         ret = -1;
         break;
     case LWS_CALLBACK_CLIENT_RECEIVE:
+        // data has appeared from the server for the client connection.
         handle_messages (in, len);
         break;
     case LWS_CALLBACK_CLIENT_WRITEABLE:
+        // If it already was able to take another packet without blocking,
+        // you'll get this callback at the next call to the service loop 
function.
+
+        // Return -1 to close the current connection and exit lws_service loop.
+        if (server->reconnect) {
+            return -1;
+        }
         msg = g_async_queue_try_pop (server->messages);
         if (!msg) {
             break;
@@ -417,22 +495,21 @@
         notif_message_free (msg);
         break;
     case LWS_CALLBACK_CLIENT_ESTABLISHED:
+        // after your client connection completed the websocket upgrade 
handshake with the remote server.
         seaf_sync_manager_check_locks_and_folder_perms (seaf->sync_mgr, 
server->server_url);
         server->status = STATUS_CONNECTED;
-        seaf_debug ("Successfully connected to the server: %s\n", 
server->server_url);
+        seaf_message ("Successfully connected to the server: %s\n", 
server->server_url);
         break;
     case LWS_CALLBACK_CLIENT_CLOSED:
+        // when a client websocket session ends.
         ret = -1;
         server->status = STATUS_ERROR;
+        server->wsi = NULL;
         // When the client is closed, cancel the context to prevent the socket 
from blocking in poll after the operating system wakes from sleep.
         // After calling lws_cancel_service, a 
LWS_CALLBACK_EVENT_WAIT_CANCELLED callback is sent to every protocol on every 
vhost,
-        // notification_worker will exit loop.
+        // lws_service() will return.
         lws_cancel_service (server->context);
         break;
-    case LWS_CALLBACK_EVENT_WAIT_CANCELLED:
-        ret = -1;
-        server->status = STATUS_CANCELLED;
-        break;
     default:
         break;
     }
@@ -797,6 +874,11 @@
 {
     struct lws_context_creation_info info;
     struct lws_context *context = NULL;
+    char *http_proxy_addr = NULL;
+    char *socks_proxy_addr = NULL;
+    gboolean has_auth = proxy_has_auth ();
+
+    SeafNotifManagerPriv *priv = seaf->notif_mgr->priv;
 
     memset(&info, 0, sizeof info);
     info.port = CONTEXT_PORT_NO_LISTEN;
@@ -806,20 +888,38 @@
     // have to use the default allocations for fd tables up to ulimit -n.
     // It will just allocate for 1 internal and 1 (+ 1 http2 nwsi) that we 
will use.
     info.fd_limit_per_thread = 1 + 1 + 1;
-    char *ca_path = g_build_filename (seaf->seaf_dir, "ca-bundle.pem", NULL);
+
+    if (seaf->use_http_proxy && seaf->http_proxy_type && 
seaf->http_proxy_addr) {
+        if (g_strcmp0 (seaf->http_proxy_type, PROXY_TYPE_HTTP) == 0) {
+            http_proxy_addr = has_auth ? build_proxy_address (80) : g_strdup 
(seaf->http_proxy_addr);
+            info.http_proxy_address = http_proxy_addr;
+            info.http_proxy_port = has_auth ? 0 :
+                                   (seaf->http_proxy_port > 0 ? 
seaf->http_proxy_port : 80);
+        } else if (g_strcmp0 (seaf->http_proxy_type, PROXY_TYPE_SOCKS) == 0) {
+            if (seaf->http_proxy_port >= 0) {
+                socks_proxy_addr = has_auth ? build_proxy_address (1080) : 
g_strdup (seaf->http_proxy_addr);
+                info.socks_proxy_address = socks_proxy_addr;
+                info.socks_proxy_port = has_auth ? 0 :
+                                    (seaf->http_proxy_port > 0 ? 
seaf->http_proxy_port : 1080);
+            }
+        }
+    }
+
     if (use_ssl) {
          info.options = LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT;
-         info.client_ssl_ca_filepath = ca_path;
+         info.client_ssl_ca_filepath = priv->ca_bundle_path;
     }
 
     context = lws_create_context(&info);
     if (!context) {
-        g_free (ca_path);
+        g_free (http_proxy_addr);
+        g_free (socks_proxy_addr);
         seaf_warning ("failed to create libwebsockets context\n");
         return NULL;
     }
 
-    g_free (ca_path);
+    g_free (http_proxy_addr);
+    g_free (socks_proxy_addr);
     return context;
 }
 
@@ -871,21 +971,31 @@
     struct lws_client_connect_info *i = &server->i;
     int n = 0;
 
-    while (!server->close) {
+    while (1) {
+        if (reset_lws_context (server) < 0) {
+            g_usleep (RECONNECT_INTERVAL * G_USEC_PER_SEC);
+            server->status = STATUS_DISCONNECTED;
+            continue;
+        }
+
         // We don't need to check the return value of this function, the 
connection will be processed in the event loop.
         lws_client_connect_via_info(i);
 
-        while (n >= 0 && !server->close &&
-               server->status != STATUS_ERROR &&
-               server->status != STATUS_CANCELLED) {
-            n = lws_service(server->context, 0);
+        while (n >= 0 && server->status != STATUS_ERROR) {
+            // Wait for events for up to 1000 ms, lws_service() will return 
when the timeout expires.
+            n = lws_service(server->context, 1000);
         }
 
         delete_subscribed_repos (server);
         delete_unsent_messages (server);
 
-        if (server->status == STATUS_CANCELLED)
-            break;
+        if (server->reconnect) {
+            server->reconnect = FALSE;
+            n = 0;
+            server->status = STATUS_DISCONNECTED;
+            seaf_message ("Reconnecting to the notification server: %s.\n", 
server->server_url);
+            continue;
+        }
 
         // Wait a minute to reconnect to the notification server.
         seaf_sleep (RECONNECT_INTERVAL);
@@ -893,12 +1003,6 @@
         server->status = STATUS_DISCONNECTED;
     }
 
-    seaf_message ("Notification worker for server %s exiting.\n", 
server->server_url);
-    pthread_mutex_lock (&seaf->notif_mgr->priv->server_lock);
-    g_hash_table_remove (seaf->notif_mgr->priv->servers, server->server_url);
-    pthread_mutex_unlock (&seaf->notif_mgr->priv->server_lock);
-    notif_server_unref (server);
-
     return 0;
 }
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/seadrive-fuse-3.0.23/src/notif-mgr.h 
new/seadrive-fuse-3.0.24/src/notif-mgr.h
--- old/seadrive-fuse-3.0.23/src/notif-mgr.h    2026-06-04 04:55:24.000000000 
+0200
+++ new/seadrive-fuse-3.0.24/src/notif-mgr.h    2026-07-29 05:48:24.000000000 
+0200
@@ -21,6 +21,9 @@
                                    gboolean use_notif_server_port);
 
 void
+seaf_notif_manager_reconnect_servers (SeafNotifManager *mgr);
+
+void
 seaf_notif_manager_subscribe_repo (SeafNotifManager *mgr, SeafRepo *repo);
 
 void
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/seadrive-fuse-3.0.23/src/seadrive.c 
new/seadrive-fuse-3.0.24/src/seadrive.c
--- old/seadrive-fuse-3.0.23/src/seadrive.c     2026-06-04 04:55:24.000000000 
+0200
+++ new/seadrive-fuse-3.0.24/src/seadrive.c     2026-07-29 05:48:24.000000000 
+0200
@@ -383,7 +383,7 @@
         return -1;
     }
 
-    if (flock (fd, LOCK_EX | LOCK_NB) < 0) {
+    if (flock (fd, LOCK_EX | LOCK_NB) < 0 && errno != ENOSYS) {
         seaf_warning ("Failed to lock pidfile %s: %s\n",
                       pidfile, strerror(errno));
         close (fd);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/seadrive-fuse-3.0.23/src/seafile-config.c 
new/seadrive-fuse-3.0.24/src/seafile-config.c
--- old/seadrive-fuse-3.0.23/src/seafile-config.c       2026-06-04 
04:55:24.000000000 +0200
+++ new/seadrive-fuse-3.0.24/src/seafile-config.c       2026-07-29 
05:48:24.000000000 +0200
@@ -148,8 +148,13 @@
     if (g_strcmp0(key, KEY_USE_PROXY) == 0) {
         if (g_strcmp0(value, "true") == 0)
             session->use_http_proxy = TRUE;
-        else
+        else {
             session->use_http_proxy = FALSE;
+            // Disabling proxy completes with KEY_USE_PROXY=false,
+            // so reconnect notification server here to drop the old proxied 
connection.
+            if (session->notif_mgr)
+                seaf_notif_manager_reconnect_servers (session->notif_mgr);
+        }
     }
 
     if (g_strcmp0(key, KEY_PROXY_TYPE) == 0) {
@@ -167,6 +172,10 @@
 
     if (g_strcmp0(key, KEY_PROXY_PASSWORD) == 0) {
         session->http_proxy_password = g_strdup(value);
+        // The RPC caller updates proxy settings key by key and writes 
KEY_PROXY_PASSWORD last when proxy is enabled,
+        // so reconnect notifications here to pick up the complete new proxy 
settings.
+        if (session->notif_mgr)
+            seaf_notif_manager_reconnect_servers (session->notif_mgr);
     }
 
     if (g_strcmp0 (key, KEY_ENABLE_AUTO_LOCK) == 0) {
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/seadrive-fuse-3.0.23/src/sync-mgr.c 
new/seadrive-fuse-3.0.24/src/sync-mgr.c
--- old/seadrive-fuse-3.0.23/src/sync-mgr.c     2026-06-04 04:55:24.000000000 
+0200
+++ new/seadrive-fuse-3.0.24/src/sync-mgr.c     2026-07-29 05:48:24.000000000 
+0200
@@ -184,6 +184,7 @@
     struct SeafTimer *update_sync_status_timer;
     GHashTable *active_paths;
     pthread_mutex_t paths_lock;
+    GAsyncQueue *update_path_xattr_queue;
 
     GAsyncQueue *lock_file_job_queue;
 
@@ -201,6 +202,14 @@
     GHashTable *del_confirmation_tasks;
 };
 
+struct _UpdatePathXattrTask {
+    char *mount_path;
+    char *key;
+    char *value;
+    gsize size;
+};
+typedef struct _UpdatePathXattrTask UpdatePathXattrTask;
+
 struct _ActivePathsInfo {
     struct SyncStatusTree *syncing_tree;
     struct SyncStatusTree *synced_tree;
@@ -1032,6 +1041,9 @@
 static void
 active_paths_info_free (ActivePathsInfo *info);
 
+static void *
+update_path_xattr_worker (void *data);
+
 SeafSyncManager*
 seaf_sync_manager_new (SeafileSession *seaf)
 {
@@ -1093,6 +1105,7 @@
     pthread_mutex_init (&mgr->priv->errors_lock, NULL);
 
     mgr->priv->cache_file_task_queue = g_async_queue_new ();
+    mgr->priv->update_path_xattr_queue = g_async_queue_new ();
 
     mgr->priv->auto_sync_enabled = TRUE;
 
@@ -1161,6 +1174,7 @@
 static void* check_space_usage_thread (void *data);
 static void* lock_file_worker (void *data);
 static void* cache_file_task_worker (void *data);
+static void* update_path_xattr_worker (void *data);
 
 int
 seaf_sync_manager_start (SeafSyncManager *mgr)
@@ -1198,6 +1212,11 @@
         seaf_warning ("Failed to create cache file task worker thread: %s.\n", 
strerror(rc));
     }
 
+    rc = pthread_create (&tid, &attr, update_path_xattr_worker, 
mgr->priv->update_path_xattr_queue);
+    if (rc != 0) {
+        seaf_warning ("Failed to create update path xattr worker thread: 
%s.\n", strerror(rc));
+    }
+
     return 0;
 }
 
@@ -4510,6 +4529,62 @@
 
 /* Path sync status. */
 
+static void
+update_path_xattr_task_free (UpdatePathXattrTask *task)
+{
+    if (!task)
+        return;
+
+    g_free (task->mount_path);
+    g_free (task->key);
+    g_free (task->value);
+    g_free (task);
+}
+
+// Update mount-path xattrs asynchronously to avoid blocking sync status 
updates.
+static void *
+update_path_xattr_worker (void *data)
+{
+    GAsyncQueue *queue = data;
+    UpdatePathXattrTask *task;
+
+    while (1) {
+        task = g_async_queue_pop (queue);
+        if (!task)
+            break;
+
+        seaf_setxattr (task->mount_path, task->key, task->value, task->size);
+        update_path_xattr_task_free (task);
+    }
+
+    return NULL;
+}
+
+// seadrive-fuse updates xattrs to notify Nautilus to refresh file sync status.
+// Such xattr updates are triggered during file download and file upload.
+// When downloading a file, the fuse read callback function will block waiting 
for the file from being cached.
+// The file fetch worker tries to update xattr for the file (via mount path) 
when it fetches a file, which in turn calls into seadrive-fuse.
+// Fuse dosesn't seem to allow concurrent operations on the same file path. So 
the fuse call to update xattr is in turn waiting for fuse read to finish,
+// which causes deadlock between the tow fuse calls.
+// Moving the xattr update fuse calls out of the file fetch worker code path 
will avoid the deadlock. So it's executed asynchronously.
+static void
+update_path_xattr (SeafSyncManager *mgr,
+                   char *mount_path,
+                   const char *key,
+                   const char *value,
+                   gsize size)
+{
+    UpdatePathXattrTask *task = NULL;
+
+    task = g_new0 (UpdatePathXattrTask, 1);
+    task->mount_path = g_strdup (mount_path);
+    task->key = g_strdup (key);
+    task->value = g_strdup (value);
+    task->size = size;
+
+    g_async_queue_push (mgr->priv->update_path_xattr_queue, task);
+}
+
 static ActivePathsInfo *
 active_paths_info_new (SeafRepo *repo)
 {
@@ -4579,9 +4654,9 @@
 
     if (mount_path) {
         if (status == SYNC_STATUS_SYNCING)
-            seaf_setxattr (mount_path, "user.seafile-status", "syncing", 8);
+            update_path_xattr (mgr, mount_path, "user.seafile-status", 
"syncing", 8);
         else
-            seaf_setxattr (mount_path, "user.seafile-status", "cached", 7);
+            update_path_xattr (mgr, mount_path, "user.seafile-status", 
"cached", 7);
     }
 
     seaf_repo_unref (repo);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/seadrive-fuse-3.0.23/src/utils.c 
new/seadrive-fuse-3.0.24/src/utils.c
--- old/seadrive-fuse-3.0.23/src/utils.c        2026-06-04 04:55:24.000000000 
+0200
+++ new/seadrive-fuse-3.0.24/src/utils.c        2026-07-29 05:48:24.000000000 
+0200
@@ -774,3 +774,28 @@
         return g_strndup (server_addr, sep - server_addr);
     }
 }
+
+char *ca_paths[] = {
+    "/etc/ssl/certs/ca-certificates.crt",
+    "/etc/ssl/certs/ca-bundle.crt",
+    "/etc/pki/tls/certs/ca-bundle.crt",
+    "/usr/share/ssl/certs/ca-bundle.crt",
+    "/usr/local/share/certs/ca-root-nss.crt",
+    "/etc/ssl/cert.pem",
+};
+
+const char *
+load_ca_bundle_path ()
+{
+    int i;
+    const char *ca_path = NULL;
+
+    for (i = 0; i < sizeof(ca_paths) / sizeof(ca_paths[0]); i++) {
+        ca_path = ca_paths[i];
+        if (seaf_util_exists (ca_path)) {
+            return ca_path;
+        }
+    }
+
+    return NULL;
+}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/seadrive-fuse-3.0.23/src/utils.h 
new/seadrive-fuse-3.0.24/src/utils.h
--- old/seadrive-fuse-3.0.23/src/utils.h        2026-06-04 04:55:24.000000000 
+0200
+++ new/seadrive-fuse-3.0.24/src/utils.h        2026-07-29 05:48:24.000000000 
+0200
@@ -264,4 +264,7 @@
 
 char *
 parse_fileserver_addr (const char *server_addr);
+
+const char *
+load_ca_bundle_path ();
 #endif

Reply via email to