From 7fc71acefb4702a656cc33be6ec910fb9498dafc Mon Sep 17 00:00:00 2001 From: Anthony Baccuet Date: Fri, 21 Dec 2018 09:49:36 +0100 Subject: [PATCH 1/3] Add find and findx to amrecover Adding the possibility to search for a file with find or findx in amrecover. find compare the whole filename and findx work with regular expression --- recover-src/amrecover.h | 2 + recover-src/display_commands.c | 152 +++++++++++++++++++++++++++++++++ recover-src/help.c | 4 + recover-src/uparse.y | 10 ++- recover-src/uscan.l | 2 + 5 files changed, 169 insertions(+), 1 deletion(-) diff --git a/recover-src/amrecover.h b/recover-src/amrecover.h index f48f07d3c0..cacb65a0ed 100644 --- a/recover-src/amrecover.h +++ b/recover-src/amrecover.h @@ -106,6 +106,8 @@ extern void show_mode(void); extern void set_property_name(char *name, int append); extern void add_property_value(char *value); extern void list_property(void); +extern void list_all_file(char *dir, char *name, int re); +extern void find_file(char *name, char *dir, int re); extern void add_storage_value(char *storage); extern void set_storage(void); diff --git a/recover-src/display_commands.c b/recover-src/display_commands.c index 3de7e873be..aa918f438c 100644 --- a/recover-src/display_commands.c +++ b/recover-src/display_commands.c @@ -34,6 +34,7 @@ #include "amanda.h" #include "amrecover.h" #include "amutil.h" +#include "match.h" gboolean translate_mode = TRUE; @@ -50,6 +51,7 @@ static int add_dir_list_item(char *date, void list_disk_history(void); void suck_dir_list_from_server(void); void list_directory(void); +char *convert_name(char *name); static DIR_ITEM *dir_list = NULL; @@ -69,6 +71,156 @@ get_next_dir_item( } +void +list_all_file(char *dir, char *name, int re) +{ + DIR_ITEM *item; + char *quote; + int size = 5; + int nb_folder = 0; + char **dir_list; + char *next_dir; + int i; + int len; + int dir_len; + int printed = 0; + + if (disk_path == NULL) { + g_printf(_("Must select a disk before listing files; use the setdisk command.\n")); + return; + } + + dir_list = g_malloc0(sizeof(char *) * size); + + if (set_directory(dir, 0) == 1) { + dir_len = strlen(disk_tpath); + if (dir_len == 1) + dir_len = 0; + for (item = get_dir_list(); item != NULL; item = get_next_dir_item(item)) { + quote = quote_string(item->tpath + 1); + i = 0; + if (quote[strlen(quote) - 1] == '\"') { + quote++; + quote[strlen(quote) - 1] = '\0'; + i = 1; + } + len = strlen(quote); + if (quote[len - 1] == '/') { + if (dir[strlen(dir) - 1] == '/') { + next_dir = g_strconcat(dir, "e[dir_len], NULL); + } else { + next_dir = g_strconcat(dir, "/", "e[dir_len], NULL); + } + dir_list[nb_folder] = next_dir; + nb_folder++; + if (nb_folder == size) { + size *= 2; + dir_list = g_realloc(dir_list, sizeof(char *) * size); + for (int j = size/2; j < size; j++) { + dir_list[j] = NULL; + } + } + } else { + if ((re && (match(name, "e[dir_len]) == 1)) || (!re && (strcmp(name, "e[dir_len]) == 0))) { + if (!printed) { + printed = 1; + g_printf("\nFolder: %s\n", dir); + } + g_printf("%s: %s\n", item->date, quote); + } + } + quote -= i; + amfree(quote); + } + i = 0; + while ((i < size) && (dir_list[i] != NULL)) { + list_all_file(dir_list[i], name, re); + amfree(dir_list[i]); + i++; + } + set_directory(dir, 0); + } + amfree(dir_list); +} + + +void +find_file(char *name, char *dir, int re) +{ + char *error = NULL; + char *regex = NULL; + + if (disk_path == NULL) { + g_printf(_("Must select a disk before search for a file; use the setdisk command.\n")); + return; + } + + if ((strlen(dir) != 1) && (dir[0] == '\"') && (dir[strlen(dir) - 1] == '\"')) { + dir = &dir[1]; + dir[strlen(dir) - 1] = '\0'; + } + if (!g_str_has_prefix(dir, mount_point)) { + if (dir[0] != '/') { + if (disk_tpath[strlen(disk_tpath) - 1] == '/') { + dir = g_strconcat(mount_point, disk_tpath, dir, NULL); + } else { + dir = g_strconcat(mount_point, disk_tpath, "/", dir, NULL); + } + } else { + dir = g_strconcat(mount_point, dir, NULL); + } + } + + name = convert_name(name); + if (re == 1) { + error = validate_regexp(name); + if (error == NULL) { + regex = g_strconcat("^", name, "$", NULL); + + g_printf("Search regex : %s in %s\n", regex, dir); + + list_all_file(dir, regex, re); + } else { + g_printf("Regex error: %s\n", error); + } + } else { + g_printf("Search %s in %s\n", name, dir); + + list_all_file(dir, name, re); + } + amfree(name); +} + + +char * +convert_name(char *name) +{ + char *new_name; + char *tmp; + int i; + + if ((name[0] == '\"') && (name[strlen(name) - 1] == '\"')) { + new_name = g_strdup(name + 1); + new_name[strlen(new_name) - 1] = '\0'; + } else { + new_name = g_strdup(name); + } + i = 0; + while (new_name[i] != '\0') { + if (new_name[i] == '/') { + new_name[i] = '\0'; + tmp = g_strconcat(new_name, "\342\201\204", &new_name[i + 1], NULL); + amfree(new_name); + new_name = tmp; + i += 2; + } + i++; + } + return new_name; +} + + + void clear_dir_list(void) { diff --git a/recover-src/help.c b/recover-src/help.c index 3f0b903f3e..b8440f7ca7 100644 --- a/recover-src/help.c +++ b/recover-src/help.c @@ -49,6 +49,10 @@ help_list(void) g_printf(_("deletex path1 ... - delete from extraction list (regular expressions)\n")); g_printf(_("extract - extract selected files from tapes\n")); g_printf(_("exit\n")); + g_printf(_("find file - find file in current directory and subdirectories\n")); + g_printf(_("find path file - find file in path and path subdirectories\n")); + g_printf(_("findx filename - find file in current directory and subdirectories (regular expressions)\n")); + g_printf(_("findx path file - find file in path and path subdirectories (regular expressions)\n")); g_printf(_("help\n")); g_printf(_("history - show dump history of disk\n")); g_printf(_("list [filename] - show extraction list, optionally writing to file\n")); diff --git a/recover-src/uparse.y b/recover-src/uparse.y index 10edcdc01b..a0f16ddda7 100644 --- a/recover-src/uparse.y +++ b/recover-src/uparse.y @@ -55,7 +55,7 @@ extern char * yytext; %token SETHOST SETDISK SETDATE SETTAPE SETMODE SETDEVICE SETPROPERTY %token CD CDX QUIT DHIST LS ADD ADDX EXTRACT DASH_H %token LIST DELETE DELETEX PWD CLEAR HELP LCD LPWD MODE SMB TAR -%token APPEND PRIORITY SETTRANSLATE STORAGE +%token APPEND PRIORITY SETTRANSLATE STORAGE FIND FINDX %token NL /* typed tokens */ @@ -129,6 +129,14 @@ set_command: | SETMODE invalid_string { yyerror("Invalid argument"); } | SETMODE NL { yyerror("Argument required"); } | STORAGE storage_value { set_storage(); } + | FIND STRING STRING NL { find_file($3, $2, 0); amfree($2); amfree($3); } + | FIND STRING NL { find_file($2, "", 0); amfree($2); } + | FIND NL { yyerror("Argument required"); } + | FIND STRING STRING invalid_string { yyerror("Invalid argument"); amfree($2); amfree($3); } + | FINDX STRING STRING NL { find_file($3, $2, 1); amfree($2); amfree($3); } + | FINDX STRING NL { find_file($2, "", 1); amfree($2); } + | FINDX NL { yyerror("Argument required"); } + | FINDX STRING STRING invalid_string { yyerror("Invalid argument"); amfree($2); amfree($3); } ; setdate_command: diff --git a/recover-src/uscan.l b/recover-src/uscan.l index 3da4716425..e00d151c4d 100644 --- a/recover-src/uscan.l +++ b/recover-src/uscan.l @@ -106,6 +106,8 @@ lpwd { BEGIN(needstring); return LPWD; } extract { BEGIN(needstring); return EXTRACT; } mode { BEGIN(needstring); return MODE; } storage { BEGIN(needstring); return STORAGE; } +find { BEGIN(needstring); return FIND; } +findx { BEGIN(needstring); return FINDX; } tar { BEGIN(needstring); return TAR; } smb { BEGIN(needstring); return SMB; } {LINEFEED} { BEGIN(INITIAL); return NL; } From aff8efcc2fdbbd9b784290609fa1d8833928464a Mon Sep 17 00:00:00 2001 From: Anthony Baccuet Date: Fri, 21 Dec 2018 10:18:50 +0100 Subject: [PATCH 2/3] Add ls-all to amrecover --- recover-src/help.c | 1 + recover-src/uparse.y | 4 +++- recover-src/uscan.l | 1 + 3 files changed, 5 insertions(+), 1 deletion(-) diff --git a/recover-src/help.c b/recover-src/help.c index b8440f7ca7..00292c0320 100644 --- a/recover-src/help.c +++ b/recover-src/help.c @@ -58,6 +58,7 @@ help_list(void) g_printf(_("list [filename] - show extraction list, optionally writing to file\n")); g_printf(_("lcd directory - change cwd on local file system\n")); g_printf(_("ls - list directory on virtual file system\n")); + g_printf(_("ls-all - list all directories and file on virtual file system\n")); g_printf(_("lpwd - show cwd on local file system\n")); g_printf(_("mode - show the method used to extract SMB shares\n")); g_printf(_("pwd - show cwd on virtual file system\n")); diff --git a/recover-src/uparse.y b/recover-src/uparse.y index a0f16ddda7..1c5daf47ca 100644 --- a/recover-src/uparse.y +++ b/recover-src/uparse.y @@ -53,7 +53,7 @@ extern char * yytext; %token LISTHOST LISTDISK LISTPROPERTY %token SETHOST SETDISK SETDATE SETTAPE SETMODE SETDEVICE SETPROPERTY -%token CD CDX QUIT DHIST LS ADD ADDX EXTRACT DASH_H +%token CD CDX QUIT DHIST LS LSALL ADD ADDX EXTRACT DASH_H %token LIST DELETE DELETEX PWD CLEAR HELP LCD LPWD MODE SMB TAR %token APPEND PRIORITY SETTRANSLATE STORAGE FIND FINDX %token NL @@ -194,6 +194,8 @@ display_command: | DHIST invalid_string { yyerror("Invalid argument"); } | LS NL { list_directory(); } | LS invalid_string { yyerror("Invalid argument"); } + | LSALL NL { list_all_file(mount_point, ".*", 1); } + | LSALL invalid_string { yyerror("Invalid argument"); } | LIST STRING NL { display_extract_list($2); amfree($2); } | LIST NL { display_extract_list(NULL); } | LIST STRING invalid_string { yyerror("Invalid argument"); } diff --git a/recover-src/uscan.l b/recover-src/uscan.l index e00d151c4d..b091517f82 100644 --- a/recover-src/uscan.l +++ b/recover-src/uscan.l @@ -92,6 +92,7 @@ quit { BEGIN(needstring); return QUIT; } exit { BEGIN(needstring); return QUIT; } history { BEGIN(needstring); return DHIST; } ls { BEGIN(needstring); return LS; } +ls-all { BEGIN(needstring); return LSALL; } add { BEGIN(needstring); return ADD; } addx { BEGIN(needstring); return ADDX; } list { BEGIN(needstring); return LIST; } From 6dcfd2f65a13b8867a94989f41e7f00c1879d8dc Mon Sep 17 00:00:00 2001 From: Anthony Baccuet Date: Fri, 21 Dec 2018 10:40:53 +0100 Subject: [PATCH 3/3] Add version command to amrecover Adding version command to list history of a file. --- recover-src/amrecover.c | 2 + recover-src/amrecover.h | 2 + recover-src/display_commands.c | 101 +++++++++++++++++++++++++++++++++ recover-src/help.c | 1 + recover-src/set_commands.c | 5 +- recover-src/uparse.y | 5 +- recover-src/uscan.l | 1 + 7 files changed, 115 insertions(+), 2 deletions(-) diff --git a/recover-src/amrecover.c b/recover-src/amrecover.c index f69e3897f4..7106b16b49 100644 --- a/recover-src/amrecover.c +++ b/recover-src/amrecover.c @@ -88,6 +88,7 @@ static char *errstr = NULL; char *authopt; int amindexd_alive = 0; security_handle_t *gsech; +char *listing_date = NULL; static struct { const char *name; @@ -606,6 +607,7 @@ main( g_printf(_("Setting restore date to today (%s)\n"), dump_date); line = g_strdup_printf("DATE %s", dump_date); + listing_date = g_strdup(dump_date); if (converse(line) == -1) { aclose(server_socket); exit(1); diff --git a/recover-src/amrecover.h b/recover-src/amrecover.h index cacb65a0ed..3ddba28a9a 100644 --- a/recover-src/amrecover.h +++ b/recover-src/amrecover.h @@ -72,6 +72,7 @@ extern am_feature_t *tapesrv_features; extern pid_t extract_restore_child_pid; extern proplist_t proplist; extern gboolean translate_mode; +extern char *listing_date; extern void free_dir_item(DIR_ITEM *item); @@ -108,6 +109,7 @@ extern void add_property_value(char *value); extern void list_property(void); extern void list_all_file(char *dir, char *name, int re); extern void find_file(char *name, char *dir, int re); +extern void list_file_history(char* name); extern void add_storage_value(char *storage); extern void set_storage(void); diff --git a/recover-src/display_commands.c b/recover-src/display_commands.c index aa918f438c..8ab3c00cd5 100644 --- a/recover-src/display_commands.c +++ b/recover-src/display_commands.c @@ -71,6 +71,107 @@ get_next_dir_item( } +void list_file_history(char* name) +{ + size_t i; + DIR_ITEM *item; + char *quoted; + char *l; + char *s; + char *date; + int ch; + int ind = 0; + int size = 1; + char *next_date; + char *cmd; + char **list_date; + list_date = g_malloc0(sizeof(char *) * size); + + if (disk_path == NULL) { + g_printf(_("Must select a disk before listing file history; use the setdisk command.\n")); + return; + } + + send_command("DHST"); + get_reply_line(); + + while (get_reply_line() != 0) + { + s = reply_line(); + l = s; + if (strncmp_const_skip(l, "201-", s, ch) != 0) { + g_printf("bad reply: not 201-"); + continue; + } + ch = *s++; + skip_whitespace(s, ch); + if(ch == '\0') { + g_printf("bad reply: missing date field"); + continue; + } + date = s - 1; + skip_non_whitespace(s, ch); + *(s - 1) = '\0'; + list_date[ind] = g_strdup(date); + ind++; + if (ind == size) { + size *= 2; + list_date = g_realloc(list_date, sizeof(char *) * size); + for (int j = size/2; j < size; j++) { + list_date[j] = NULL; + } + } + } + g_printf("History of file: %s\n", name); + i = strlen(disk_tpath); + if (i != 1) + i++; + ind = 0; + next_date = g_strdup(list_date[ind]); + while ((ind < size) && (list_date[ind] != NULL)) { + if (!(strcmp(list_date[ind], next_date) > 0)) + { + + clear_dir_list(); + cmd = g_strconcat("DATE ", list_date[ind], NULL); + if (exchange(cmd) == -1) + exit(1); + if (server_happy()) + { + suck_dir_list_from_server(); + } else { + continue; + } + for (item = get_dir_list(); item != NULL; item = get_next_dir_item(item)) { + quoted = quote_string(item->tpath + i); + if (strcmp(quoted, name) == 0) { + if (strcmp(item->date, list_date[ind]) == 0) { + g_printf("%s %s\n", item->date, quoted); + amfree(quoted); + break; + } else { + amfree(next_date); + next_date = g_strdup(item->date); + } + } + amfree(quoted); + } + } + amfree(list_date[ind]); + ind++; + } + amfree(list_date); + cmd = g_strconcat("DATE ", listing_date, NULL); + if (exchange(cmd) == -1) + exit(1); + if (server_happy()) + { + suck_dir_list_from_server(); + } + amfree(cmd); +} + + void list_all_file(char *dir, char *name, int re) { diff --git a/recover-src/help.c b/recover-src/help.c index 00292c0320..e5786400b5 100644 --- a/recover-src/help.c +++ b/recover-src/help.c @@ -76,5 +76,6 @@ help_list(void) g_printf(_("settranslate [on|off] - set/unset translation of non-ASCII characters\n")); g_printf(_("storage [storage-name]* - the name of the storage in order of preference\n")); g_printf(_(" use 'HOLDING' for the holding disk\n")); + g_printf(_("version filename - show file history\n")); g_printf("\n"); } diff --git a/recover-src/set_commands.c b/recover-src/set_commands.c index 982f40f542..6067bb6fe0 100644 --- a/recover-src/set_commands.c +++ b/recover-src/set_commands.c @@ -46,7 +46,10 @@ set_date( { char *cmd = NULL; char *qdisk_path; - + + amfree(listing_date); + listing_date = g_strdup(date); + clear_dir_list(); cmd = g_strconcat("DATE ", date, NULL); diff --git a/recover-src/uparse.y b/recover-src/uparse.y index 1c5daf47ca..383a611fdc 100644 --- a/recover-src/uparse.y +++ b/recover-src/uparse.y @@ -55,7 +55,7 @@ extern char * yytext; %token SETHOST SETDISK SETDATE SETTAPE SETMODE SETDEVICE SETPROPERTY %token CD CDX QUIT DHIST LS LSALL ADD ADDX EXTRACT DASH_H %token LIST DELETE DELETEX PWD CLEAR HELP LCD LPWD MODE SMB TAR -%token APPEND PRIORITY SETTRANSLATE STORAGE FIND FINDX +%token APPEND PRIORITY SETTRANSLATE STORAGE FIND FINDX FILEHISTORY %token NL /* typed tokens */ @@ -137,6 +137,9 @@ set_command: | FINDX STRING NL { find_file($2, "", 1); amfree($2); } | FINDX NL { yyerror("Argument required"); } | FINDX STRING STRING invalid_string { yyerror("Invalid argument"); amfree($2); amfree($3); } + | FILEHISTORY STRING NL { list_file_history($2); amfree($2); } + | FILEHISTORY STRING invalid_string { yyerror("Invalid argument"); amfree($2); } + | FILEHISTORY NL { yyerror("Argument required"); } ; setdate_command: diff --git a/recover-src/uscan.l b/recover-src/uscan.l index b091517f82..37a4c986e6 100644 --- a/recover-src/uscan.l +++ b/recover-src/uscan.l @@ -109,6 +109,7 @@ mode { BEGIN(needstring); return MODE; } storage { BEGIN(needstring); return STORAGE; } find { BEGIN(needstring); return FIND; } findx { BEGIN(needstring); return FINDX; } +version { BEGIN(needstring); return FILEHISTORY; } tar { BEGIN(needstring); return TAR; } smb { BEGIN(needstring); return SMB; } {LINEFEED} { BEGIN(INITIAL); return NL; }