remap.cc (fstransform-0.9.3-src) | : | remap.cc (fstransform-0.9.4) | ||
---|---|---|---|---|
/* | /* | |||
* fstransform - transform a file-system to another file-system type, | * fstransform - transform a file-system to another file-system type, | |||
* preserving its contents and without the need for a backup | * preserving its contents and without the need for a backup | |||
* | * | |||
* Copyright (C) 2011-2012 Massimiliano Ghilardi | * Copyright (C) 2011-2017 Massimiliano Ghilardi | |||
* | * | |||
* This program is free software: you can redistribute it and/or modify | * 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 | * it under the terms of the GNU General Public License as published by | |||
* the Free Software Foundation, either version 3 of the License, or | * the Free Software Foundation, either version 3 of the License, or | |||
* (at your option) any later version. | * (at your option) any later version. | |||
* | * | |||
* This program is distributed in the hope that it will be useful, | * This program is distributed in the hope that it will be useful, | |||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
* GNU General Public License for more details. | * GNU General Public License for more details. | |||
skipping to change at line 40 | skipping to change at line 40 | |||
#elif defined(FT_HAVE_CSTRING) | #elif defined(FT_HAVE_CSTRING) | |||
# include <cstring> // for strcmp() | # include <cstring> // for strcmp() | |||
#endif | #endif | |||
#if defined(FT_HAVE_STRING_H) | #if defined(FT_HAVE_STRING_H) | |||
# include <stdlib.h> // for atoi() | # include <stdlib.h> // for atoi() | |||
#elif defined(FT_HAVE_CSTRING) | #elif defined(FT_HAVE_CSTRING) | |||
# include <cstdlib> // for atoi() | # include <cstdlib> // for atoi() | |||
#endif | #endif | |||
#include "log.hh" // for ff_log() | #include "log.hh" // for ff_log() | |||
#include "map.hh" // for fr_map<T> | #include "map.hh" // for fr_map<T> | |||
#include "vector.hh" // for fr_vector<T> | #include "vector.hh" // for fr_vector<T> | |||
#include "dispatch.hh" // for fr_dispatch | #include "dispatch.hh" // for fr_dispatch | |||
#include "remap.hh" // for fr_remap | #include "remap.hh" // for fr_remap | |||
#include "misc.hh" // for ff_strtoul() | #include "misc.hh" // for ff_strtoul() | |||
#include "io/io.hh" // for fr_io | #include "io/io.hh" // for fr_io | |||
#include "io/io_posix.hh" // for fr_io_posix | #include "io/io_posix.hh" // for fr_io_posix | |||
#ifdef FT_HAVE_IO_PREALLOC | ||||
# include "io/io_prealloc.hh" // for fr_io_prealloc | ||||
#endif | ||||
#include "io/io_self_test.hh" // for fr_io_self_test | #include "io/io_self_test.hh" // for fr_io_self_test | |||
#include "io/util.hh" // for ff_mkdir() | #include "io/util_dir.hh" // for ff_mkdir() | |||
FT_NAMESPACE_BEGIN | FT_NAMESPACE_BEGIN | |||
enum { | enum { | |||
FC_DEVICE = FT_IO_NS fr_io_posix::FC_DEVICE, | FC_DEVICE = FT_IO_NS fr_io_posix::FC_DEVICE, | |||
FC_LOOP_FILE = FT_IO_NS fr_io_posix::FC_LOOP_FILE, | FC_LOOP_FILE = FT_IO_NS fr_io_posix::FC_LOOP_FILE, | |||
FC_FILE_COUNT = FT_IO_NS fr_io_posix::FC_FILE_COUNT | FC_FILE_COUNT = FT_IO_NS fr_io_posix::FC_FILE_COUNT | |||
}; | }; | |||
static char const* const* label = FT_IO_NS fr_io::label; | static char const* const* label = FT_IO_NS fr_io::label; | |||
skipping to change at line 110 | skipping to change at line 113 | |||
return err; | return err; | |||
} | } | |||
/** print command-line usage to stdout and return 0 */ | /** print command-line usage to stdout and return 0 */ | |||
int fr_remap::usage(const char * program_name) | int fr_remap::usage(const char * program_name) | |||
{ | { | |||
quit_immediately = true; | quit_immediately = true; | |||
ff_log(FC_NOTICE, 0, "Usage: %s [OPTION]... %s %s [%s]", program_name, LABEL [0], LABEL[1], LABEL[2]); | ff_log(FC_NOTICE, 0, "Usage: %s [OPTION]... %s %s [%s]", program_name, LABEL [0], LABEL[1], LABEL[2]); | |||
ff_log(FC_NOTICE, 0, " or: %s [OPTION]... --resume-job=JOB_ID %s", program _name, LABEL[0]); | ff_log(FC_NOTICE, 0, " or: %s [OPTION]... --resume-job=JOB_ID %s", program _name, LABEL[FC_DEVICE]); | |||
ff_log(FC_NOTICE, 0, "Replace the contents of %s with the contents of %s, i. e. write %s onto %s", | ff_log(FC_NOTICE, 0, "Replace the contents of %s with the contents of %s, i. e. write %s onto %s", | |||
LABEL[FC_DEVICE], LABEL[FC_LOOP_FILE], LABEL[FC_LOOP_FILE], LABEL[FC _DEVICE]); | LABEL[FC_DEVICE], LABEL[FC_LOOP_FILE], LABEL[FC_LOOP_FILE], LABEL[FC _DEVICE]); | |||
ff_log(FC_NOTICE, 0, "even if %s is inside a file system _inside_ %s\n", LAB EL[FC_LOOP_FILE], LABEL[FC_DEVICE]); | ff_log(FC_NOTICE, 0, "even if %s is inside a file system _inside_ %s\n", LAB EL[FC_LOOP_FILE], LABEL[FC_DEVICE]); | |||
return ff_log | return ff_log | |||
(FC_NOTICE, 0, "Mandatory arguments to long options are mandatory for short options too.\n" | (FC_NOTICE, 0, "Mandatory arguments to long options are mandatory for short options too.\n" | |||
" -- end of options. treat subsequent parameters as arg uments\n" | " -- end of options. treat subsequent parameters as arg uments\n" | |||
" even if they start with '-'\n" | " even if they start with '-'\n" | |||
" -a, --no-questions automatic run: do not ask any question\n" | " -a, --no-questions automatic run: do not ask any question\n" | |||
" --clear=all clear all free blocks after remapping (default)\n" | " --clear=all clear all free blocks after remapping (default)\n" | |||
" --clear=minimal (DANGEROUS) clear only overwritten free blocks\n" | " --clear=minimal (DANGEROUS) clear only overwritten free blocks\n" | |||
" after remapping\n" | " after remapping\n" | |||
" --clear=none (DANGEROUS) do not clear any free blocks after rem apping\n" | " --clear=none (DANGEROUS) do not clear any free blocks after rem apping\n" | |||
" --cmd-umount=CMD command to unmount %s (default: /bin/umount)\n" | " --cmd-umount=CMD command to unmount %s (default: /bin/umount)\n" | |||
" --cmd-losetup=CMD 'losetup' command (default: /sbin/losetup)\n" | ||||
" --color=MODE set messages color. MODE is one of:\n" | ||||
" auto (default), none, ansi\n" | ||||
#ifdef FT_HAVE_IO_PREALLOC | ||||
" --device-mount-point=DIR\n" | ||||
" set device mount point (needed by --io=prealloc)\n | ||||
" | ||||
#endif | ||||
" -f, --force-run continue even if some sanity checks fail\n" | " -f, --force-run continue even if some sanity checks fail\n" | |||
" -i, --interactive ask confirmation after analysis, before actual wor k\n" | ||||
" --io=posix use posix I/O (default)\n" | " --io=posix use posix I/O (default)\n" | |||
#ifdef FT_HAVE_IO_PREALLOC | ||||
" --io=prealloc use posix I/O with EXPERIMENTAL preallocated files | ||||
\n" | ||||
#endif | ||||
" --io=self-test perform in-memory self-test with random data\n" | " --io=self-test perform in-memory self-test with random data\n" | |||
" --io=test use test I/O. Arguments are:\n" | " --io=test use test I/O. Arguments are:\n" | |||
" DEVICE-LENGTH LOOP-FILE-EXTENTS FREE-SPACE-EXTEN TS\n" | " DEVICE-LENGTH LOOP-FILE-EXTENTS FREE-SPACE-EXTEN TS\n" | |||
#ifdef FT_HAVE_IO_PREALLOC | ||||
" --loop-device=LOOP-DEVICE\n" | ||||
" loop device to disconnect (needed by --io=prealloc | ||||
)\n" | ||||
" --loop-mount-point=DIR\n" | ||||
" set loop file mount point (needed by --io=prealloc | ||||
)\n" | ||||
#endif | ||||
" -m, --mem-buffer=RAM_SIZE[k|M|G|T|P|E|Z|Y]\n" | " -m, --mem-buffer=RAM_SIZE[k|M|G|T|P|E|Z|Y]\n" | |||
" set RAM buffer size (default: autodetect)\n" | " set RAM buffer size (default: autodetect)\n" | |||
" -n, --no-action, --simulate-run\n" | " -n, --no-action, --simulate-run\n" | |||
" do not actually read or write any disk block\n" | " do not actually read or write any disk block\n" | |||
" --questions=MODE set interactive mode. MODE is one of:\n" | ||||
" no: never ask questions, abort on errors (defaul | ||||
t)\n" | ||||
" yes: ask questions in case of user-fixable error | ||||
s\n" | ||||
" extra: also ask confirmation before dangerous st | ||||
eps\n" | ||||
" -q, --quiet be quiet, print less output\n" | " -q, --quiet be quiet, print less output\n" | |||
" -qq be very quiet, only print warnings or errors\n" | " -qq be very quiet, only print warnings or errors\n" | |||
" --resume-job=NUM resume an interrupted job\n" | " --resume-job=NUM resume the interrupted job NUM. The only non-optio | |||
n\n" | ||||
" argument must be %s. Do _not_ pass %s\n" | ||||
" as argument, or you will LOSE YOUR DATA!\n" | ||||
" -s, --secondary-storage=SECONDARY_SIZE[k|M|G|T|P|E|Z|Y]\n" | " -s, --secondary-storage=SECONDARY_SIZE[k|M|G|T|P|E|Z|Y]\n" | |||
" set secondary storage file length (default: autode tect)\n" | " set secondary storage file length (default: autode tect)\n" | |||
" -t, --temp-dir=DIR write storage and log files inside DIR\n" | " -t, --temp-dir=DIR write storage and log files inside DIR\n" | |||
" (default: /var/tmp/fstransform)\n" | " (default: /var/tmp/fstransform)\n" | |||
" --ui-tty=TTY show full-text progress on tty device TTY\n" | " --ui-tty=TTY show full-text progress on tty device TTY\n" | |||
" -v, --verbose be verbose\n" | " -v, --verbose be verbose\n" | |||
" -vv be very verbose\n" | " -vv be very verbose\n" | |||
" -vvv be incredibly verbose (warning: prints lots of out put)\n" | " -vvv be incredibly verbose (warning: prints lots of out put)\n" | |||
" -xp, --exact-primary-storage=PRIMARY_SIZE[k|M|G|T|P|E|Z|Y]\n" | " -xp, --exact-primary-storage=PRIMARY_SIZE[k|M|G|T|P|E|Z|Y]\n" | |||
" set *exact* primary storage length, or fail\n" | " set _exact_ primary storage length, or fail\n" | |||
" (default: autodetect)\n" | " (default: autodetect)\n" | |||
" -xs, --exact-secondary-storage=SECONDARY_SIZE[k|M|G|T|P|E|Z|Y]\n" | " -xs, --exact-secondary-storage=SECONDARY_SIZE[k|M|G|T|P|E|Z|Y]\n" | |||
" set *exact* secondary storage length, or fail\n" | " set _exact_ secondary storage length, or fail\n" | |||
" (default: autodetect)\n" | " (default: autodetect)\n" | |||
" --x-OPTION=VALUE set internal, undocumented option. for maintainers | " --x-OPTION=VALUE set internal, undocumented option. for maintainers | |||
only\n" | only\n" | |||
" --help display this help and exit\n" | " --help display this help and exit\n" | |||
" --version output version information and exit\n", | " --version output version information and exit\n", | |||
label[FC_DEVICE]); | LABEL[FC_DEVICE], LABEL[FC_DEVICE], LABEL[FC_LOOP_FILE]); | |||
} | } | |||
/** output version information and return 0 */ | /** output version information and return 0 */ | |||
int fr_remap::version() | int fr_remap::version() | |||
{ | { | |||
quit_immediately = true; | quit_immediately = true; | |||
return ff_log(FC_NOTICE, 0, | return ff_log(FC_NOTICE, 0, | |||
"fsremap (fstransform utilities) " FT_VERSION "\n" | "fsremap (fstransform utilities) " FT_VERSION "\n" | |||
"Copyright (C) 2011-2012 Massimiliano Ghilardi\n" | "Copyright (C) 2011-2017 Massimiliano Ghilardi\n" | |||
"\n" | "\n" | |||
"License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses /gpl.html>.\n" | "License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses /gpl.html>.\n" | |||
"This is free software: you are free to change and redistribute it.\ n" | "This is free software: you are free to change and redistribute it.\ n" | |||
"There is NO WARRANTY, to the extent permitted by law.\n"); | "There is NO WARRANTY, to the extent permitted by law.\n"); | |||
} | } | |||
int fr_remap::invalid_cmdline(const fr_args & args, int err, const char * fmt, . ..) | int fr_remap::invalid_cmdline(const fr_args & args, int err, const char * fmt, . ..) | |||
{ | { | |||
va_list vargs; | va_list vargs; | |||
skipping to change at line 231 | skipping to change at line 257 | |||
/** | /** | |||
* parse from command line and initialize all subsystems (job, I/O, log...) | * parse from command line and initialize all subsystems (job, I/O, log...) | |||
* return 0 if success, else error. | * return 0 if success, else error. | |||
* | * | |||
* implementation: parse command line, fill a fr_args and call init(const fr_arg s &) | * implementation: parse command line, fill a fr_args and call init(const fr_arg s &) | |||
*/ | */ | |||
int fr_remap::init(int argc, char const* const* argv) | int fr_remap::init(int argc, char const* const* argv) | |||
{ | { | |||
fr_args args; | fr_args args; | |||
int err; | int err; | |||
ft_log_level level = FC_INFO, new_level; | ||||
fr_io_kind io_kind; | fr_io_kind io_kind; | |||
fr_clear_free_space new_clear; | fr_clear_free_space new_clear; | |||
ft_log_fmt format = FC_FMT_MSG; | ||||
ft_log_level level = FC_INFO, new_level; | ||||
ft_log_color color = FC_COL_AUTO; | ||||
bool format_set = false; | ||||
do { | do { | |||
if ((err = check_is_closed()) != 0) | if ((err = check_is_closed()) != 0) | |||
break; | break; | |||
if (argc == 0) { | if (argc == 0) { | |||
err = invalid_cmdline(args, 0, "missing arguments: %s %s [%s]", LABE L[0], LABEL[1], LABEL[2]); | err = invalid_cmdline(args, 0, "missing arguments: %s %s [%s]", LABE L[0], LABEL[1], LABEL[2]); | |||
break; | break; | |||
} | } | |||
skipping to change at line 264 | skipping to change at line 293 | |||
ft_size opt_len = ff_str_index_of_plus_1(arg, '='); | ft_size opt_len = ff_str_index_of_plus_1(arg, '='); | |||
bool is_short_opt = arg[1] != '-'; | bool is_short_opt = arg[1] != '-'; | |||
const char * opt_arg = argc > 1 && is_short_opt ? argv[1] : arg + opt_len; | const char * opt_arg = argc > 1 && is_short_opt ? argv[1] : arg + opt_len; | |||
/* -- means end of options*/ | /* -- means end of options*/ | |||
if (!strcmp(arg, "--")) | if (!strcmp(arg, "--")) | |||
allow_opts = false; | allow_opts = false; | |||
/* -a, --no-questions: run automatically without asking any conf irmation */ | /* -a, --no-questions run automatically without asking any confi rmation */ | |||
else if (!strcmp(arg, "-a") || !strcmp(arg, "--no-questions")) { | else if (!strcmp(arg, "-a") || !strcmp(arg, "--no-questions")) { | |||
args.ask_questions = false; | args.ask_questions = false; | |||
} | } | |||
/* --clear=all, --clear=minimal, --clear=none */ | /* --clear=all, --clear=minimal, --clear=none */ | |||
else if ((new_clear = FC_CLEAR_ALL, !strcmp(arg, "--clear=all" )) | else if ((new_clear = FC_CLEAR_ALL, !strcmp(arg, "--clear=all" )) | |||
|| (new_clear = FC_CLEAR_MINIMAL, !strcmp(arg, "--clear=mini mal")) | || (new_clear = FC_CLEAR_MINIMAL, !strcmp(arg, "--clear=mini mal")) | |||
|| (new_clear = FC_CLEAR_NONE, !strcmp(arg, "--clear=none "))) { | || (new_clear = FC_CLEAR_NONE, !strcmp(arg, "--clear=none "))) { | |||
if (args.job_clear == FC_CLEAR_AUTODETECT) | if (args.job_clear == FC_CLEAR_AUTODETECT) | |||
args.job_clear = new_clear; | args.job_clear = new_clear; | |||
else | else | |||
err = invalid_cmdline(args, 0, | err = invalid_cmdline(args, 0, | |||
"options --clear=all, --clear=minimal and --clea r=none are mutually exclusive"); | "options --clear=all, --clear=minimal and --clea r=none are mutually exclusive"); | |||
} | } | |||
/* --cmd-losetup=CMD */ | ||||
else if (!strncmp(arg, "--cmd-losetup=", opt_len)) { | ||||
args.cmd_losetup = opt_arg; | ||||
} | ||||
/* --cmd-umount=CMD */ | /* --cmd-umount=CMD */ | |||
else if (!strncmp(arg, "--cmd-umount=", opt_len)) { | else if (!strncmp(arg, "--cmd-umount=", opt_len)) { | |||
args.umount_cmd = opt_arg; | args.cmd_umount = opt_arg; | |||
} | } | |||
/* -f, --force-run: consider failed sanity checks as WARNINGS (w hich let execution continue) instead of ERRORS (which stop execution) */ | /* -f, --force-run: consider failed sanity checks as WARNINGS (w hich let execution continue) instead of ERRORS (which stop execution) */ | |||
else if (!strcmp(arg, "-f") || !strcmp(arg, "--force-run")) { | else if (!strcmp(arg, "-f") || !strcmp(arg, "--force-run")) { | |||
args.force_run = true; | args.force_run = true; | |||
} | } | |||
/* --io=posix, --io=test, --io=self-test */ | /* -i, --interactive: ask confirmation after analysis, before st | |||
else if ((io_kind = FC_IO_POSIX, !strcmp(arg, "--io=posix")) | arting real work */ | |||
|| (io_kind = FC_IO_TEST, !strcmp(arg, "--io=test")) | else if (!strcmp(arg, "-i") || !strcmp(arg, "--interactive")) { | |||
|| (io_kind = FC_IO_SELF_TEST, !strcmp(arg, "--io=self-test" | args.ask_questions = true; | |||
))) | } | |||
/* --io=test, --io=self-test, --io=posix, --io=prealloc */ | ||||
else if ((io_kind = FC_IO_TEST, !strcmp(arg, "--io=test") | ||||
) | ||||
|| (io_kind = FC_IO_SELF_TEST, !strcmp(arg, "--io=self-t | ||||
est")) | ||||
|| (io_kind = FC_IO_POSIX, !strcmp(arg, "--io=posix" | ||||
)) | ||||
#ifdef FT_HAVE_IO_PREALLOC | ||||
|| (io_kind = FC_IO_PREALLOC, !strcmp(arg, "--io=preall | ||||
oc")) | ||||
#endif | ||||
) | ||||
{ | { | |||
if (args.io_kind == FC_IO_AUTODETECT) | if (args.io_kind == FC_IO_AUTODETECT) | |||
args.io_kind = io_kind; | args.io_kind = io_kind; | |||
else | else | |||
err = invalid_cmdline(args, 0, | err = invalid_cmdline(args, 0, | |||
"options --io=posix, --io=test and --io=self-tes | "options --io=posix, --io=prealloc, --io=test an | |||
t are mutually exclusive"); | d --io=self-test are mutually exclusive"); | |||
} | ||||
else if (!strncmp(arg, "--loop-device=", opt_len)) { | ||||
args.loop_dev = opt_arg; | ||||
} | } | |||
/* -m, --mem-buffer=RAM_SIZE[k|M|G|T|P|E|Z|Y] */ | /* -m, --mem-buffer=RAM_SIZE[k|M|G|T|P|E|Z|Y] */ | |||
else if ((argc > 1 && !strcmp(arg, "-m")) || !strncmp(arg, "--me m-buffer=", opt_len)) { | else if ((argc > 1 && !strcmp(arg, "-m")) || !strncmp(arg, "--me m-buffer=", opt_len)) { | |||
if ((err = ff_str2un_scaled(opt_arg, & args.storage_size[FC_ MEM_BUFFER_SIZE])) != 0) { | if ((err = ff_str2un_scaled(opt_arg, & args.storage_size[FC_ MEM_BUFFER_SIZE])) != 0) { | |||
err = invalid_cmdline(args, err, "invalid memory buffer size '%s'", opt_arg); | err = invalid_cmdline(args, err, "invalid memory buffer size '%s'", opt_arg); | |||
break; | break; | |||
} | } | |||
if (is_short_opt) | if (is_short_opt) | |||
--argc, ++argv; | --argc, ++argv; | |||
} | } | |||
else if (!strncmp(arg, "--device-mount-point=", opt_len)) { | ||||
args.mount_points[FC_MOUNT_POINT_DEVICE] = opt_arg; | ||||
} | ||||
else if (!strncmp(arg, "--loop-mount-point=", opt_len)) { | ||||
args.mount_points[FC_MOUNT_POINT_LOOP_FILE] = opt_arg; | ||||
} | ||||
/* -n, --no-action, --simulate-run: do not read or write device blocks */ | /* -n, --no-action, --simulate-run: do not read or write device blocks */ | |||
else if (!strcmp(arg, "-n") || !strcmp(arg, "--no-action") || !s trcmp(arg, "--simulate-run")) { | else if (!strcmp(arg, "-n") || !strcmp(arg, "--no-action") || !s trcmp(arg, "--simulate-run")) { | |||
args.simulate_run = true; | args.simulate_run = true; | |||
} | } | |||
/* --questions=[no|yes|extra] */ | ||||
else if (!strncmp(arg, "--questions=", opt_len)) | ||||
{ | ||||
args.ask_questions = !strcmp("extra", opt_arg); | ||||
} | ||||
/* --resume-job=JOB_ID */ | /* --resume-job=JOB_ID */ | |||
else if (!strncmp(arg, "--resume-job=", opt_len)) { | else if (!strncmp(arg, "--resume-job=", opt_len)) { | |||
if (args.job_id != FC_JOB_ID_AUTODETECT) { | if (args.job_id != FC_JOB_ID_AUTODETECT) { | |||
err = invalid_cmdline(args, err, "option --resume-job=JO B_ID can be specified only once"); | err = invalid_cmdline(args, err, "option --resume-job=JO B_ID can be specified only once"); | |||
break; | break; | |||
} | } | |||
if ((err = ff_str2un(opt_arg, & args.job_id)) != 0 || args.j ob_id == FC_JOB_ID_AUTODETECT) { | if ((err = ff_str2un(opt_arg, & args.job_id)) != 0 || args.j ob_id == FC_JOB_ID_AUTODETECT) { | |||
err = invalid_cmdline(args, err, "invalid job id '%s'", opt_arg); | err = invalid_cmdline(args, err, "invalid job id '%s'", opt_arg); | |||
break; | break; | |||
} | } | |||
skipping to change at line 346 | skipping to change at line 401 | |||
else if ((argc > 1 && !strcmp(arg, "-t")) || !strncmp(arg, "--te mp-dir=", opt_len)) { | else if ((argc > 1 && !strcmp(arg, "-t")) || !strncmp(arg, "--te mp-dir=", opt_len)) { | |||
args.root_dir = opt_arg; | args.root_dir = opt_arg; | |||
if (is_short_opt) | if (is_short_opt) | |||
--argc, ++argv; | --argc, ++argv; | |||
} | } | |||
/* --ui-tty=TTY */ | /* --ui-tty=TTY */ | |||
else if (!strncmp(arg, "--ui-tty=", opt_len)) { | else if (!strncmp(arg, "--ui-tty=", opt_len)) { | |||
args.ui_kind = FC_UI_TTY; | args.ui_kind = FC_UI_TTY; | |||
args.ui_arg = opt_arg; | args.ui_arg = opt_arg; | |||
} | } | |||
/* --x-log-FILE=LEVEL */ | ||||
else if (!strncmp(arg, "--x-log-", 8)) { | ||||
ft_string logger_name(arg + 8, opt_len - 9); // 9 == 8 fo | ||||
r "--x-log-" plus 1 for '=' | ||||
ft_log_level logger_level = (ft_log_level) atoi(opt_arg); | ||||
ft_log::get_logger(logger_name).set_level(logger_level); | ||||
} | ||||
/* -xp, --exact-primary-storage=PRIMARY_SIZE[k|M|G|T|P|E|Z|Y] */ | /* -xp, --exact-primary-storage=PRIMARY_SIZE[k|M|G|T|P|E|Z|Y] */ | |||
else if ((argc > 1 && !strcmp(arg, "-xp")) || !strncmp(arg, "--e xact-primary-storage=", opt_len)) { | else if ((argc > 1 && !strcmp(arg, "-xp")) || !strncmp(arg, "--e xact-primary-storage=", opt_len)) { | |||
if ((err = ff_str2un_scaled(opt_arg, & args.storage_size[FC_ PRIMARY_STORAGE_EXACT_SIZE])) != 0) { | if ((err = ff_str2un_scaled(opt_arg, & args.storage_size[FC_ PRIMARY_STORAGE_EXACT_SIZE])) != 0) { | |||
err = invalid_cmdline(args, err, "invalid primary storag e exact size '%s'", opt_arg); | err = invalid_cmdline(args, err, "invalid primary storag e exact size '%s'", opt_arg); | |||
break; | break; | |||
} | } | |||
if (is_short_opt) | if (is_short_opt) | |||
--argc, ++argv; | --argc, ++argv; | |||
} | } | |||
/* -xs, --exact-secondary-storage=SECONDARY_SIZE[k|M|G|T|P|E|Z|Y ] */ | /* -xs, --exact-secondary-storage=SECONDARY_SIZE[k|M|G|T|P|E|Z|Y ] */ | |||
else if ((argc > 1 && !strcmp(arg, "-xs")) || !strncmp(arg, "--e xact-secondary-storage=", opt_len)) { | else if ((argc > 1 && !strcmp(arg, "-xs")) || !strncmp(arg, "--e xact-secondary-storage=", opt_len)) { | |||
if ((err = ff_str2un_scaled(opt_arg, & args.storage_size[FC_ SECONDARY_STORAGE_EXACT_SIZE])) != 0) { | if ((err = ff_str2un_scaled(opt_arg, & args.storage_size[FC_ SECONDARY_STORAGE_EXACT_SIZE])) != 0) { | |||
err = invalid_cmdline(args, err, "invalid secondary stor age exact size '%s'", opt_arg); | err = invalid_cmdline(args, err, "invalid secondary stor age exact size '%s'", opt_arg); | |||
break; | break; | |||
} | } | |||
if (is_short_opt) | if (is_short_opt) | |||
--argc, ++argv; | --argc, ++argv; | |||
} | } | |||
/* --x-log-FILE=LEVEL */ | ||||
else if (!strncmp(arg, "--x-log-", 8)) { | ||||
ft_mstring logger_name(arg + 8, opt_len - 9); // 9 == 8 for | ||||
"--x-log-" plus 1 for '=' | ||||
ft_log_level logger_level = (ft_log_level) atoi(opt_arg); | ||||
ft_log::get_logger(logger_name).set_level(logger_level); | ||||
} | ||||
/* -q, --quiet decrease verbosity by one */ | /* -q, --quiet decrease verbosity by one */ | |||
/* -qq decrease verbosity by two */ | /* -qq decrease verbosity by two */ | |||
/* -v, --verbose increase verbosity by one */ | /* -v, --verbose increase verbosity by one */ | |||
/* -vv increase verbosity by two */ | /* -vv increase verbosity by two */ | |||
/* -vvv increase verbosity by three */ | /* -vvv increase verbosity by three */ | |||
else if ((new_level = FC_WARN, !strcmp(arg, "-qq")) | else if ((new_level = FC_WARN, !strcmp(arg, "-qq")) | |||
|| (new_level = FC_NOTICE, !strcmp(arg, "-q") || !strcmp(arg , "--quiet")) | || (new_level = FC_NOTICE, !strcmp(arg, "-q") || !strcmp(arg , "--quiet")) | |||
|| (new_level = FC_DEBUG, !strcmp(arg, "-v") || !strcmp(arg, "--verbose")) | || (new_level = FC_DEBUG, !strcmp(arg, "-v") || !strcmp(arg, "--verbose")) | |||
|| (new_level = FC_TRACE, !strcmp(arg, "-vv")) | || (new_level = FC_TRACE, !strcmp(arg, "-vv")) | |||
|| (new_level = FC_DUMP, !strcmp(arg, "-vvv"))) | || (new_level = FC_DUMP, !strcmp(arg, "-vvv"))) | |||
{ | { | |||
if (level == FC_INFO) | if (level == FC_INFO) | |||
level = new_level; | level = new_level; | |||
else { | else { | |||
err = invalid_cmdline(args, 0, | err = invalid_cmdline(args, 0, | |||
"options -q, -qq, -v, -vv, -vvv, --quiet, --verb ose are mutually exclusive"); | "options -q, -qq, -v, -vv, -vvv, --quiet, --verb ose are mutually exclusive"); | |||
break; | break; | |||
} | } | |||
} else if (!strcmp(arg, "--help")) { | } else if (!strncmp(arg, "--log-color=", 12)) { | |||
/* --color=(auto|none|ansi) */ | ||||
arg += 12; | ||||
if (!strcmp(arg, "ansi")) | ||||
color = FC_COL_ANSI; | ||||
else if (!strcmp(arg, "none")) | ||||
color = FC_COL_NONE; | ||||
else | ||||
color = FC_COL_AUTO; | ||||
} | ||||
else if (!strncmp(arg, "--log-format=", 13)) { | ||||
/* --color=(auto|none|ansi) */ | ||||
arg += 13; | ||||
if (!strcmp(arg, "level_msg")) | ||||
format = FC_FMT_LEVEL_MSG; | ||||
else if (!strcmp(arg, "time_level_msg")) | ||||
format = FC_FMT_DATETIME_LEVEL_MSG; | ||||
else if (!strcmp(arg, "time_level_function_msg")) | ||||
format = FC_FMT_DATETIME_LEVEL_CALLER_MSG; | ||||
else | ||||
format = FC_FMT_MSG; | ||||
format_set = true; | ||||
} | ||||
else if (!strcmp(arg, "--help")) { | ||||
return usage(args.program_name); | return usage(args.program_name); | |||
} else if (!strcmp(arg, "--version")) { | } | |||
else if (!strcmp(arg, "--version")) { | ||||
return version(); | return version(); | |||
} else { | } | |||
else { | ||||
err = invalid_cmdline(args, 0, "unknown option: '%s'", arg); | err = invalid_cmdline(args, 0, "unknown option: '%s'", arg); | |||
break; | break; | |||
} | } | |||
continue; | continue; | |||
} | } | |||
/** found an argument */ | /** found an argument */ | |||
if (io_args_n < FC_FILE_COUNT) | if (io_args_n < FC_FILE_COUNT) | |||
args.io_args[io_args_n++] = arg; | args.io_args[io_args_n++] = arg; | |||
else | else | |||
err = invalid_cmdline(args, 0, "too many arguments"); | err = invalid_cmdline(args, 0, "too many arguments"); | |||
} | } | |||
if (err == 0) { | if (err != 0) | |||
/* if autodetect, clear all free blocks */ | break; | |||
if (args.job_clear == FC_CLEAR_AUTODETECT) | ||||
args.job_clear = FC_CLEAR_ALL; | /* if autodetect, clear all free blocks */ | |||
if (args.job_clear == FC_CLEAR_AUTODETECT) | ||||
/* if autodetect, use POSIX I/O */ | args.job_clear = FC_CLEAR_ALL; | |||
if (args.io_kind == FC_IO_AUTODETECT) | ||||
args.io_kind = FC_IO_POSIX; | /* if autodetect, use POSIX I/O */ | |||
if (args.io_kind == FC_IO_AUTODETECT) | ||||
if (args.io_kind == FC_IO_POSIX) { | args.io_kind = FC_IO_POSIX; | |||
if (args.job_id == FC_JOB_ID_AUTODETECT) { | ||||
if (io_args_n == 0) { | if (args.io_kind == FC_IO_POSIX || args.io_kind == FC_IO_PREALLOC) { | |||
err = invalid_cmdline(args, 0, "missing arguments: %s %s | if (args.job_id == FC_JOB_ID_AUTODETECT) { | |||
[%s]", LABEL[0], LABEL[1], LABEL[2]); | if (io_args_n == 0) { | |||
} else if (io_args_n == 1) { | err = invalid_cmdline(args, 0, "missing arguments: %s %s [%s | |||
err = invalid_cmdline(args, 0, "missing arguments: %s [% | ]", LABEL[0], LABEL[1], LABEL[2]); | |||
s]", LABEL[1], LABEL[2]); | } else if (io_args_n == 1) { | |||
} else if (io_args_n == 2 || io_args_n == 3) { | err = invalid_cmdline(args, 0, "missing arguments: %s [%s]", | |||
/* ok */ | LABEL[1], LABEL[2]); | |||
} else | } else if (io_args_n == 2 || io_args_n == 3) { | |||
err = invalid_cmdline(args, 0, "too many arguments"); | /* ok */ | |||
} else { | } else | |||
if (io_args_n == 0) { | err = invalid_cmdline(args, 0, "too many arguments"); | |||
err = invalid_cmdline(args, 0, "missing argument: %s", L | } else { | |||
ABEL[0]); | ||||
} else if (io_args_n == 1) { | ||||
/* ok */ | ||||
} else | ||||
err = invalid_cmdline(args, 0, "too many arguments"); | ||||
} | ||||
} else if (args.io_kind == FC_IO_TEST) { | ||||
if (io_args_n == 0) { | if (io_args_n == 0) { | |||
err = invalid_cmdline(args, 0, "missing arguments: %s %s %s" , LABEL[0], LABEL[1], LABEL[2]); | err = invalid_cmdline(args, 0, "missing argument: %s", LABEL [0]); | |||
} else if (io_args_n == 1) { | } else if (io_args_n == 1) { | |||
err = invalid_cmdline(args, 0, "missing arguments: %s %s", L | ||||
ABEL[1], LABEL[2]); | ||||
} else if (io_args_n == 2) { | ||||
err = invalid_cmdline(args, 0, "missing argument: %s", LABEL | ||||
[2]); | ||||
} else if (io_args_n == 3) { | ||||
/* ok */ | /* ok */ | |||
} else | } else | |||
err = invalid_cmdline(args, 0, "too many arguments"); | err = invalid_cmdline(args, 0, "too many arguments"); | |||
} | } | |||
} else if (args.io_kind == FC_IO_TEST) { | ||||
if (io_args_n == 0) { | ||||
err = invalid_cmdline(args, 0, "missing arguments: %s %s %s", LA | ||||
BEL[0], LABEL[1], LABEL[2]); | ||||
} else if (io_args_n == 1) { | ||||
err = invalid_cmdline(args, 0, "missing arguments: %s %s", LABEL | ||||
[1], LABEL[2]); | ||||
} else if (io_args_n == 2) { | ||||
err = invalid_cmdline(args, 0, "missing argument: %s", LABEL[2]) | ||||
; | ||||
} else if (io_args_n == 3) { | ||||
/* ok */ | ||||
} else | ||||
err = invalid_cmdline(args, 0, "too many arguments"); | ||||
} | } | |||
} while (0); | } while (0); | |||
if (err == 0) { | if (err == 0) { | |||
/* always enable at least DEBUG level, to let fsremap.log collect all me | ff_log(FC_INFO, 0, "setting log level to %s", ff_log_level_to_string(lev | |||
ssages from DEBUG to FATAL */ | el)); | |||
/* | ||||
* always enable at least DEBUG level, to let let the appender installed | ||||
by fr_job::init_log() | ||||
* intercept all messages from DEBUG to FATAL. | ||||
* we avoid spamming the user by setting stdout appender->min_level = le | ||||
vel below | ||||
*/ | ||||
ft_log::get_root_logger().set_level(level < FC_DEBUG ? level : FC_DEBUG) ; | ft_log::get_root_logger().set_level(level < FC_DEBUG ? level : FC_DEBUG) ; | |||
/* note 1.4.1) -v enables FC_FMT_LEVEL_MSG also for stdout/stderr */ | /* note 1.4.1) -v sets format FC_FMT_LEVEL_MSG */ | |||
/* note 1.4.2) -vv enables FC_FMT_DATETIME_LEVEL_MSG also for stdout/std | /* note 1.4.2) -vv sets format FC_FMT_DATETIME_LEVEL_MSG */ | |||
err */ | if (!format_set) | |||
ft_log_fmt format = level < FC_DEBUG ? FC_FMT_DATETIME_LEVEL_MSG : level | format = level < FC_DEBUG ? FC_FMT_DATETIME_LEVEL_MSG : level == FC_ | |||
== FC_DEBUG ? FC_FMT_LEVEL_MSG : FC_FMT_MSG; | DEBUG ? FC_FMT_LEVEL_MSG : FC_FMT_MSG; | |||
if (format != FC_FMT_MSG) | ||||
ft_log_appender::redefine(stderr, format, FC_WARN); | ||||
ft_log_appender::redefine(stdout, format, level, FC_NOTICE); | // set stdout appender->min_level, since we played tricks with root_logg | |||
er->level above. | ||||
ft_log_appender::reconfigure_all(format, level, color); | ||||
err = init(args); | err = init(args); | |||
} | } | |||
return err; | return err; | |||
} | } | |||
/** | /** | |||
* initialize all subsystems (job, I/O, log...) using specified arguments | * initialize all subsystems (job, I/O, log...) using specified arguments | |||
* return 0 if success, else error. | * return 0 if success, else error. | |||
skipping to change at line 584 | skipping to change at line 671 | |||
/** | /** | |||
* choose the I/O to use, create and initialize it. if success, stores a pointer to I/O object. | * choose the I/O to use, create and initialize it. if success, stores a pointer to I/O object. | |||
* | * | |||
* return 0 if success, else error. | * return 0 if success, else error. | |||
*/ | */ | |||
int fr_remap::init_io(const fr_args & args) | int fr_remap::init_io(const fr_args & args) | |||
{ | { | |||
int err; | int err; | |||
switch (args.io_kind) { | switch (args.io_kind) { | |||
case FC_IO_POSIX: | ||||
err = init_io_posix(args); | ||||
break; | ||||
case FC_IO_TEST: | case FC_IO_TEST: | |||
err = init_io_test(args); | err = init_io_class<FT_IO_NS fr_io_test>(args); | |||
break; | break; | |||
case FC_IO_SELF_TEST: | case FC_IO_SELF_TEST: | |||
err = init_io_self_test(args); | err = init_io_class<FT_IO_NS fr_io_self_test>(args); | |||
break; | break; | |||
case FC_IO_POSIX: | ||||
err = init_io_class<FT_IO_NS fr_io_posix>(args); | ||||
break; | ||||
#ifdef FT_HAVE_IO_PREALLOC | ||||
case FC_IO_PREALLOC: | ||||
err = init_io_class<FT_IO_NS fr_io_prealloc>(args); | ||||
break; | ||||
#endif | ||||
default: | default: | |||
ff_log(FC_ERROR, 0, "tried to initialize unknown I/O '%d': not POSIX , not self-test", (int) args.io_kind); | ff_log(FC_ERROR, 0, "tried to initialize unknown I/O '%d': not POSIX , not PREALLOC, not TEST, not SELF-TEST", (int) args.io_kind); | |||
err = -ENOSYS; | err = -ENOSYS; | |||
break; | break; | |||
} | } | |||
return err; | return err; | |||
} | } | |||
/** | /** | |||
* initialize remapper to use POSIX I/O. | * initialize remapper to use I/O type IO_T. | |||
* POSIX I/O requires three arguments in args.io_args: DEVICE, LOOP-FILE and ZER | * | |||
O-FILE. | * args depend on I/O type: | |||
* return 0 if success, else error. | * POSIX and PREALLOC I/O require two or three arguments in args.io_args: DEVICE | |||
*/ | , LOOP-FILE and optionally ZERO-FILE; | |||
int fr_remap::init_io_posix(const fr_args & args) | * test I/O requires three arguments in args.io_args: DEVICE-LENGTH, LOOP-FILE-E | |||
{ | XTENTS and ZERO-FILE-EXTENTS; | |||
int err; | * self-test I/O does not require any argument in args.io_args; | |||
if ((err = pre_init_io()) == 0) { | ||||
FT_IO_NS fr_io_posix * io = new FT_IO_NS fr_io_posix(* this_persist); | ||||
if ((err = io->open(args)) == 0) | ||||
post_init_io(io); | ||||
else | ||||
delete io; | ||||
} | ||||
return err; | ||||
} | ||||
/** | ||||
* initialize remapper to use test I/O. | ||||
* test I/O requires three arguments in args.io_args: DEVICE-LENGTH, LOOP-FILE-E | ||||
XTENTS and ZERO-FILE-EXTENTS. | ||||
* return 0 if success, else error. | ||||
*/ | ||||
int fr_remap::init_io_test(const fr_args & args) | ||||
{ | ||||
int err; | ||||
if ((err = pre_init_io()) == 0) { | ||||
FT_IO_NS fr_io_test * io = new FT_IO_NS fr_io_test(* this_persist); | ||||
if ((err = io->open(args)) == 0) | ||||
post_init_io(io); | ||||
else | ||||
delete io; | ||||
} | ||||
return err; | ||||
} | ||||
/** | ||||
* initialize remapper to use self-test I/O. | ||||
* return 0 if success, else error. | * return 0 if success, else error. | |||
*/ | */ | |||
int fr_remap::init_io_self_test(const fr_args & args) | template<class IO_T> | |||
int fr_remap::init_io_class(const fr_args & args) | ||||
{ | { | |||
int err; | int err; | |||
if ((err = pre_init_io()) == 0) { | if ((err = pre_init_io()) == 0) { | |||
FT_IO_NS fr_io_self_test * io = new FT_IO_NS fr_io_self_test(* this_pers ist); | IO_T * io = new IO_T(* this_persist); | |||
if ((err = io->open(args)) == 0) | if ((err = io->open(args)) == 0) | |||
post_init_io(io); | post_init_io(io); | |||
else | else | |||
delete io; | delete io; | |||
} | } | |||
return err; | return err; | |||
} | } | |||
int fr_remap::pre_init_io() | int fr_remap::pre_init_io() | |||
skipping to change at line 706 | skipping to change at line 764 | |||
break; | break; | |||
FT_IO_NS fr_io & io = * this_io; | FT_IO_NS fr_io & io = * this_io; | |||
const char * dev_path = ff_if_null(io.dev_path(), "<unknown>"); | const char * dev_path = ff_if_null(io.dev_path(), "<unknown>"); | |||
ff_log(FC_INFO, 0, "analyzing %s '%s', this may take some minutes ...", label[FC_DEVICE], dev_path); | ff_log(FC_INFO, 0, "analyzing %s '%s', this may take some minutes ...", label[FC_DEVICE], dev_path); | |||
/* allocate fr_vector<ft_uoff> for both LOOP-FILE and FREE-SPACE extents */ | /* allocate fr_vector<ft_uoff> for both LOOP-FILE and FREE-SPACE extents */ | |||
fr_vector<ft_uoff> loop_file_extents, free_space_extents; | fr_vector<ft_uoff> loop_file_extents, free_space_extents; | |||
// preallocated extents in files inside loop file | ||||
// which do NOT have a correspondence in files inside device: | ||||
// they must be cleared once remapping is completed! | ||||
fr_vector<ft_uoff> to_zero_extents; | ||||
/* ask actual I/O subsystem to read LOOP-FILE and FREE-SPACE extents */ | /* ask actual I/O subsystem to read LOOP-FILE and FREE-SPACE extents */ | |||
if ((err = io.read_extents(loop_file_extents, free_space_extents)) != 0) | if ((err = io.read_extents(loop_file_extents, free_space_extents, to_zer o_extents)) != 0) | |||
break; | break; | |||
/* persistence: save LOOP-FILE and FREE-SPACE extents to disk */ | /* persistence: save LOOP-FILE and FREE-SPACE extents to disk */ | |||
if ((err = io.save_extents(loop_file_extents, free_space_extents)) != 0) | if ((err = io.save_extents(loop_file_extents, free_space_extents, to_zer o_extents)) != 0) | |||
break; | break; | |||
io.close_extents(); | io.close_extents(); | |||
/* invoke fr_dispatch::main() to choose which fr_work<T> to instantiate, and run it */ | /* invoke fr_dispatch::main() to choose which fr_work<T> to instantiate, and run it */ | |||
err = fr_dispatch::main(loop_file_extents, free_space_extents, io); | err = fr_dispatch::main(loop_file_extents, free_space_extents, to_zero_e xtents, io); | |||
} while (0); | } while (0); | |||
return err; | return err; | |||
} | } | |||
FT_NAMESPACE_END | FT_NAMESPACE_END | |||
End of changes. 47 change blocks. | ||||
143 lines changed or deleted | 220 lines changed or added |