Return-Path: X-Original-To: notmuch@notmuchmail.org Delivered-To: notmuch@notmuchmail.org Received: from localhost (localhost [127.0.0.1]) by olra.theworths.org (Postfix) with ESMTP id CD2EA431FC0 for ; Mon, 22 Sep 2014 02:55:11 -0700 (PDT) X-Virus-Scanned: Debian amavisd-new at olra.theworths.org X-Amavis-Alert: BAD HEADER SECTION, Duplicate header field: "References" X-Spam-Flag: NO X-Spam-Score: -0.7 X-Spam-Level: X-Spam-Status: No, score=-0.7 tagged_above=-999 required=5 tests=[RCVD_IN_DNSWL_LOW=-0.7] autolearn=disabled Received: from olra.theworths.org ([127.0.0.1]) by localhost (olra.theworths.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id Xs7z0sPjbAyE for ; Mon, 22 Sep 2014 02:55:07 -0700 (PDT) Received: from mail-wi0-f170.google.com (mail-wi0-f170.google.com [209.85.212.170]) (using TLSv1 with cipher RC4-SHA (128/128 bits)) (No client certificate requested) by olra.theworths.org (Postfix) with ESMTPS id C50C0431FDE for ; Mon, 22 Sep 2014 02:54:56 -0700 (PDT) Received: by mail-wi0-f170.google.com with SMTP id fb4so2486823wid.3 for ; Mon, 22 Sep 2014 02:54:55 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:in-reply-to:references; bh=+eJmjEEFeki5WtosF6F2YBxONWtxesmKdqnnEpOzjBk=; b=V7RyB2D9NOHfx7axwrDe1aqhWmgpfBAbEhV8kJBNWu3NbUHnMpgO/owi1o5Rh1dRKR p2o5F41oFfucEM665JBfKmw/61YOU1QGvXOXxUnHEJ01myngkxvwbPJ3SAnkWLXmG3Ad nx8tnqMh6U6UYCaU1NtaxsiFwfunPI0mR9U5RrOcTl+UZLWb1e3uGEuGP4PrAnxJG9UU GdtCZaF7MCftKJ/ziLR+sr5Z3jE8ddhZO6LTv6/lrLDApCFSlpHOdAxXckROyqx1zQGz WA+NrDR6vCbIOt+SFQgGqKXzZp7abV4HLDmnjCAlrHvJt/obxKbwORmPjsewvS9TTOWk Q+AQ== X-Gm-Message-State: ALoCoQlzw4D32NBOxTVZciiM1YX08srcr/bLmrCMk09EjNkT0Nukcy8L8zWiuh841xBB2kBFDwa7 X-Received: by 10.180.75.143 with SMTP id c15mr14512427wiw.31.1411379695711; Mon, 22 Sep 2014 02:54:55 -0700 (PDT) Received: from localhost ([2001:4b98:dc0:43:216:3eff:fe1b:25f3]) by mx.google.com with ESMTPSA id ky3sm11695685wjb.39.2014.09.22.02.54.55 for (version=TLSv1.1 cipher=RC4-SHA bits=128/128); Mon, 22 Sep 2014 02:54:55 -0700 (PDT) From: Jani Nikula To: notmuch@notmuchmail.org Subject: [PATCH 06/11] cli/insert: use a single recursive mkdir function Date: Mon, 22 Sep 2014 11:54:57 +0200 Message-Id: <3059bb1ef1dede24e28d9827082ca36c8e6c5996.1411379395.git.jani@nikula.org> X-Mailer: git-send-email 1.7.2.5 In-Reply-To: References: In-Reply-To: References: X-BeenThere: notmuch@notmuchmail.org X-Mailman-Version: 2.1.13 Precedence: list List-Id: "Use and development of the notmuch mail system." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 22 Sep 2014 09:55:12 -0000 Combine make_directory() and make_directory_and_parents() into a single recursive mkdir_recursive() function. Clarify the code and improve error handling. Improve error messages. Switch to using the new function in maildir_create_folder(). Constify talloc context. --- notmuch-insert.c | 131 +++++++++++++++++++++++------------------------------- 1 files changed, 55 insertions(+), 76 deletions(-) diff --git a/notmuch-insert.c b/notmuch-insert.c index 7375c54..cdeeb41 100644 --- a/notmuch-insert.c +++ b/notmuch-insert.c @@ -104,96 +104,78 @@ is_valid_folder_name (const char *folder) } } -/* Make the given directory, succeeding if it already exists. */ +/* + * 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 notmuch_bool_t -make_directory (char *path, int mode) +mkdir_recursive (const void *ctx, const char *path, int mode) { - notmuch_bool_t ret; - char *slash; + struct stat st; + int r; + char *parent = NULL, *slash; - if (mkdir (path, mode) != 0) - return (errno == EEXIST); + /* 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; + } - /* Sync the parent directory for durability. */ - ret = TRUE; - slash = strrchr (path, '/'); - if (slash) { - *slash = '\0'; - ret = sync_dir (path); - *slash = '/'; + return TRUE; + } else if (errno != ENOENT) { + fprintf (stderr, "Error: stat '%s': %s\n", path, strerror (errno)); + return FALSE; } - return ret; -} - -/* Make the given directory including its parent directories as necessary. - * Return TRUE on success, FALSE on error. */ -static notmuch_bool_t -make_directory_and_parents (char *path, int mode) -{ - struct stat st; - char *start; - char *end; - notmuch_bool_t ret; - /* First check the common case: directory already exists. */ - if (stat (path, &st) == 0) - return S_ISDIR (st.st_mode) ? TRUE : FALSE; - - for (start = path; *start != '\0'; start = end + 1) { - /* start points to the first unprocessed character. - * Find the next slash from start onwards. */ - end = strchr (start, '/'); - - /* If there are no more slashes then all the parent directories - * have been made. Now attempt to make the whole path. */ - if (end == NULL) - return make_directory (path, mode); - - /* Make the path up to the next slash, unless the current - * directory component is actually empty. */ - if (end > start) { - *end = '\0'; - ret = make_directory (path, mode); - *end = '/'; - if (! ret) - 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; } - return TRUE; + 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. dir and its subdirectories - * 'cur', 'new', 'tmp'. */ +/* + * Create the given maildir folder, i.e. maildir and its + * subdirectories cur/new/tmp. Return TRUE on success, FALSE + * otherwise. Partial results are not cleaned up on errors. + */ static notmuch_bool_t -maildir_create_folder (void *ctx, const char *dir) +maildir_create_folder (const void *ctx, const char *maildir) { + const char *subdirs[] = { "cur", "new", "tmp" }; const int mode = 0700; char *subdir; - char *tail; - - /* Create 'cur' directory, including parent directories. */ - subdir = talloc_asprintf (ctx, "%s/cur", dir); - if (! subdir) { - fprintf (stderr, "Out of memory.\n"); - return FALSE; - } - if (! make_directory_and_parents (subdir, mode)) - return FALSE; - - tail = subdir + strlen (subdir) - 3; + unsigned int i; - /* Create 'new' directory. */ - strcpy (tail, "new"); - if (! make_directory (subdir, mode)) - return FALSE; + for (i = 0; i < ARRAY_SIZE (subdirs); i++) { + subdir = talloc_asprintf (ctx, "%s/%s", maildir, subdirs[i]); + if (! subdir) { + fprintf (stderr, "Error: %s\n", strerror (ENOMEM)); + return FALSE; + } - /* Create 'tmp' directory. */ - strcpy (tail, "tmp"); - if (! make_directory (subdir, mode)) - return FALSE; + if (! mkdir_recursive (ctx, subdir, mode)) + return FALSE; + } - talloc_free (subdir); return TRUE; } @@ -463,11 +445,8 @@ notmuch_insert_command (notmuch_config_t *config, int argc, char *argv[]) fprintf (stderr, "Out of memory\n"); return EXIT_FAILURE; } - if (create_folder && ! maildir_create_folder (config, maildir)) { - fprintf (stderr, "Error: creating maildir %s: %s\n", - maildir, strerror (errno)); + if (create_folder && ! maildir_create_folder (config, maildir)) return EXIT_FAILURE; - } } /* Setup our handler for SIGINT. We do not set SA_RESTART so that copying -- 1.7.2.5