mirror of https://github.com/djcb/mu.git
* support '.noupdate' -- similar to '.noindex', maildirs containing
'.noupdate' will be ignored; however, they will _not_ be ignored when doing a full update (--rebuild)
This commit is contained in:
parent
5d5533c953
commit
9367f1ac6d
|
@ -309,7 +309,6 @@ mu_index_set_xbatch_size (MuIndex *index, guint xbatchsize)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
MuError
|
MuError
|
||||||
mu_index_run (MuIndex *index, const char* path,
|
mu_index_run (MuIndex *index, const char* path,
|
||||||
gboolean reindex, MuIndexStats *stats,
|
gboolean reindex, MuIndexStats *stats,
|
||||||
|
@ -337,6 +336,7 @@ mu_index_run (MuIndex *index, const char* path,
|
||||||
rv = mu_maildir_walk (path,
|
rv = mu_maildir_walk (path,
|
||||||
(MuMaildirWalkMsgCallback)on_run_maildir_msg,
|
(MuMaildirWalkMsgCallback)on_run_maildir_msg,
|
||||||
(MuMaildirWalkDirCallback)on_run_maildir_dir,
|
(MuMaildirWalkDirCallback)on_run_maildir_dir,
|
||||||
|
reindex, /* re-index, ie. do a full update */
|
||||||
&cb_data);
|
&cb_data);
|
||||||
|
|
||||||
mu_store_flush (index->_store);
|
mu_store_flush (index->_store);
|
||||||
|
@ -393,7 +393,7 @@ mu_index_stats (MuIndex *index, const char* path,
|
||||||
|
|
||||||
return mu_maildir_walk (path,
|
return mu_maildir_walk (path,
|
||||||
(MuMaildirWalkMsgCallback)on_stats_maildir_file,
|
(MuMaildirWalkMsgCallback)on_stats_maildir_file,
|
||||||
NULL,&cb_data);
|
NULL, FALSE, &cb_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct _CleanupData {
|
struct _CleanupData {
|
||||||
|
|
199
lib/mu-maildir.c
199
lib/mu-maildir.c
|
@ -1,7 +1,7 @@
|
||||||
/* -*-mode: c; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-*/
|
/* -*-mode: c; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Copyright (C) 2008-2011 Dirk-Jan C. Binnema <djcb@djcbsoftware.nl>
|
** Copyright (C) 2008-2012 Dirk-Jan C. Binnema <djcb@djcbsoftware.nl>
|
||||||
**
|
**
|
||||||
** This program is free software; you can redistribute it and/or modify it
|
** This program is free software; you can redistribute it and/or modify it
|
||||||
** under the terms of the GNU General Public License as published by the
|
** under the terms of the GNU General Public License as published by the
|
||||||
|
@ -47,6 +47,8 @@
|
||||||
#include "mu-str.h"
|
#include "mu-str.h"
|
||||||
|
|
||||||
#define MU_MAILDIR_NOINDEX_FILE ".noindex"
|
#define MU_MAILDIR_NOINDEX_FILE ".noindex"
|
||||||
|
#define MU_MAILDIR_NOUPDATE_FILE ".noupdate"
|
||||||
|
|
||||||
|
|
||||||
/* On Linux (and some BSD), we have entry->d_type, but some file
|
/* On Linux (and some BSD), we have entry->d_type, but some file
|
||||||
* systems (XFS, ReiserFS) do not support it, and set it DT_UNKNOWN.
|
* systems (XFS, ReiserFS) do not support it, and set it DT_UNKNOWN.
|
||||||
|
@ -88,13 +90,11 @@ create_maildir (const char *path, mode_t mode, GError **err)
|
||||||
/* note, g_mkdir_with_parents won't detect an error if
|
/* note, g_mkdir_with_parents won't detect an error if
|
||||||
* there's already such a dir, but with the wrong
|
* there's already such a dir, but with the wrong
|
||||||
* permissions; so we need to check */
|
* permissions; so we need to check */
|
||||||
if (rv != 0 || !mu_util_check_dir(fullpath, TRUE, TRUE)) {
|
if (rv != 0 || !mu_util_check_dir(fullpath, TRUE, TRUE))
|
||||||
g_set_error (err, MU_ERROR_DOMAIN, MU_ERROR_FILE_CANNOT_MKDIR,
|
return mu_util_g_set_error
|
||||||
"creating dir failed for %s: %s",
|
(err,MU_ERROR_FILE_CANNOT_MKDIR,
|
||||||
fullpath,
|
"creating dir failed for %s: %s",
|
||||||
strerror (errno));
|
fullpath, strerror (errno));
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
@ -114,13 +114,10 @@ create_noindex (const char *path, GError **err)
|
||||||
|
|
||||||
/* note, if the 'close' failed, creation may still have
|
/* note, if the 'close' failed, creation may still have
|
||||||
* succeeded...*/
|
* succeeded...*/
|
||||||
if (fd < 0 || close (fd) != 0) {
|
if (fd < 0 || close (fd) != 0)
|
||||||
g_set_error (err, MU_ERROR_DOMAIN, MU_ERROR_FILE_CANNOT_CREATE,
|
return mu_util_g_set_error (err, MU_ERROR_FILE_CANNOT_CREATE,
|
||||||
"error in create_noindex: %s",
|
"error in create_noindex: %s",
|
||||||
strerror (errno));
|
strerror (errno));
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -146,22 +143,22 @@ mu_maildir_mkdir (const char* path, mode_t mode, gboolean noindex, GError **err)
|
||||||
static gboolean
|
static gboolean
|
||||||
check_subdir (const char *src, gboolean *in_cur, GError **err)
|
check_subdir (const char *src, gboolean *in_cur, GError **err)
|
||||||
{
|
{
|
||||||
|
gboolean rv;
|
||||||
gchar *srcpath;
|
gchar *srcpath;
|
||||||
|
|
||||||
srcpath = g_path_get_dirname (src);
|
srcpath = g_path_get_dirname (src);
|
||||||
|
|
||||||
|
rv = TRUE;
|
||||||
if (g_str_has_suffix (srcpath, "new"))
|
if (g_str_has_suffix (srcpath, "new"))
|
||||||
*in_cur = FALSE;
|
*in_cur = FALSE;
|
||||||
else if (g_str_has_suffix (srcpath, "cur"))
|
else if (g_str_has_suffix (srcpath, "cur"))
|
||||||
*in_cur = TRUE;
|
*in_cur = TRUE;
|
||||||
else {
|
else
|
||||||
g_set_error(err, 0, MU_ERROR_FILE_INVALID_SOURCE,
|
rv = mu_util_g_set_error(err, MU_ERROR_FILE_INVALID_SOURCE,
|
||||||
"invalid source message '%s'", src);
|
"invalid source message '%s'", src);
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
g_free (srcpath);
|
g_free (srcpath);
|
||||||
|
|
||||||
return TRUE;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
static gchar*
|
static gchar*
|
||||||
|
@ -207,23 +204,21 @@ mu_maildir_link (const char* src, const char *targetpath, GError **err)
|
||||||
|
|
||||||
rv = symlink (src, targetfullpath);
|
rv = symlink (src, targetfullpath);
|
||||||
|
|
||||||
if (rv != 0) {
|
if (rv != 0)
|
||||||
g_set_error (err, MU_ERROR_DOMAIN, MU_ERROR_FILE_CANNOT_LINK,
|
mu_util_g_set_error (err, MU_ERROR_FILE_CANNOT_LINK,
|
||||||
"error creating link %s => %s: %s",
|
"error creating link %s => %s: %s",
|
||||||
targetfullpath, src, strerror (errno));
|
targetfullpath, src, strerror (errno));
|
||||||
g_free (targetfullpath);
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
g_free (targetfullpath);
|
g_free (targetfullpath);
|
||||||
return TRUE;
|
|
||||||
|
return rv == 0 ? TRUE: FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static MuError
|
static MuError
|
||||||
process_dir (const char* path, const gchar *mdir,
|
process_dir (const char* path, const gchar *mdir,
|
||||||
MuMaildirWalkMsgCallback msg_cb,
|
MuMaildirWalkMsgCallback msg_cb,
|
||||||
MuMaildirWalkDirCallback dir_cb, void *data);
|
MuMaildirWalkDirCallback dir_cb, gboolean full,
|
||||||
|
void *data);
|
||||||
|
|
||||||
static MuError
|
static MuError
|
||||||
process_file (const char* fullpath, const gchar* mdir,
|
process_file (const char* fullpath, const gchar* mdir,
|
||||||
|
@ -292,26 +287,26 @@ is_maildir_new_or_cur (const char *path)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* check if there is a noindex file (MU_MAILDIR_NOINDEX_FILE) in this
|
|
||||||
|
/* check if there path contains file; used for checking if there is
|
||||||
|
* MU_MAILDIR_NOINDEX_FILE or MU_MAILDIR_NOUPDATE_FILE in this
|
||||||
* dir; */
|
* dir; */
|
||||||
static gboolean
|
static gboolean
|
||||||
has_noindex_file (const char *path)
|
dir_contains_file (const char *path, const char *file)
|
||||||
{
|
{
|
||||||
const char* noindexpath;
|
const char* fullpath;
|
||||||
|
|
||||||
/* static buffer */
|
/* static buffer */
|
||||||
noindexpath = mu_str_fullpath_s (path, MU_MAILDIR_NOINDEX_FILE);
|
fullpath = mu_str_fullpath_s (path, file);
|
||||||
|
|
||||||
if (access (noindexpath, F_OK) == 0)
|
if (access (fullpath, F_OK) == 0)
|
||||||
return TRUE;
|
return TRUE;
|
||||||
else if (G_UNLIKELY(errno != ENOENT))
|
else if (G_UNLIKELY(errno != ENOENT))
|
||||||
g_warning ("error testing for noindex file %s: %s",
|
g_warning ("error testing for %s/%s: %s",
|
||||||
noindexpath, strerror(errno));
|
fullpath, file, strerror(errno));
|
||||||
|
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
is_dotdir_to_ignore (const char* dir)
|
is_dotdir_to_ignore (const char* dir)
|
||||||
{
|
{
|
||||||
|
@ -351,6 +346,9 @@ ignore_dir_entry (struct dirent *entry, unsigned char d_type)
|
||||||
if (entry->d_name[0] == 'd' &&
|
if (entry->d_name[0] == 'd' &&
|
||||||
strncmp (entry->d_name, "dovecot", 7) == 0)
|
strncmp (entry->d_name, "dovecot", 7) == 0)
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
/* ignore special files */
|
||||||
|
if (entry->d_name[0] == '.')
|
||||||
|
return TRUE;
|
||||||
/* ignore core files */
|
/* ignore core files */
|
||||||
if (entry->d_name[0] == 'c' &&
|
if (entry->d_name[0] == 'c' &&
|
||||||
strncmp (entry->d_name, "core", 4) == 0)
|
strncmp (entry->d_name, "core", 4) == 0)
|
||||||
|
@ -390,7 +388,7 @@ static MuError
|
||||||
process_dir_entry (const char* path, const char* mdir, struct dirent *entry,
|
process_dir_entry (const char* path, const char* mdir, struct dirent *entry,
|
||||||
MuMaildirWalkMsgCallback cb_msg,
|
MuMaildirWalkMsgCallback cb_msg,
|
||||||
MuMaildirWalkDirCallback cb_dir,
|
MuMaildirWalkDirCallback cb_dir,
|
||||||
void *data)
|
gboolean full, void *data)
|
||||||
{
|
{
|
||||||
const char *fp;
|
const char *fp;
|
||||||
char* fullpath;
|
char* fullpath;
|
||||||
|
@ -420,10 +418,9 @@ process_dir_entry (const char* path, const char* mdir, struct dirent *entry,
|
||||||
MuError rv;
|
MuError rv;
|
||||||
/* my_mdir is the search maildir (the dir starting
|
/* my_mdir is the search maildir (the dir starting
|
||||||
* with the top-level maildir as /, and without the
|
* with the top-level maildir as /, and without the
|
||||||
* /tmp, /cur, /new
|
* /tmp, /cur, /new */
|
||||||
*/
|
|
||||||
my_mdir = get_mdir_for_path (mdir, entry->d_name);
|
my_mdir = get_mdir_for_path (mdir, entry->d_name);
|
||||||
rv = process_dir (fullpath, my_mdir, cb_msg, cb_dir, data);
|
rv = process_dir (fullpath, my_mdir, cb_msg, cb_dir, full, data);
|
||||||
g_free (my_mdir);
|
g_free (my_mdir);
|
||||||
|
|
||||||
return rv;
|
return rv;
|
||||||
|
@ -470,7 +467,8 @@ dirent_cmp (struct dirent *d1, struct dirent *d2)
|
||||||
static MuError
|
static MuError
|
||||||
process_dir_entries (DIR *dir, const char* path, const char* mdir,
|
process_dir_entries (DIR *dir, const char* path, const char* mdir,
|
||||||
MuMaildirWalkMsgCallback msg_cb,
|
MuMaildirWalkMsgCallback msg_cb,
|
||||||
MuMaildirWalkDirCallback dir_cb, void *data)
|
MuMaildirWalkDirCallback dir_cb,
|
||||||
|
gboolean full, void *data)
|
||||||
{
|
{
|
||||||
MuError result;
|
MuError result;
|
||||||
GSList *lst, *c;
|
GSList *lst, *c;
|
||||||
|
@ -502,7 +500,7 @@ process_dir_entries (DIR *dir, const char* path, const char* mdir,
|
||||||
|
|
||||||
for (c = lst, result = MU_OK; c && result == MU_OK; c = g_slist_next(c))
|
for (c = lst, result = MU_OK; c && result == MU_OK; c = g_slist_next(c))
|
||||||
result = process_dir_entry (path, mdir, (struct dirent*)c->data,
|
result = process_dir_entry (path, mdir, (struct dirent*)c->data,
|
||||||
msg_cb, dir_cb, data);
|
msg_cb, dir_cb, full, data);
|
||||||
|
|
||||||
g_slist_foreach (lst, (GFunc)dirent_destroy, NULL);
|
g_slist_foreach (lst, (GFunc)dirent_destroy, NULL);
|
||||||
g_slist_free (lst);
|
g_slist_free (lst);
|
||||||
|
@ -513,22 +511,22 @@ process_dir_entries (DIR *dir, const char* path, const char* mdir,
|
||||||
|
|
||||||
static MuError
|
static MuError
|
||||||
process_dir (const char* path, const char* mdir,
|
process_dir (const char* path, const char* mdir,
|
||||||
MuMaildirWalkMsgCallback msg_cb,
|
MuMaildirWalkMsgCallback msg_cb, MuMaildirWalkDirCallback dir_cb,
|
||||||
MuMaildirWalkDirCallback dir_cb, void *data)
|
gboolean full, void *data)
|
||||||
{
|
{
|
||||||
MuError result;
|
MuError result;
|
||||||
DIR* dir;
|
DIR* dir;
|
||||||
|
|
||||||
/* if it has a noindex file, we ignore this dir */
|
/* if it has a noindex file, we ignore this dir */
|
||||||
if (has_noindex_file (path)) {
|
if (dir_contains_file (path, MU_MAILDIR_NOINDEX_FILE) ||
|
||||||
g_debug ("found .noindex: ignoring dir %s", path);
|
(!full && dir_contains_file (path, MU_MAILDIR_NOUPDATE_FILE))) {
|
||||||
|
g_debug ("found noindex/noupdate: ignoring dir %s", path);
|
||||||
return MU_OK;
|
return MU_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
dir = opendir (path);
|
dir = opendir (path);
|
||||||
if (G_UNLIKELY(!dir)) {
|
if (G_UNLIKELY(!dir)) {
|
||||||
g_warning ("%s: ignoring %s: %s", __FUNCTION__,
|
g_warning ("opendir failed %s: %s", path, strerror(errno));
|
||||||
path, strerror(errno));
|
|
||||||
return MU_OK;
|
return MU_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -541,7 +539,7 @@ process_dir (const char* path, const char* mdir,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
result = process_dir_entries (dir, path, mdir, msg_cb, dir_cb, data);
|
result = process_dir_entries (dir, path, mdir, msg_cb, dir_cb, full, data);
|
||||||
closedir (dir);
|
closedir (dir);
|
||||||
|
|
||||||
/* only run dir_cb if it exists and so far, things went ok */
|
/* only run dir_cb if it exists and so far, things went ok */
|
||||||
|
@ -554,7 +552,8 @@ process_dir (const char* path, const char* mdir,
|
||||||
|
|
||||||
MuError
|
MuError
|
||||||
mu_maildir_walk (const char *path, MuMaildirWalkMsgCallback cb_msg,
|
mu_maildir_walk (const char *path, MuMaildirWalkMsgCallback cb_msg,
|
||||||
MuMaildirWalkDirCallback cb_dir, void *data)
|
MuMaildirWalkDirCallback cb_dir, gboolean full,
|
||||||
|
void *data)
|
||||||
{
|
{
|
||||||
MuError rv;
|
MuError rv;
|
||||||
char *mypath;
|
char *mypath;
|
||||||
|
@ -567,7 +566,7 @@ mu_maildir_walk (const char *path, MuMaildirWalkMsgCallback cb_msg,
|
||||||
if (mypath[strlen(mypath)-1] == G_DIR_SEPARATOR)
|
if (mypath[strlen(mypath)-1] == G_DIR_SEPARATOR)
|
||||||
mypath[strlen(mypath)-1] = '\0';
|
mypath[strlen(mypath)-1] = '\0';
|
||||||
|
|
||||||
rv = process_dir (mypath, NULL, cb_msg, cb_dir, data);
|
rv = process_dir (mypath, NULL, cb_msg, cb_dir, full, data);
|
||||||
g_free (mypath);
|
g_free (mypath);
|
||||||
|
|
||||||
return rv;
|
return rv;
|
||||||
|
@ -617,8 +616,8 @@ clear_links (const gchar* dirname, DIR *dir, GError **err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (errno != 0)
|
if (errno != 0)
|
||||||
g_set_error (err, MU_ERROR_DOMAIN, MU_ERROR_FILE,
|
mu_util_g_set_error (err, MU_ERROR_FILE,
|
||||||
"file error: %s", strerror(errno));
|
"file error: %s", strerror(errno));
|
||||||
|
|
||||||
return (rv == FALSE && errno == 0);
|
return (rv == FALSE && errno == 0);
|
||||||
}
|
}
|
||||||
|
@ -633,12 +632,10 @@ mu_maildir_clear_links (const gchar* path, GError **err)
|
||||||
g_return_val_if_fail (path, FALSE);
|
g_return_val_if_fail (path, FALSE);
|
||||||
|
|
||||||
dir = opendir (path);
|
dir = opendir (path);
|
||||||
if (!dir) {
|
if (!dir)
|
||||||
g_set_error (err, MU_ERROR_DOMAIN, MU_ERROR_FILE_CANNOT_OPEN,
|
return mu_util_g_set_error (err, MU_ERROR_FILE_CANNOT_OPEN,
|
||||||
"failed to open %s: %s", path,
|
"failed to open %s: %s", path,
|
||||||
strerror(errno));
|
strerror(errno));
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
rv = clear_links (path, dir, err);
|
rv = clear_links (path, dir, err);
|
||||||
closedir (dir);
|
closedir (dir);
|
||||||
|
@ -790,29 +787,23 @@ mu_maildir_get_new_path (const char *oldpath, const char *new_mdir,
|
||||||
static gboolean
|
static gboolean
|
||||||
msg_move_check_pre (const gchar *src, const gchar *dst, GError **err)
|
msg_move_check_pre (const gchar *src, const gchar *dst, GError **err)
|
||||||
{
|
{
|
||||||
if (!g_path_is_absolute(src)) {
|
if (!g_path_is_absolute(src))
|
||||||
g_set_error (err, MU_ERROR_DOMAIN, MU_ERROR_FILE,
|
return mu_util_g_set_error
|
||||||
"source is not an absolute path: '%s'", src);
|
(err, MU_ERROR_FILE,
|
||||||
return FALSE;
|
"source is not an absolute path: '%s'", src);
|
||||||
}
|
|
||||||
|
|
||||||
if (!g_path_is_absolute(dst)) {
|
if (!g_path_is_absolute(dst))
|
||||||
g_set_error (err, MU_ERROR_DOMAIN, MU_ERROR_FILE,
|
return mu_util_g_set_error
|
||||||
"target is not an absolute path: '%s'", dst);
|
(err, MU_ERROR_FILE,
|
||||||
return FALSE;
|
"target is not an absolute path: '%s'", dst);
|
||||||
}
|
|
||||||
|
|
||||||
if (access (src, R_OK) != 0) {
|
if (access (src, R_OK) != 0)
|
||||||
g_set_error (err, MU_ERROR_DOMAIN, MU_ERROR_FILE, "cannot read %s",
|
return mu_util_g_set_error (err, MU_ERROR_FILE,
|
||||||
src);
|
"cannot read %s", src);
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (access (dst, F_OK) == 0) {
|
if (access (dst, F_OK) == 0)
|
||||||
g_set_error (err, MU_ERROR_DOMAIN, MU_ERROR_FILE, "%s already exists",
|
return mu_util_g_set_error (err, MU_ERROR_FILE,
|
||||||
dst);
|
"%s already exists", dst);
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
@ -821,17 +812,13 @@ static gboolean
|
||||||
msg_move_check_post (const char *src, const char *dst, GError **err)
|
msg_move_check_post (const char *src, const char *dst, GError **err)
|
||||||
{
|
{
|
||||||
/* double check -- is the target really there? */
|
/* double check -- is the target really there? */
|
||||||
if (access (dst, F_OK) != 0) {
|
if (access (dst, F_OK) != 0)
|
||||||
g_set_error (err, MU_ERROR_DOMAIN, MU_ERROR_FILE, "can't find target (%s)",
|
return mu_util_g_set_error
|
||||||
dst);
|
(err, MU_ERROR_FILE, "can't find target (%s)", dst);
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (access (src, F_OK) == 0) {
|
if (access (src, F_OK) == 0)
|
||||||
g_set_error (err, MU_ERROR_DOMAIN, MU_ERROR_FILE, "source is still there (%s)",
|
return mu_util_g_set_error
|
||||||
src);
|
(err, MU_ERROR_FILE, "source still there (%s)", src);
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
@ -843,16 +830,11 @@ msg_move (const char* src, const char *dst, GError **err)
|
||||||
if (!msg_move_check_pre (src, dst, err))
|
if (!msg_move_check_pre (src, dst, err))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
if (rename (src, dst) != 0) {
|
if (rename (src, dst) != 0)
|
||||||
g_set_error (err, MU_ERROR_DOMAIN, MU_ERROR_FILE, "error moving %s to %s",
|
return mu_util_g_set_error
|
||||||
src, dst);
|
(err, MU_ERROR_FILE,"error moving %s to %s", src, dst);
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!msg_move_check_post (src, dst, err))
|
return msg_move_check_post (src, dst, err);
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
return TRUE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
gchar*
|
gchar*
|
||||||
|
@ -869,18 +851,17 @@ mu_maildir_move_message (const char* oldpath, const char* targetmdir,
|
||||||
newfullpath = mu_maildir_get_new_path (oldpath, targetmdir,
|
newfullpath = mu_maildir_get_new_path (oldpath, targetmdir,
|
||||||
newflags);
|
newflags);
|
||||||
if (!newfullpath) {
|
if (!newfullpath) {
|
||||||
g_set_error (err, MU_ERROR_DOMAIN, MU_ERROR_FILE,
|
mu_util_g_set_error (err, MU_ERROR_FILE,
|
||||||
"failed to determine target full path");
|
"failed to determine targetpath");
|
||||||
return FALSE;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
src_is_target = (g_strcmp0 (oldpath, newfullpath) == 0);
|
src_is_target = (g_strcmp0 (oldpath, newfullpath) == 0);
|
||||||
|
|
||||||
if (!ignore_dups && src_is_target) {
|
if (!ignore_dups && src_is_target) {
|
||||||
g_set_error (err, MU_ERROR_DOMAIN, MU_ERROR_FILE_TARGET_EQUALS_SOURCE,
|
mu_util_g_set_error (err, MU_ERROR_FILE_TARGET_EQUALS_SOURCE,
|
||||||
"target equals source");
|
"target equals source");
|
||||||
return FALSE;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!src_is_target) {
|
if (!src_is_target) {
|
||||||
|
|
|
@ -96,7 +96,9 @@ typedef MuError (*MuMaildirWalkDirCallback)
|
||||||
* dotdirs are visited (ie. '.dotdir/cur'), so this enables Maildir++.
|
* dotdirs are visited (ie. '.dotdir/cur'), so this enables Maildir++.
|
||||||
* (http://www.inter7.com/courierimap/README.maildirquota.html, search
|
* (http://www.inter7.com/courierimap/README.maildirquota.html, search
|
||||||
* for 'Mission statement'). In addition, dirs containing a file named
|
* for 'Mission statement'). In addition, dirs containing a file named
|
||||||
* '.noindex' are ignored, as are their subdirectories.
|
* '.noindex' are ignored, as are their subdirectories, and dirs
|
||||||
|
* containing a file called '.noupdate' are ignored, unless @param
|
||||||
|
* full is TRUE.
|
||||||
*
|
*
|
||||||
* mu_walk_maildir stops if the callbacks return something different
|
* mu_walk_maildir stops if the callbacks return something different
|
||||||
* from MU_OK. For example, it can return MU_STOP to stop the scan, or
|
* from MU_OK. For example, it can return MU_STOP to stop the scan, or
|
||||||
|
@ -105,6 +107,7 @@ typedef MuError (*MuMaildirWalkDirCallback)
|
||||||
* @param path the maildir path to scan
|
* @param path the maildir path to scan
|
||||||
* @param cb_msg the callback function called for each msg
|
* @param cb_msg the callback function called for each msg
|
||||||
* @param cb_dir the callback function called for each dir
|
* @param cb_dir the callback function called for each dir
|
||||||
|
* @param full whether do a full scan, i.e., to ignore .noupdate files
|
||||||
* @param data user data pointer
|
* @param data user data pointer
|
||||||
*
|
*
|
||||||
* @return a scanner result; MU_OK if everything went ok,
|
* @return a scanner result; MU_OK if everything went ok,
|
||||||
|
@ -112,7 +115,8 @@ typedef MuError (*MuMaildirWalkDirCallback)
|
||||||
* case of error
|
* case of error
|
||||||
*/
|
*/
|
||||||
MuError mu_maildir_walk (const char *path, MuMaildirWalkMsgCallback cb_msg,
|
MuError mu_maildir_walk (const char *path, MuMaildirWalkMsgCallback cb_msg,
|
||||||
MuMaildirWalkDirCallback cb_dir, void *data);
|
MuMaildirWalkDirCallback cb_dir, gboolean full,
|
||||||
|
void *data);
|
||||||
/**
|
/**
|
||||||
* recursively delete all the symbolic links in a directory tree
|
* recursively delete all the symbolic links in a directory tree
|
||||||
*
|
*
|
||||||
|
|
|
@ -441,7 +441,7 @@ mu_util_fputs_encoded (const char *str, FILE *stream)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void
|
gboolean
|
||||||
mu_util_g_set_error (GError **err, MuError errcode, const char *frm, ...)
|
mu_util_g_set_error (GError **err, MuError errcode, const char *frm, ...)
|
||||||
{
|
{
|
||||||
va_list ap;
|
va_list ap;
|
||||||
|
@ -459,6 +459,8 @@ mu_util_g_set_error (GError **err, MuError errcode, const char *frm, ...)
|
||||||
g_set_error (err, MU_ERROR_DOMAIN, errcode, "%s", msg);
|
g_set_error (err, MU_ERROR_DOMAIN, errcode, "%s", msg);
|
||||||
|
|
||||||
g_free (msg);
|
g_free (msg);
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -439,13 +439,15 @@ typedef enum _MuError MuError;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* set an error if it's not already set
|
* set an error if it's not already set, and return FALSE
|
||||||
*
|
*
|
||||||
* @param err errptr, or NULL
|
* @param err errptr, or NULL
|
||||||
* @param errcode error code
|
* @param errcode error code
|
||||||
* @param frm printf-style format, followed by paremeters
|
* @param frm printf-style format, followed by paremeters
|
||||||
|
*
|
||||||
|
* @return FALSE
|
||||||
*/
|
*/
|
||||||
void mu_util_g_set_error (GError **err, MuError errcode, const char *frm, ...)
|
gboolean mu_util_g_set_error (GError **err, MuError errcode, const char *frm, ...)
|
||||||
G_GNUC_PRINTF(3,4);
|
G_GNUC_PRINTF(3,4);
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -256,6 +256,7 @@ test_mu_maildir_walk_01 (void)
|
||||||
rv = mu_maildir_walk (tmpdir,
|
rv = mu_maildir_walk (tmpdir,
|
||||||
(MuMaildirWalkMsgCallback)msg_cb,
|
(MuMaildirWalkMsgCallback)msg_cb,
|
||||||
(MuMaildirWalkDirCallback)dir_cb,
|
(MuMaildirWalkDirCallback)dir_cb,
|
||||||
|
TRUE,
|
||||||
&data);
|
&data);
|
||||||
|
|
||||||
g_assert_cmpuint (MU_OK, ==, rv);
|
g_assert_cmpuint (MU_OK, ==, rv);
|
||||||
|
@ -269,7 +270,7 @@ test_mu_maildir_walk_01 (void)
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
test_mu_maildir_walk_02 (void)
|
test_mu_maildir_walk (void)
|
||||||
{
|
{
|
||||||
char *tmpdir, *cmd, *dir;
|
char *tmpdir, *cmd, *dir;
|
||||||
WalkData data;
|
WalkData data;
|
||||||
|
@ -287,13 +288,13 @@ test_mu_maildir_walk_02 (void)
|
||||||
|
|
||||||
cmd = g_strdup_printf ("touch %s%c.noindex", dir, G_DIR_SEPARATOR);
|
cmd = g_strdup_printf ("touch %s%c.noindex", dir, G_DIR_SEPARATOR);
|
||||||
g_assert (g_spawn_command_line_sync (cmd, NULL, NULL, NULL, NULL));
|
g_assert (g_spawn_command_line_sync (cmd, NULL, NULL, NULL, NULL));
|
||||||
|
|
||||||
g_free (cmd);
|
g_free (cmd);
|
||||||
g_free (dir);
|
g_free (dir);
|
||||||
|
|
||||||
rv = mu_maildir_walk (tmpdir,
|
rv = mu_maildir_walk (tmpdir,
|
||||||
(MuMaildirWalkMsgCallback)msg_cb,
|
(MuMaildirWalkMsgCallback)msg_cb,
|
||||||
(MuMaildirWalkDirCallback)dir_cb,
|
(MuMaildirWalkDirCallback)dir_cb,
|
||||||
|
TRUE,
|
||||||
&data);
|
&data);
|
||||||
|
|
||||||
g_assert_cmpuint (MU_OK, ==, rv);
|
g_assert_cmpuint (MU_OK, ==, rv);
|
||||||
|
@ -305,6 +306,90 @@ test_mu_maildir_walk_02 (void)
|
||||||
g_free (tmpdir);
|
g_free (tmpdir);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_mu_maildir_walk_with_noupdate (void)
|
||||||
|
{
|
||||||
|
char *tmpdir, *cmd, *dir;
|
||||||
|
WalkData data;
|
||||||
|
MuError rv;
|
||||||
|
|
||||||
|
tmpdir = copy_test_data ();
|
||||||
|
|
||||||
|
/* mark the 'new' dir with '.noindex', to ignore it */
|
||||||
|
dir = g_strdup_printf ("%s%ctestdir%cnew", tmpdir,
|
||||||
|
G_DIR_SEPARATOR, G_DIR_SEPARATOR);
|
||||||
|
cmd = g_strdup_printf ("chmod 700 %s", dir);
|
||||||
|
g_assert (g_spawn_command_line_sync (cmd, NULL, NULL, NULL, NULL));
|
||||||
|
g_free (cmd);
|
||||||
|
|
||||||
|
memset (&data, 0, sizeof(WalkData));
|
||||||
|
rv = mu_maildir_walk (tmpdir,
|
||||||
|
(MuMaildirWalkMsgCallback)msg_cb,
|
||||||
|
(MuMaildirWalkDirCallback)dir_cb,
|
||||||
|
FALSE, /* ie., non-full update */
|
||||||
|
&data);
|
||||||
|
|
||||||
|
g_assert_cmpuint (MU_OK, ==, rv);
|
||||||
|
g_assert_cmpuint (data._file_count, ==, 17);
|
||||||
|
g_assert_cmpuint (data._dir_entered,==, 5);
|
||||||
|
g_assert_cmpuint (data._dir_left,==, 5);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* again, full update. results should be the same, since there
|
||||||
|
* is no noupdate yet */
|
||||||
|
memset (&data, 0, sizeof(WalkData));
|
||||||
|
rv = mu_maildir_walk (tmpdir,
|
||||||
|
(MuMaildirWalkMsgCallback)msg_cb,
|
||||||
|
(MuMaildirWalkDirCallback)dir_cb,
|
||||||
|
TRUE, /* ie., full update */
|
||||||
|
&data);
|
||||||
|
|
||||||
|
g_assert_cmpuint (MU_OK, ==, rv);
|
||||||
|
g_assert_cmpuint (data._file_count, ==, 17);
|
||||||
|
g_assert_cmpuint (data._dir_entered,==, 5);
|
||||||
|
g_assert_cmpuint (data._dir_left,==, 5);
|
||||||
|
|
||||||
|
/* add a '.noupdate' file; this affects the outcome when the
|
||||||
|
* 4th arg to mu_maildir_walk is FALSE */
|
||||||
|
cmd = g_strdup_printf ("touch %s%c.noupdate", dir, G_DIR_SEPARATOR);
|
||||||
|
g_assert (g_spawn_command_line_sync (cmd, NULL, NULL, NULL, NULL));
|
||||||
|
g_free (cmd);
|
||||||
|
|
||||||
|
memset (&data, 0, sizeof(WalkData));
|
||||||
|
rv = mu_maildir_walk (tmpdir,
|
||||||
|
(MuMaildirWalkMsgCallback)msg_cb,
|
||||||
|
(MuMaildirWalkDirCallback)dir_cb,
|
||||||
|
FALSE, /* non-full update */
|
||||||
|
&data);
|
||||||
|
|
||||||
|
g_assert_cmpuint (MU_OK, ==, rv);
|
||||||
|
g_assert_cmpuint (data._file_count, ==, 13);
|
||||||
|
|
||||||
|
g_assert_cmpuint (data._dir_entered,==, 4);
|
||||||
|
g_assert_cmpuint (data._dir_left,==, 4);
|
||||||
|
|
||||||
|
/* now run again, but do a full update */
|
||||||
|
memset (&data, 0, sizeof(WalkData));
|
||||||
|
rv = mu_maildir_walk (tmpdir,
|
||||||
|
(MuMaildirWalkMsgCallback)msg_cb,
|
||||||
|
(MuMaildirWalkDirCallback)dir_cb,
|
||||||
|
TRUE, /* full update */
|
||||||
|
&data);
|
||||||
|
|
||||||
|
g_assert_cmpuint (MU_OK, ==, rv);
|
||||||
|
g_assert_cmpuint (data._file_count, ==, 17);
|
||||||
|
|
||||||
|
g_assert_cmpuint (data._dir_entered,==, 5);
|
||||||
|
g_assert_cmpuint (data._dir_left,==, 5);
|
||||||
|
|
||||||
|
g_free (dir);
|
||||||
|
g_free (tmpdir);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -478,8 +563,10 @@ main (int argc, char *argv[])
|
||||||
/* mu_util_maildir_walk */
|
/* mu_util_maildir_walk */
|
||||||
g_test_add_func ("/mu-maildir/mu-maildir-walk-01",
|
g_test_add_func ("/mu-maildir/mu-maildir-walk-01",
|
||||||
test_mu_maildir_walk_01);
|
test_mu_maildir_walk_01);
|
||||||
g_test_add_func ("/mu-maildir/mu-maildir-walk-02",
|
g_test_add_func ("/mu-maildir/mu-maildir-walk",
|
||||||
test_mu_maildir_walk_02);
|
test_mu_maildir_walk);
|
||||||
|
g_test_add_func ("/mu-maildir/mu-maildir-walk-with-noupdate",
|
||||||
|
test_mu_maildir_walk_with_noupdate);
|
||||||
|
|
||||||
/* get/set flags */
|
/* get/set flags */
|
||||||
g_test_add_func("/mu-maildir/mu-maildir-get-new-path-01",
|
g_test_add_func("/mu-maildir/mu-maildir-get-new-path-01",
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
.TH MU-EASY 1 "January 2012" "User Manuals"
|
.TH MU-EASY 1 "May 2012" "User Manuals"
|
||||||
|
|
||||||
.SH NAME
|
.SH NAME
|
||||||
|
|
||||||
|
@ -45,7 +45,8 @@ Normally, \fBmu index\fR visits all the directories under the top-level
|
||||||
Maildir; however, you can exclude certain directories (say, the 'trash'
|
Maildir; however, you can exclude certain directories (say, the 'trash'
|
||||||
or 'spam' folders) by creating a file called \fI.noindex\fR in the directory.
|
or 'spam' folders) by creating a file called \fI.noindex\fR in the directory.
|
||||||
When \fBmu\fR sees such a file, it will exclude this directory and its
|
When \fBmu\fR sees such a file, it will exclude this directory and its
|
||||||
sub-directories from indexing.
|
sub-directories from indexing. Also see \fB.noupdate\fR in the \fBmu-index\fR
|
||||||
|
manpage.
|
||||||
|
|
||||||
.SH SEARCHING YOUR E-MAIL
|
.SH SEARCHING YOUR E-MAIL
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
.TH MU-INDEX 1 "May 2011" "User Manuals"
|
.TH MU-INDEX 1 "May 2012" "User Manuals"
|
||||||
|
|
||||||
.SH NAME
|
.SH NAME
|
||||||
|
|
||||||
mu index \- index e-mail messages stored in Maildirs
|
mu index \- index e-mail messages stored in Maildirs
|
||||||
|
|
||||||
|
@ -14,7 +14,7 @@ mu index \- index e-mail messages stored in Maildirs
|
||||||
directories and storing the results in a Xapian database. The data can then be
|
directories and storing the results in a Xapian database. The data can then be
|
||||||
queried using
|
queried using
|
||||||
.BR mu-find(1)
|
.BR mu-find(1)
|
||||||
\.
|
\.
|
||||||
|
|
||||||
.B index
|
.B index
|
||||||
understands Maildirs as defined by Daniel Bernstein for qmail(7). In addition,
|
understands Maildirs as defined by Daniel Bernstein for qmail(7). In addition,
|
||||||
|
@ -33,6 +33,12 @@ directory and all of its subdirectories will be ignored. This can be useful to
|
||||||
exclude certain directories from the indexing process, for example directories
|
exclude certain directories from the indexing process, for example directories
|
||||||
with spam-messages.
|
with spam-messages.
|
||||||
|
|
||||||
|
If there is a file called \fI.noupdate\fR in a directory, the contents of that
|
||||||
|
directory and all of its subdirectories will be ignored, unless we do a full
|
||||||
|
rebuild (with \fB--rebuild\fR). This can be useful to speed up things you have
|
||||||
|
some maildirs that never change. Note that you can still search for these
|
||||||
|
messages, this only affects updating the database.
|
||||||
|
|
||||||
The first run of \fBmu index\fR may take a few minutes if you have a lot of
|
The first run of \fBmu index\fR may take a few minutes if you have a lot of
|
||||||
mail (ten thousands of messages). Fortunately, such a full scan needs to be
|
mail (ten thousands of messages). Fortunately, such a full scan needs to be
|
||||||
done only once; after that it suffices to index the changes, which goes much
|
done only once; after that it suffices to index the changes, which goes much
|
||||||
|
|
Loading…
Reference in New Issue