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 80ABA431FD8 for ; Sun, 28 Sep 2014 11:29:24 -0700 (PDT) X-Virus-Scanned: Debian amavisd-new at olra.theworths.org X-Spam-Flag: NO X-Spam-Score: 0 X-Spam-Level: X-Spam-Status: No, score=0 tagged_above=-999 required=5 tests=[none] 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 xS4RMl-BkY4h for ; Sun, 28 Sep 2014 11:29:19 -0700 (PDT) Received: from yantan.tethera.net (yantan.tethera.net [199.188.72.155]) (using TLSv1 with cipher DHE-RSA-AES128-SHA (128/128 bits)) (No client certificate requested) by olra.theworths.org (Postfix) with ESMTPS id B2600431FDC for ; Sun, 28 Sep 2014 11:29:07 -0700 (PDT) Received: from remotemail by yantan.tethera.net with local (Exim 4.80) (envelope-from ) id 1XYJDX-0005gR-8c; Sun, 28 Sep 2014 15:29:07 -0300 Received: (nullmailer pid 31288 invoked by uid 1000); Sun, 28 Sep 2014 18:28:49 -0000 From: David Bremner To: notmuch@notmuchmail.org Subject: [WIP 2/3] cli/insert: move several file/directory manipulation routines into a new util file. Date: Sun, 28 Sep 2014 20:28:18 +0200 Message-Id: <1411928899-29625-3-git-send-email-david@tethera.net> X-Mailer: git-send-email 2.1.0 In-Reply-To: <1411928899-29625-1-git-send-email-david@tethera.net> References: <87iok8vog6.fsf@steelpick.2x.cz> <1411928899-29625-1-git-send-email-david@tethera.net> 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: Sun, 28 Sep 2014 18:29:25 -0000 This will promote code sharing of low level file operations. --- notmuch-insert.c | 79 ++---------------------------------------- util/Makefile.local | 1 + util/file-util.c | 98 +++++++++++++++++++++++++++++++++++++++++++++++++++++ util/file-util.h | 20 +++++++++++ 4 files changed, 121 insertions(+), 77 deletions(-) create mode 100644 util/file-util.c create mode 100644 util/file-util.h diff --git a/notmuch-insert.c b/notmuch-insert.c index 5ef6e66..48bdd28 100644 --- a/notmuch-insert.c +++ b/notmuch-insert.c @@ -23,6 +23,7 @@ #include "notmuch-client.h" #include "tag-util.h" +#include "file-util.h" #include #include @@ -63,26 +64,6 @@ safe_gethostname (char *hostname, size_t len) } } -/* Call fsync() on a directory path. */ -static notmuch_bool_t -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 @@ -92,65 +73,9 @@ sync_dir (const char *dir) static notmuch_bool_t is_valid_folder_name (const char *folder) { - const char *p = folder; - - for (;;) { - if ((p[0] == '.') && (p[1] == '.') && (p[2] == '\0' || p[2] == '/')) - return FALSE; - p = strchr (p, '/'); - if (!p) - return TRUE; - p++; - } + return ! has_double_dot_component (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 notmuch_bool_t -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 diff --git a/util/Makefile.local b/util/Makefile.local index 905f237..8749cfb 100644 --- a/util/Makefile.local +++ b/util/Makefile.local @@ -5,6 +5,7 @@ extra_cflags += -I$(srcdir)/$(dir) libutil_c_srcs := $(dir)/xutil.c $(dir)/error_util.c $(dir)/hex-escape.c \ $(dir)/string-util.c $(dir)/talloc-extra.c $(dir)/zlib-extra.c \ + $(dir)/file-util.c \ $(dir)/util.c libutil_modules := $(libutil_c_srcs:.c=.o) diff --git a/util/file-util.c b/util/file-util.c new file mode 100644 index 0000000..66c4485 --- /dev/null +++ b/util/file-util.c @@ -0,0 +1,98 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +#include "file-util.h" + +/* + * Check whether specified path name contains a directory + * component "..". to prevent writes outside of the Maildir + */ +int +has_double_dot_component (const char *path) +{ + const char *p = path; + + for (;;) { + if ((p[0] == '.') && (p[1] == '.') && (p[2] == '\0' || p[2] == '/')) + return TRUE; + p = strchr (p, '/'); + if (!p) + return FALSE; + p++; + } +} + +/* + * Make the given directory and its parents as necessary, using the + * given mode. return TRUE on success, 0 otherwise. Partial + * results are not cleaned up on errors. + */ +int +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; +} + +/* Call fsync() on a directory path. */ +int +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; +} diff --git a/util/file-util.h b/util/file-util.h new file mode 100644 index 0000000..4f96957 --- /dev/null +++ b/util/file-util.h @@ -0,0 +1,20 @@ +#ifndef _FILE_UTIL_H +#define _FILE_UTIL_H + +#ifndef FALSE +#define FALSE 0 +#endif +#ifndef TRUE +#define TRUE 1 +#endif + +int +has_double_dot_component (const char *path); + +int +mkdir_recursive (const void *ctx, const char *path, int mode); + +int +sync_dir (const char *path); + +#endif -- 2.1.0