* mu-maildir.[ch]: re-implement message flag parsing, message moving
This commit is contained in:
198
src/mu-msg.c
198
src/mu-msg.c
@ -680,199 +680,6 @@ mu_msg_is_readable (MuMsg *self)
|
||||
== 0) ? TRUE : FALSE;
|
||||
}
|
||||
|
||||
enum _MaildirType {
|
||||
MAILDIR_TYPE_CUR,
|
||||
MAILDIR_TYPE_NEW,
|
||||
MAILDIR_TYPE_OTHER
|
||||
};
|
||||
typedef enum _MaildirType MaildirType;
|
||||
|
||||
static MaildirType
|
||||
get_maildir_type (const char *path)
|
||||
{
|
||||
MaildirType mtype;
|
||||
gchar *dirname;
|
||||
|
||||
dirname = g_path_get_dirname (path);
|
||||
/* g_path_get_dirname does not specify if the name includes
|
||||
* the closing '/'... if it does, remove it */
|
||||
if (dirname[strlen(dirname) - 1 ] == G_DIR_SEPARATOR)
|
||||
dirname[strlen(dirname) - 1] = '\0';
|
||||
|
||||
if (g_str_has_suffix (dirname, "cur"))
|
||||
mtype = MAILDIR_TYPE_CUR;
|
||||
else if (g_str_has_suffix (dirname, "new"))
|
||||
mtype = MAILDIR_TYPE_NEW;
|
||||
else
|
||||
mtype = MAILDIR_TYPE_OTHER;
|
||||
|
||||
g_free (dirname);
|
||||
|
||||
return mtype;
|
||||
}
|
||||
|
||||
char*
|
||||
get_new_fullpath (const char *oldpath, const char *targetmdir,
|
||||
MaildirType mtype, MuFlags flags)
|
||||
{
|
||||
char *filename, *newfullpath;
|
||||
const char* mdirsub;
|
||||
|
||||
filename = g_path_get_basename (oldpath);
|
||||
|
||||
if (mtype == MAILDIR_TYPE_CUR)
|
||||
mdirsub = "cur";
|
||||
else if (mtype == MAILDIR_TYPE_NEW)
|
||||
mdirsub = "new";
|
||||
else {
|
||||
g_free (filename);
|
||||
g_return_val_if_reached (NULL);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
newfullpath = g_strdup_printf ("%s%c%s%c%s",
|
||||
targetmdir,
|
||||
G_DIR_SEPARATOR,
|
||||
mdirsub,
|
||||
G_DIR_SEPARATOR,
|
||||
filename);
|
||||
g_free (filename);
|
||||
|
||||
/* we update the filename for the new flags; in case the NEW
|
||||
* flag is set/unset, this can also influence the dir */
|
||||
if (flags != MU_FLAG_NONE) {
|
||||
gchar *tmp;
|
||||
tmp = mu_maildir_get_path_from_flags (newfullpath, flags);
|
||||
g_free (newfullpath);
|
||||
newfullpath = tmp;
|
||||
}
|
||||
|
||||
return newfullpath;
|
||||
}
|
||||
|
||||
|
||||
static gboolean
|
||||
msg_move (const char* oldpath, const char *newfullpath, GError **err)
|
||||
{
|
||||
if (access (oldpath, R_OK) != 0) {
|
||||
g_set_error (err, 0, MU_ERROR_FILE, "cannot read %s",
|
||||
oldpath);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
if (access (newfullpath, F_OK) == 0) {
|
||||
g_set_error (err, 0, MU_ERROR_FILE, "%s already exists",
|
||||
newfullpath);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (rename (oldpath, newfullpath) != 0) {
|
||||
g_set_error (err, 0, MU_ERROR_FILE, "error moving %s to %s",
|
||||
oldpath, newfullpath);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* double check -- is the target really there? */
|
||||
if (access (newfullpath, F_OK) != 0) {
|
||||
g_set_error (err, 0, MU_ERROR_FILE, "can't find target (%s)",
|
||||
newfullpath);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (access (oldpath, F_OK) == 0) {
|
||||
g_set_error (err, 0, MU_ERROR_FILE, "source is still there (%s)",
|
||||
oldpath);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
static gboolean
|
||||
check_source_file (const char *src, MaildirType *mtype, GError **err)
|
||||
{
|
||||
if (!g_path_is_absolute(src)) {
|
||||
g_set_error (err, 0, MU_ERROR_FILE,
|
||||
"source is not an absolute path: '%s'", src);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
*mtype = get_maildir_type (src);
|
||||
if (*mtype != MAILDIR_TYPE_CUR && *mtype != MAILDIR_TYPE_NEW) {
|
||||
g_set_error (err, 0, MU_ERROR_FILE,
|
||||
"source is not in a maildir: '%s'", src);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
check_target_dir (const char* targetmdir, GError **err)
|
||||
{
|
||||
if (!g_path_is_absolute(targetmdir)) {
|
||||
g_set_error (err, 0, MU_ERROR_FILE,
|
||||
"target is not an absolute path: '%s'", targetmdir);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!mu_util_check_dir (targetmdir, TRUE, TRUE)) {
|
||||
g_set_error (err, 0, MU_ERROR_FILE,
|
||||
"target is not a read-writable dir: '%s'", targetmdir);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* move a msg to another maildir, trying to maintain 'integrity',
|
||||
* ie. msg in 'new/' will go to new/, one in cur/ goes to cur/. be
|
||||
* super-paranoid here...
|
||||
*/
|
||||
gchar*
|
||||
mu_msg_file_move_to_maildir (const char* oldpath, const char* targetmdir,
|
||||
MuFlags flags, GError **err)
|
||||
{
|
||||
MaildirType mtype;
|
||||
char *newfullpath;
|
||||
gboolean rv;
|
||||
|
||||
g_return_val_if_fail (oldpath, FALSE);
|
||||
g_return_val_if_fail (targetmdir, FALSE);
|
||||
|
||||
if (!check_source_file (oldpath, &mtype, err))
|
||||
return FALSE;
|
||||
|
||||
if (!check_target_dir (targetmdir, err))
|
||||
return FALSE;
|
||||
|
||||
newfullpath = get_new_fullpath (oldpath, targetmdir, mtype, flags);
|
||||
if (!newfullpath) {
|
||||
g_set_error (err, 0, MU_ERROR_FILE,
|
||||
"failed to determine target full path");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (g_strcmp0 (oldpath, newfullpath) == 0) {
|
||||
g_set_error (err, 0, MU_ERROR_FILE,
|
||||
"target equals source");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
rv = msg_move (oldpath, newfullpath, err);
|
||||
if (!rv) {
|
||||
g_free (newfullpath);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return newfullpath;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* move a msg to another maildir, trying to maintain 'integrity',
|
||||
* ie. msg in 'new/' will go to new/, one in cur/ goes to cur/. be
|
||||
@ -885,10 +692,9 @@ mu_msg_move_to_maildir (MuMsg *self, const char* targetmdir,
|
||||
char *newfullpath;
|
||||
|
||||
g_return_val_if_fail (self, FALSE);
|
||||
g_return_val_if_fail (targetmdir, FALSE);
|
||||
|
||||
newfullpath = mu_msg_file_move_to_maildir (mu_msg_get_path (self),
|
||||
targetmdir, flags, err);
|
||||
newfullpath = mu_maildir_move_message (mu_msg_get_path (self),
|
||||
targetmdir, flags, err);
|
||||
if (newfullpath) /* update our path to new one... */
|
||||
mu_msg_cache_set_str (self->_cache, MU_MSG_FIELD_ID_PATH, newfullpath,
|
||||
TRUE); /* the cache will free the string */
|
||||
|
||||
Reference in New Issue
Block a user