* Author: Peter Wang <novalazy@gmail.com>
*/
-#include "notmuch-client.h"
-#include "tag-util.h"
-#include <sys/types.h>
-#include <sys/stat.h>
#include <fcntl.h>
+
+#include "notmuch-client.h"
+#include "tag-util.h"
#include "string-util.h"
+#include "path-util.h"
static volatile sig_atomic_t interrupted;
}
}
-/* 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
}
}
-/*
- * 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
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]);
return false;
}
- if (! mkdir_recursive (ctx, subdir, mode))
+ if (mkdir_recursive (ctx, subdir, mode, status_string))
return false;
}
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)
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;
}
#define _GNU_SOURCE
#include "path-util.h"
-
+#include "compat.h"
+#include <string.h>
+#include <stdio.h>
+#include <errno.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
#include <limits.h>
#include <stdlib.h>
+#include <talloc.h>
char *
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;
+}