/* GNU Mailutils -- a suite of utilities for electronic mail
Copyright (C) 2010-2021 Free Software Foundation, Inc.
GNU Mailutils is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3, or (at your option)
any later version.
GNU Mailutils is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Mailutils. If not, see . */
#if defined(HAVE_CONFIG_H)
# include
#endif
#include
#include
#include "mu.h"
#include "muaux.h"
/* Utility-specific exit codes */
enum
{
EXIT_OK, /* Success */
EXIT_HARDFAIL, /* None of the maildirs fixed */
EXIT_SOFTFAIL, /* Some of the maildirs failed to fix */
};
static int verbose_option;
static int dry_run_option;
static unsigned long fail_count;
static unsigned long succ_count;
static struct mu_option options[] =
{
{ "verbose", 'v', NULL, MU_OPTION_DEFAULT,
"verbosely list what is being done",
mu_c_incr, &verbose_option },
{ "dry-run", 'n', NULL, MU_OPTION_DEFAULT,
"do nothing, print everything",
mu_c_incr, &dry_run_option },
MU_OPTION_END
};
static int
mailbox_fixup (void *item, void *data)
{
struct mu_list_response *resp = item;
mu_mailbox_t mbox = NULL;
int rc;
if (!(resp->type & MU_FOLDER_ATTRIBUTE_FILE))
return 0;
if (verbose_option)
mu_diag_output (MU_DIAG_INFO, "Fixing %s", resp->name);
if (dry_run_option)
return 0;
rc = manlock_open_mailbox (&mbox, resp->name, 1, MU_STREAM_RDWR);
if (rc == 0)
{
rc = mu_mailbox_scan (mbox, 1, NULL);
mu_mailbox_close (mbox);
manlock_unlock (mbox);
mu_mailbox_destroy (&mbox);
}
else
mu_error ("can't open mailbox: %s", mu_strerror (rc));
if (rc)
fail_count++;
else
succ_count++;
return 0;
}
static inline int
filename_ok (char const *fname)
{
return fname[0] == '/' ||
fname[0] == '~' ||
(fname[0] == '.' &&
(fname[1] == '/' || (fname[1] == '.' && fname[2] == '/')));
}
static int
fix_mailboxes_in_folder (char *fname)
{
mu_folder_t folder;
struct mu_folder_scanner scn = MU_FOLDER_SCANNER_INITIALIZER;
int rc;
if (!filename_ok (fname))
{
char *cwd = mu_getcwd ();
size_t prefix_len = strlen (cwd);
if (cwd[prefix_len-1] != '/')
prefix_len++;
fname = mu_make_file_name (cwd, fname);
free (cwd);
if (!fname)
mu_alloc_die ();
}
rc = mu_folder_create (&folder, fname);
if (rc)
{
mu_diag_funcall (MU_DIAG_ERROR, "mu_folder_create", fname, rc);
return rc;
}
rc = mu_folder_open (folder, MU_STREAM_READ);
if (rc)
{
mu_diag_funcall (MU_DIAG_ERROR, "mu_folder_open", fname, rc);
goto err;
}
rc = mu_list_create (&scn.result);
if (rc)
{
mu_diag_funcall (MU_DIAG_ERROR, "mu_list_create", NULL, rc);
goto err;
}
rc = mu_folder_scan (folder, &scn);
if (rc)
mu_diag_funcall (MU_DIAG_ERROR, "mu_folder_scan", NULL, rc);
else
mu_list_foreach (scn.result, mailbox_fixup, NULL);
err:
mu_list_destroy (&scn.result);
mu_folder_destroy (&folder);
return rc;
}
static char docstring[] = N_(
"recursively scans all maildirs in the folder\n"
"\nThis induces fixing of the maildir message attributes (bug #56428) "
"and attaching persistent UID numbers (commits fd9b19bac-d7110faa).\n"
);
static char argdoc[] = N_("FOLDER ...");
static char *capa[] = {
"debug",
"locking",
NULL
};
static struct mu_cfg_param config_param[] = {
{ "mandatory-locking", mu_cfg_section },
{ NULL }
};
int
main (int argc, char **argv)
{
int i;
mu_registrar_record (mu_maildir_record);
mu_registrar_set_default_scheme ("maildir");
manlock_cfg_init ();
mu_cli_simple (argc, argv,
MU_CLI_OPTION_OPTIONS, options,
MU_CLI_OPTION_OPTIONS, common_options,
MU_CLI_OPTION_PROG_NAME, getenv ("MAILUTILS_PROGNAME"),
MU_CLI_OPTION_PROG_DOC, docstring,
MU_CLI_OPTION_PROG_ARGS, argdoc,
MU_CLI_OPTION_RETURN_ARGC, &argc,
MU_CLI_OPTION_RETURN_ARGV, &argv,
MU_CLI_OPTION_PACKAGE_NAME, PACKAGE_NAME,
MU_CLI_OPTION_PACKAGE_URL, PACKAGE_URL,
MU_CLI_OPTION_BUG_ADDRESS, PACKAGE_BUGREPORT,
MU_CLI_OPTION_VERSION_HOOK, mu_version_hook,
MU_CLI_OPTION_CAPABILITIES, capa,
MU_CLI_OPTION_CONFIG, config_param,
MU_CLI_OPTION_CONF_SITE_FILE, NULL,
MU_CLI_OPTION_CONF_PROGNAME, "maildir_fixup",
MU_CLI_OPTION_END);
if (argc == 0)
{
mu_error ("required argument missing; try --help for more info");
exit (EX_USAGE);
}
if (dry_run_option)
verbose_option++;
for (i = 0; i < argc; i++)
fix_mailboxes_in_folder (argv[i]);
if (fail_count)
exit (succ_count == 0 ? EXIT_HARDFAIL : EXIT_SOFTFAIL);
exit (EXIT_OK);
}