talons

Fork of Claws Mail https://www.claws-mail
Log | Files | Refs | README | LICENSE

commit 5c606d419912680015c8c4ab1d78e895e32233fe
parent f5b8cdb85f2a18f55fe19fd195c009d0f0c73860
Author: Oliver Lowe <o@olowe.co>
Date:   Sat, 30 Aug 2025 16:26:21 +1000

Just use flock(2)

This project is very POSIX-y already so the workarounds don't actually
get us anywhere

Diffstat:
Mconfigure.ac | 2+-
Msrc/common/file-utils.c | 4----
Msrc/inc.c | 40+++++++++++++++++++---------------------
Msrc/main.c | 45++++++++-------------------------------------
Msrc/mbox.c | 177-------------------------------------------------------------------------------
Msrc/mbox.h | 16++--------------
6 files changed, 30 insertions(+), 254 deletions(-)

diff --git a/configure.ac b/configure.ac @@ -212,7 +212,7 @@ AC_CHECK_SIZEOF(unsigned long, 4) dnl Checks for library functions. AC_FUNC_ALLOCA -AC_CHECK_FUNCS(fchmod flock lockf strcasestr) +AC_CHECK_FUNCS(strcasestr) dnl ***************** dnl ** common code ** diff --git a/src/common/file-utils.c b/src/common/file-utils.c @@ -664,11 +664,7 @@ gint copy_dir(const gchar *src, const gchar *dst) gint change_file_mode_rw(FILE *fp, const gchar *file) { -#if HAVE_FCHMOD return fchmod(fileno(fp), S_IRUSR|S_IWUSR); -#else - return g_chmod(file, S_IRUSR|S_IWUSR); -#endif } FILE *my_tmpfile(void) diff --git a/src/inc.c b/src/inc.c @@ -23,6 +23,7 @@ #include "defs.h" +#include <fcntl.h> #include <glib.h> #include <glib/gi18n.h> #include <gtk/gtk.h> @@ -663,7 +664,6 @@ static gint inc_start(IncProgressDialog *inc_dialog) for (; inc_dialog->queue_list != NULL && !cancelled; inc_dialog->cur_row++) { session = inc_dialog->queue_list->data; pop3_session = POP3_SESSION(session->session); - GSList *filtered, *unfiltered; if (pop3_session->pass == NULL) { SET_PIXMAP_AND_TEXT(okpix, _("Cancelled")); @@ -754,9 +754,6 @@ static gint inc_start(IncProgressDialog *inc_dialog) /* process messages */ folder_item_update_freeze(); - if (unfiltered != NULL) - folder_item_move_msgs(inbox, unfiltered); - for(msglist_element = msglist; msglist_element != NULL; msglist_element = msglist_element->next) { procmsg_msginfo_free((MsgInfo**)&(msglist_element->data)); @@ -764,8 +761,6 @@ static gint inc_start(IncProgressDialog *inc_dialog) folder_item_update_thaw(); g_slist_free(msglist); - g_slist_free(filtered); - g_slist_free(unfiltered); statusbar_pop_all(); @@ -1379,7 +1374,6 @@ static gint inc_spool_account(PrefsAccount *account) static gint get_spool(FolderItem *dest, const gchar *mbox, PrefsAccount *account) { gint msgs, size; - gint lockfd; gchar tmp_mbox[MAXPATHLEN + 1]; cm_return_val_if_fail(dest != NULL, -1); @@ -1387,30 +1381,34 @@ static gint get_spool(FolderItem *dest, const gchar *mbox, PrefsAccount *account cm_return_val_if_fail(account != NULL, -1); if (!is_file_exist(mbox) || (size = get_file_size(mbox)) == 0) { - debug_print("%s: no messages in local mailbox.\n", mbox); + debug_print("%s: no messages\n", mbox); return 0; } else if (size < 0) return -1; - if ((lockfd = lock_mbox(mbox, LOCK_FLOCK)) < 0) - return -1; - - g_snprintf(tmp_mbox, sizeof(tmp_mbox), "%s%ctmpmbox.%p", - get_tmp_dir(), G_DIR_SEPARATOR, mbox); + g_snprintf(tmp_mbox, sizeof(tmp_mbox), "%s/tmpmbox.%p", get_tmp_dir(), mbox); - if (copy_mbox(lockfd, tmp_mbox) < 0) { - unlock_mbox(mbox, lockfd, LOCK_FLOCK); + int spool = open(mbox, O_RDONLY); + if (flock(spool, LOCK_EX|LOCK_NB) < 0) { + perror("lock mbox"); return -1; } - - debug_print("Getting new messages from %s into %s...\n", - mbox, dest->path); + debug_print("Getting new messages from %s into %s...\n", mbox, dest->path); + if (copy_mbox(spool, tmp_mbox) < 0) { + flock(spool, LOCK_UN); + close(spool); + return -1; + } + close(spool); msgs = proc_mbox(dest, tmp_mbox, FALSE, account); - unlink(tmp_mbox); - if (msgs >= 0) empty_mbox(mbox); - unlock_mbox(mbox, lockfd, LOCK_FLOCK); + if (msgs >= 0) { + if (truncate(mbox, 0) < 0) + perror("truncate mbox"); + } + + flock(spool, LOCK_UN); return msgs; } diff --git a/src/main.c b/src/main.c @@ -27,24 +27,19 @@ #include <glib/gi18n.h> #include <gtk/gtk.h> +#include <ctype.h> +#include <errno.h> +#include <fcntl.h> +#include <signal.h> +#include <stdbool.h> #include <stdio.h> #include <stdlib.h> -#include <stdbool.h> #include <string.h> -#include <ctype.h> -#include <unistd.h> -#include <time.h> +#include <sys/file.h> #include <sys/stat.h> #include <sys/types.h> -#ifdef G_OS_UNIX -# include <signal.h> -# include <errno.h> -# include <fcntl.h> -#endif - -#if HAVE_FLOCK -#include <sys/file.h> -#endif +#include <time.h> +#include <unistd.h> #ifdef HAVE_VALGRIND #include <valgrind.h> @@ -1314,7 +1309,6 @@ static gint prohibit_duplicate_launch(int *argc, char ***argv) { gint sock; GList *curr; -#ifdef G_OS_UNIX gchar *path; path = claws_get_socket_name(); @@ -1323,7 +1317,6 @@ static gint prohibit_duplicate_launch(int *argc, char ***argv) if (sock < 0) { gint ret; -#if HAVE_FLOCK gchar *socket_lock; gint lock_fd; /* If connect failed, no other process is running. @@ -1349,38 +1342,16 @@ static gint prohibit_duplicate_launch(int *argc, char ***argv) g_free(socket_lock); return -1; } -#endif unlink(path); debug_print("Opening socket %s\n", path); ret = fd_open_unix(path); -#if HAVE_FLOCK flock(lock_fd, LOCK_UN); close(lock_fd); unlink(socket_lock); g_free(socket_lock); -#endif return ret; } -#else - HANDLE hmutex; - - hmutex = CreateMutexA(NULL, FALSE, "ClawsMail"); - if (!hmutex) { - debug_print("cannot create Mutex\n"); - return -1; - } - if (GetLastError() != ERROR_ALREADY_EXISTS) { - sock = fd_open_inet(50216); - if (sock < 0) - return 0; - return sock; - } - - sock = fd_connect_inet(50216); - if (sock < 0) - return -1; -#endif /* remote command mode */ debug_print("another Claws Mail instance is already running.\n"); diff --git a/src/mbox.c b/src/mbox.c @@ -258,171 +258,6 @@ gint proc_mbox(FolderItem *dest, const gchar *mbox, gboolean apply_filter, return msgs; } -gint lock_mbox(const gchar *base, LockType type) -{ -#ifdef G_OS_UNIX - gint retval = 0; - - if (type == LOCK_FILE) { - gchar *lockfile, *locklink; - gint retry = 0; - FILE *lockfp; - - lockfile = g_strdup_printf("%s.%d", base, getpid()); - if ((lockfp = g_fopen(lockfile, "wb")) == NULL) { - FILE_OP_ERROR(lockfile, "g_fopen"); - g_warning("can't create lock file '%s', use 'flock' instead of 'file' if possible", lockfile); - g_free(lockfile); - return -1; - } - - if (fprintf(lockfp, "%d\n", getpid()) < 0) { - FILE_OP_ERROR(lockfile, "fprintf"); - g_free(lockfile); - fclose(lockfp); - return -1; - } - - if (safe_fclose(lockfp) == EOF) { - FILE_OP_ERROR(lockfile, "fclose"); - g_free(lockfile); - return -1; - } - - locklink = g_strconcat(base, ".lock", NULL); - while (link(lockfile, locklink) < 0) { - FILE_OP_ERROR(lockfile, "link"); - if (retry >= 5) { - g_warning("can't create '%s'", lockfile); - unlink(lockfile); - g_free(locklink); - g_free(lockfile); - return -1; - } - if (retry == 0) - g_warning("mailbox is owned by another process, waiting"); - retry++; - sleep(5); - } - unlink(lockfile); - g_free(locklink); - g_free(lockfile); - } else if (type == LOCK_FLOCK) { - gint lockfd; - gboolean fcntled = FALSE; -#if HAVE_FCNTL_H && !defined(G_OS_WIN32) - struct flock fl; - fl.l_type = F_WRLCK; - fl.l_whence = SEEK_SET; - fl.l_start = 0; - fl.l_len = 0; -#endif - -#if HAVE_FLOCK - if ((lockfd = g_open(base, O_RDWR, 0)) < 0) { -#else - if ((lockfd = g_open(base, O_RDWR, 0)) < 0) { -#endif - FILE_OP_ERROR(base, "open"); - return -1; - } - -#if HAVE_FCNTL_H && !defined(G_OS_WIN32) - if (fcntl(lockfd, F_SETLK, &fl) == -1) { - g_warning("can't fnctl %s (%s)", base, g_strerror(errno)); - close(lockfd); - return -1; - } else { - fcntled = TRUE; - } -#endif - -#if HAVE_FLOCK - if (flock(lockfd, LOCK_EX|LOCK_NB) < 0 && !fcntled) { - perror("flock"); -#else -#if HAVE_LOCKF - if (lockf(lockfd, F_TLOCK, 0) < 0 && !fcntled) { - perror("lockf"); -#else - { -#endif -#endif /* HAVE_FLOCK */ - g_warning("can't lock %s", base); - if (close(lockfd) < 0) - perror("close"); - return -1; - } - retval = lockfd; - } else { - g_warning("invalid lock type"); - return -1; - } - - return retval; -#else - return -1; -#endif /* G_OS_UNIX */ -} - -gint unlock_mbox(const gchar *base, gint fd, LockType type) -{ - if (type == LOCK_FILE) { - gchar *lockfile; - - lockfile = g_strconcat(base, ".lock", NULL); - if (unlink(lockfile) < 0) { - FILE_OP_ERROR(lockfile, "unlink"); - g_free(lockfile); - return -1; - } - g_free(lockfile); - - return 0; - } else if (type == LOCK_FLOCK) { -#if HAVE_FCNTL_H && !defined(G_OS_WIN32) - gboolean fcntled = FALSE; - struct flock fl; - fl.l_type = F_UNLCK; - fl.l_whence = SEEK_SET; - fl.l_start = 0; - fl.l_len = 0; - - if (fcntl(fd, F_SETLK, &fl) == -1) { - g_warning("can't fnctl %s", base); - } else { - fcntled = TRUE; - } -#endif -#if HAVE_FLOCK - if (flock(fd, LOCK_UN) < 0 && !fcntled) { - perror("flock"); -#else -#if HAVE_LOCKF - if (lockf(fd, F_ULOCK, 0) < 0 && !fcntled) { - perror("lockf"); -#else - { -#endif -#endif /* HAVE_FLOCK */ - g_warning("can't unlock %s", base); - if (close(fd) < 0) - perror("close"); - return -1; - } - - if (close(fd) < 0) { - perror("close"); - return -1; - } - - return 0; - } - - g_warning("invalid lock type"); - return -1; -} - gint copy_mbox(gint srcfd, const gchar *dest) { FILE *dest_fp; @@ -473,18 +308,6 @@ gint copy_mbox(gint srcfd, const gchar *dest) return 0; } -void empty_mbox(const gchar *mbox) -{ - FILE *fp; - - if ((fp = g_fopen(mbox, "wb")) == NULL) { - FILE_OP_ERROR(mbox, "g_fopen"); - g_warning("can't truncate mailbox to zero"); - return; - } - safe_fclose(fp); -} - gint export_list_to_mbox(GSList *mlist, const gchar *mbox) /* return values: -2 skipped, -1 error, 0 OK */ { diff --git a/src/mbox.h b/src/mbox.h @@ -14,7 +14,7 @@ * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. - * + * */ #ifndef __MBOX_H__ @@ -24,28 +24,16 @@ #include "folder.h" -typedef enum { - LOCK_FILE, - LOCK_FLOCK -} LockType; - - gint proc_mbox (FolderItem *dest, const gchar *mbox, gboolean apply_filter, PrefsAccount *account); -gint lock_mbox (const gchar *base, - LockType type); -gint unlock_mbox (const gchar *base, - gint fd, - LockType type); gint copy_mbox (gint srcfd, const gchar *dest); -void empty_mbox (const gchar *mbox); gint export_to_mbox (FolderItem *src, const gchar *mbox); -gint export_list_to_mbox(GSList *mlist, +gint export_list_to_mbox(GSList *mlist, const gchar *mbox); #endif /* __MBOX_H__ */