From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mp1.migadu.com ([2001:41d0:403:4876::]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)) by ms13.migadu.com with LMTPS id KEsFBRaN3WaKfAAA62LTzQ:P1 (envelope-from ) for ; Sun, 08 Sep 2024 11:40:06 +0000 Received: from aspmx1.migadu.com ([2001:41d0:403:4876::]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)) by mp1.migadu.com with LMTPS id KEsFBRaN3WaKfAAA62LTzQ (envelope-from ) for ; Sun, 08 Sep 2024 13:40:06 +0200 X-Envelope-To: larch@yhetil.org Authentication-Results: aspmx1.migadu.com; dkim=fail ("body hash did not verify") header.d=tethera.net header.s=2024 header.b=LMBXbgUZ; spf=pass (aspmx1.migadu.com: domain of notmuch-bounces@notmuchmail.org designates 135.181.149.255 as permitted sender) smtp.mailfrom=notmuch-bounces@notmuchmail.org; dmarc=none ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=yhetil.org; s=key1; t=1725795606; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references:list-id:list-help: list-owner:list-unsubscribe:list-subscribe:list-post:dkim-signature; bh=MLo1ANrzD9GXBvmkebYFvudrV5Ewo/nGnfqglc0AyX4=; b=t1BF6S34Rl75lw8NBTlO6jsK2hd06GdTu4OEG0JZX4tPjptXAqVfu1nEk6shJW6z267JEp 01RP7GVps+ehbhd1iU4chMdioKgQPiC9ybTfCtkviU9L/a0YWwKCmU2Ar7FQ51I1S8Aj9L bnri7yrFlu04CcOP+vzkMNVy6OgIaYeyOWGr1U+CursD+7l4pkUTPBwQXX8MT4x18yl2c1 E4PfIRULDTNulmAWtYrSRwHxjqof4QM0Wgh+rDlOs5KEIcOO2AzG84freYhIqv6hlwmJNw lJSsHJNrzKV1GXW0JSB2sGcseOgQFlj3FBqbnQiVAmrlNthwOIDu/tKB4YY08w== ARC-Authentication-Results: i=1; aspmx1.migadu.com; dkim=fail ("body hash did not verify") header.d=tethera.net header.s=2024 header.b=LMBXbgUZ; spf=pass (aspmx1.migadu.com: domain of notmuch-bounces@notmuchmail.org designates 135.181.149.255 as permitted sender) smtp.mailfrom=notmuch-bounces@notmuchmail.org; dmarc=none ARC-Seal: i=1; s=key1; d=yhetil.org; t=1725795606; a=rsa-sha256; cv=none; b=CknJxm9UlLGePfuCaksbsqjV05aa50MuhVOJu4Kt0hzg2nT8ZnsnjBUM2QreK3vv2jFabF dU8bju+i6vzX5SWjhGG2s15+8PN1r5JvGMFWAQlIvTWrDh9PT2DSglgxYant4csoR9JTVH Zfr6suye3zFBwyFc5rb7aEdvxDVmV6kx6cRsYufJHdDlaqXcghUD3rbYTGABd/Hvi+6Jxw K0Kbs/VkTjnXz+FP8zRWy6tDeilglVCnhrcTNU1X7UJxr7+zg2i+cqrds2unHYrHAUZ1aP IuyEpOc4+RmR0pOpRY59J0h74xfsHOjyKYsT0raLZOmV4+spqEzFvEETWYeYYQ== Received: from mail.notmuchmail.org (yantan.tethera.net [135.181.149.255]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by aspmx1.migadu.com (Postfix) with ESMTPS id 8658336CDB for ; Sun, 08 Sep 2024 13:40:02 +0200 (CEST) Received: from yantan.tethera.net (localhost [127.0.0.1]) by mail.notmuchmail.org (Postfix) with ESMTP id BD47A5E2A3; Sun, 8 Sep 2024 11:39:52 +0000 (UTC) Received: from phubs.tethera.net (phubs.tethera.net [192.99.9.157]) by mail.notmuchmail.org (Postfix) with ESMTPS id 053A45E292 for ; Sun, 8 Sep 2024 11:39:49 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=tethera.net; i=@tethera.net; q=dns/txt; s=2024; t=1725795587; h=from : to : cc : subject : date : message-id : in-reply-to : references : mime-version : content-transfer-encoding : from; bh=zG/eXGDMLcdLExnpsFx2yr64iQ0NGBQQA/8gmfNgFNI=; b=LMBXbgUZqn1cEuFgr4oUOzpRSpxWcNaoCRU43G4tEujiZ0wRi6s8hB/dEziM+nYfeRmzk Leipj8BppOZi1HLI8wIvRPZu0ogqsd/BzOXOc6PX1yRqt4yOzYKNct0JvG/rcJELk0Xed1F FYX8X74dnvd07+i8mSib5i3K9fztKj6ObPLm/ELJq3UQVnIeZrpvfHsMekUa4bbq3G8Lz/i o6cZ6lQD2UwoGec9xznvgsN92o8U//N+D6EAuQsF41pC9F+scKgK1kRuIKlPcDQItTjDeg7 6u9WIaq81FfRYKyPNajSrROdhVJlZEFIz6lop8E0QXJtY8r+AH1FX2ti9jew== Received: from tethera.net (fctnnbsc51w-159-2-211-58.dhcp-dynamic.fibreop.nb.bellaliant.net [159.2.211.58]) by phubs.tethera.net (Postfix) with ESMTPS id 257C3180181; Sun, 8 Sep 2024 08:39:47 -0300 (ADT) Received: (nullmailer pid 286542 invoked by uid 1000); Sun, 08 Sep 2024 11:39:45 -0000 From: David Bremner To: notmuch@notmuchmail.org Subject: [PATCH v2 1/4] util: refactor sync_dir and mkdir_recursive Date: Sun, 8 Sep 2024 08:27:29 -0300 Message-ID: <20240908113937.286108-2-david@tethera.net> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20240908113937.286108-1-david@tethera.net> References: <20240908113937.286108-1-david@tethera.net> MIME-Version: 1.0 Message-ID-Hash: RRZD43GBJSPDVEAYSRAGGTPBUDB2CY2L X-Message-ID-Hash: RRZD43GBJSPDVEAYSRAGGTPBUDB2CY2L X-MailFrom: bremner@tethera.net X-Mailman-Rule-Misses: dmarc-mitigation; no-senders; approved; emergency; loop; banned-address; member-moderation; header-match-notmuch.notmuchmail.org-0; nonmember-moderation; administrivia; implicit-dest; max-recipients; max-size; news-moderation; no-subject; digests; suspicious-header X-Mailman-Version: 3.3.3 Precedence: list List-Id: "Use and development of the notmuch mail system." List-Help: List-Owner: List-Post: List-Subscribe: List-Unsubscribe: Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit X-Migadu-Country: DE X-Migadu-Flow: FLOW_IN X-Spam-Score: 3.62 X-Migadu-Queue-Id: 8658336CDB X-Migadu-Scanner: mx10.migadu.com X-Migadu-Spam-Score: 3.62 X-TUID: y7y/+oCZkaNY Moving these functions to libnotmuch_util will allow re-user from either multiple CLI compilation units or from the library. To avoid future surprises, replace printing to stderr with the usual status string mechanism. --- notmuch-insert.c | 84 +++++------------------------------------ util/path-util.c | 97 +++++++++++++++++++++++++++++++++++++++++++++++- util/path-util.h | 8 ++++ 3 files changed, 114 insertions(+), 75 deletions(-) diff --git a/notmuch-insert.c b/notmuch-insert.c index e44607ad..66c4f434 100644 --- a/notmuch-insert.c +++ b/notmuch-insert.c @@ -21,13 +21,13 @@ * Author: Peter Wang */ -#include "notmuch-client.h" -#include "tag-util.h" -#include -#include #include + +#include "notmuch-client.h" +#include "tag-util.h" #include "string-util.h" +#include "path-util.h" static volatile sig_atomic_t interrupted; @@ -64,26 +64,6 @@ safe_gethostname (char *hostname, size_t len) } } -/* Call fsync() on a directory path. */ -static bool -sync_dir (const char *dir) -{ - int fd, r; - - fd = open (dir, O_RDONLY); - if (fd == -1) { - fprintf (stderr, "Error: open %s: %s\n", dir, strerror (errno)); - return false; - } - - r = fsync (fd); - if (r) - fprintf (stderr, "Error: fsync %s: %s\n", dir, strerror (errno)); - - close (fd); - - return r == 0; -} /* * Check the specified folder name does not contain a directory @@ -105,54 +85,6 @@ is_valid_folder_name (const char *folder) } } -/* - * Make the given directory and its parents as necessary, using the - * given mode. Return true on success, false otherwise. Partial - * results are not cleaned up on errors. - */ -static bool -mkdir_recursive (const void *ctx, const char *path, int mode) -{ - struct stat st; - int r; - char *parent = NULL, *slash; - - /* First check the common case: directory already exists. */ - r = stat (path, &st); - if (r == 0) { - if (! S_ISDIR (st.st_mode)) { - fprintf (stderr, "Error: '%s' is not a directory: %s\n", - path, strerror (EEXIST)); - return false; - } - - return true; - } else if (errno != ENOENT) { - fprintf (stderr, "Error: stat '%s': %s\n", path, strerror (errno)); - return false; - } - - /* mkdir parents, if any */ - slash = strrchr (path, '/'); - if (slash && slash != path) { - parent = talloc_strndup (ctx, path, slash - path); - if (! parent) { - fprintf (stderr, "Error: %s\n", strerror (ENOMEM)); - return false; - } - - if (! mkdir_recursive (ctx, parent, mode)) - return false; - } - - if (mkdir (path, mode)) { - fprintf (stderr, "Error: mkdir '%s': %s\n", path, strerror (errno)); - return false; - } - - return parent ? sync_dir (parent) : true; -} - /* * Create the given maildir folder, i.e. maildir and its * subdirectories cur/new/tmp. Return true on success, false @@ -165,6 +97,7 @@ maildir_create_folder (const void *ctx, const char *maildir, bool world_readable const int mode = (world_readable ? 0755 : 0700); char *subdir; unsigned int i; + char **status_string = NULL; for (i = 0; i < ARRAY_SIZE (subdirs); i++) { subdir = talloc_asprintf (ctx, "%s/%s", maildir, subdirs[i]); @@ -173,7 +106,7 @@ maildir_create_folder (const void *ctx, const char *maildir, bool world_readable return false; } - if (! mkdir_recursive (ctx, subdir, mode)) + if (mkdir_recursive (ctx, subdir, mode, status_string)) return false; } @@ -347,6 +280,7 @@ static char * maildir_write_new (const void *ctx, int fdin, const char *maildir, bool world_readable) { char *cleanpath, *tmppath, *newpath, *newdir; + char *status_string = NULL; tmppath = maildir_write_tmp (ctx, fdin, maildir, world_readable); if (! tmppath) @@ -375,13 +309,15 @@ maildir_write_new (const void *ctx, int fdin, const char *maildir, bool world_re goto FAIL; } - if (! sync_dir (newdir)) + if (sync_dir (newdir, &status_string)) goto FAIL; return newpath; FAIL: unlink (cleanpath); + if (status_string) + fputs (status_string, stderr); return NULL; } diff --git a/util/path-util.c b/util/path-util.c index 3267a967..5511c09b 100644 --- a/util/path-util.c +++ b/util/path-util.c @@ -5,10 +5,17 @@ #define _GNU_SOURCE #include "path-util.h" - +#include "compat.h" +#include +#include +#include +#include +#include +#include #include #include +#include char * notmuch_canonicalize_file_name (const char *path) @@ -25,3 +32,91 @@ notmuch_canonicalize_file_name (const char *path) #error undefined PATH_MAX _and_ missing canonicalize_file_name not supported #endif } + +/* Call fsync() on a directory path. */ +notmuch_status_t +sync_dir (const char *dir, char **status_string) +{ + int fd, r; + + fd = open (dir, O_RDONLY); + if (fd == -1) { + if (status_string) + IGNORE_RESULT (asprintf (status_string, + "Error: open %s: %s\n", dir, strerror (errno))); + return NOTMUCH_STATUS_FILE_ERROR; + } + + r = fsync (fd); + if (r && status_string) + IGNORE_RESULT (asprintf (status_string, + "Error: fsync %s: %s\n", dir, strerror (errno))); + + close (fd); + + return r == 0 ? NOTMUCH_STATUS_SUCCESS : NOTMUCH_STATUS_FILE_ERROR; +} + +/* + * Make the given directory and its parents as necessary, using the + * given mode. Partial results are not cleaned up on errors. + */ +notmuch_status_t +mkdir_recursive (const void *ctx, const char *path, int mode, + char **status_string) +{ + notmuch_status_t status; + struct stat st; + int r; + char *parent = NULL, *slash; + + /* First check the common case: directory already exists. */ + r = stat (path, &st); + if (r == 0) { + if (! S_ISDIR (st.st_mode)) { + if (status_string) + IGNORE_RESULT (asprintf (status_string, "Error: '%s' is not a directory: %s\n", + path, strerror (EEXIST))); + return NOTMUCH_STATUS_FILE_ERROR; + } + + return NOTMUCH_STATUS_SUCCESS; + } else if (errno != ENOENT) { + if (status_string) + IGNORE_RESULT (asprintf (status_string, + "Error: stat '%s': %s\n", path, strerror (errno))); + return NOTMUCH_STATUS_FILE_ERROR; + } + + /* mkdir parents, if any */ + slash = strrchr (path, '/'); + if (slash && slash != path) { + parent = talloc_strndup (ctx, path, slash - path); + if (! parent) { + if (status_string) + IGNORE_RESULT (asprintf (status_string, + "Error: %s\n", + strerror (ENOMEM))); + return NOTMUCH_STATUS_FILE_ERROR; + } + + status = mkdir_recursive (ctx, parent, mode, status_string); + if (status) + return status; + } + + if (mkdir (path, mode)) { + if (status_string) + IGNORE_RESULT (asprintf (status_string, + "Error: mkdir '%s': %s\n", + path, strerror (errno))); + return NOTMUCH_STATUS_FILE_ERROR; + } + + if (parent) { + status = sync_dir (parent, status_string); + if (status) + return status; + } + return NOTMUCH_STATUS_SUCCESS; +} diff --git a/util/path-util.h b/util/path-util.h index ac85f696..673c3b6f 100644 --- a/util/path-util.h +++ b/util/path-util.h @@ -5,6 +5,8 @@ #ifndef NOTMUCH_UTIL_PATH_UTIL_H_ #define NOTMUCH_UTIL_PATH_UTIL_H_ +#include "notmuch.h" + #ifdef __cplusplus extern "C" { #endif @@ -12,6 +14,12 @@ extern "C" { char * notmuch_canonicalize_file_name (const char *path); +notmuch_status_t +mkdir_recursive (const void *ctx, const char *path, int mode, char **status_string); + +notmuch_status_t +sync_dir (const char *path, char **status_string); + #ifdef __cplusplus } #endif -- 2.43.0