2 * Amanda, The Advanced Maryland Automatic Network Disk Archiver
3 * Copyright (c) 1991-1998, 2000 University of Maryland at College Park
6 * Permission to use, copy, modify, distribute, and sell this software and its
7 * documentation for any purpose is hereby granted without fee, provided that
8 * the above copyright notice appear in all copies and that both that
9 * copyright notice and this permission notice appear in supporting
10 * documentation, and that the name of U.M. not be used in advertising or
11 * publicity pertaining to distribution of the software without specific,
12 * written prior permission. U.M. makes no representations about the
13 * suitability of this software for any purpose. It is provided "as is"
14 * without express or implied warranty.
16 * U.M. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL U.M.
18 * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
19 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
20 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
21 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
23 * Authors: the Amanda Development Team. Its members are listed in a
24 * file named AUTHORS, in the root directory of this distribution.
27 * $Id: set_commands.c,v 1.26 2006/07/05 13:14:58 martinea Exp $
29 * implements the "set" commands in amrecover
34 #include "amrecover.h"
37 extern unsigned short samba_extract_method;
39 /* sets a date, mapping given date into standard form if needed */
49 cmd = stralloc2("DATE ", date);
50 if (converse(cmd) == -1)
53 /* if a host/disk/directory is set, then check if that directory
54 is still valid at the new date, and if not set directory to
56 if (disk_path != NULL) {
57 qdisk_path = quote_string(disk_path);
58 cmd = newstralloc2(cmd, "OISD ", qdisk_path);
60 if (exchange(cmd) == -1)
64 suck_dir_list_from_server();
68 g_printf(_("No index records for cwd on new date\n"));
69 g_printf(_("Setting cwd to mount point\n"));
70 disk_path = newstralloc(disk_path, "/"); /* fake it */
84 struct hostent *hp = NULL;
87 char *uqhost = unquote_string(host);
89 if (is_extract_list_nonempty())
91 g_printf(_("Must clear extract list before changing host\n"));
97 * The idea here is to try as many permutations of the hostname
98 * as we can imagine. The server will reject anything it doesn't
102 cmd = stralloc2("HOST ", uqhost);
103 if (converse(cmd) == -1)
109 * Try converting the given host to a fully qualified, canonical
113 if ((hp = gethostbyname(uqhost)) != NULL) {
115 g_printf(_("Trying host %s ...\n"), host);
116 cmd = newstralloc2(cmd, "HOST ", host);
117 if (converse(cmd) == -1)
125 * Since we have them, try any CNAMEs that were traversed from uqhost
126 * to the canonical name (this assumes gethostbyname was called above)
130 for (hostp = hp->h_aliases; (host = *hostp) != NULL; hostp++)
132 g_printf(_("Trying host %s ...\n"), host);
133 cmd = newstralloc2(cmd, "HOST ", host);
134 if (converse(cmd) == -1)
145 /* Try looking up the canonical name of the host */
150 result = resolve_hostname(uqhost, 0, NULL, &canonname);
151 if (result == 0 && canonname) {
153 g_printf(_("Trying host %s ...\n"), host);
154 cmd = newstralloc2(cmd, "HOST ", host);
155 if (converse(cmd) == -1)
163 dump_hostname = newstralloc(dump_hostname, host);
178 cmd = stralloc("LISTHOST");
179 if (converse(cmd) == -1)
194 if (is_extract_list_nonempty())
196 g_printf(_("Must clear extract list before changing disk\n"));
200 /* if mount point specified, check it is valid */
202 uqmtpt = unquote_string(mtpt);
204 g_printf(_("Mount point \"%s\" invalid - must start with /\n"), uqmtpt);
211 uqdsk = unquote_string(dsk);
212 qdsk = quote_string(uqdsk);
213 cmd = stralloc2("DISK ", qdsk);
215 if (converse(cmd) == -1)
219 if (!server_happy()) {
225 disk_name = newstralloc(disk_name, uqdsk);
228 /* mount point not specified */
231 /* disk specified by mount point, hence use it */
232 mount_point = newstralloc(mount_point, uqdsk);
236 /* device name given, use '/' because nothing better */
237 mount_point = newstralloc(mount_point, "/");
242 /* mount point specified */
243 mount_point = newstralloc(mount_point, uqmtpt);
246 /* set the working directory to the mount point */
247 /* there is the possibility that there are no index records for the
248 disk for the given date, hence setting the directory to the
249 mount point will fail. Preempt this by checking first so we can write
250 a more informative message. */
251 if (exchange("OISD /") == -1)
255 disk_path = newstralloc(disk_path, "/");
256 suck_dir_list_from_server(); /* get list of directory contents */
260 g_printf(_("No index records for disk for specified date\n"));
261 g_printf(_("If date correct, notify system administrator\n"));
262 disk_path = newstralloc(disk_path, "/"); /* fake it */
268 if (am_has_feature(indexsrv_features, fe_amindexd_DLE)) {
272 cmd = stralloc("DLE");
273 if (exchange(cmd) == -1)
280 dle_str = reply_line();
281 if (BSTRNCMP(dle_str+4, "NODLE") == 0) {
284 dle_str = unquote_string(dle_str+4);
285 dump_dle = amxml_parse_node_CHAR(dle_str, &errmsg);
295 char *qamdevice, *uqamdevice;
298 uqamdevice = unquote_string(amdevice);
299 qamdevice = quote_string(uqamdevice);
300 cmd = stralloc2("LISTDISK ", qamdevice);
303 if (converse(cmd) == -1)
308 cmd = stralloc("LISTDISK");
309 if (converse(cmd) == -1)
319 char *uqdir = unquote_string(dir);
320 if (chdir(uqdir) == -1) {
335 char *path_on_disk = NULL;
337 if (disk_name == NULL) {
338 g_printf(_("Must select disk before changing directory\n"));
342 uqglob = unquote_string(glob);
343 regex = glob_to_regex(uqglob);
344 dbprintf(_("cd_glob (%s) -> %s\n"), uqglob, regex);
345 if ((s = validate_regexp(regex)) != NULL) {
346 g_printf(_("\"%s\" is not a valid shell wildcard pattern: "), glob);
353 * glob_to_regex() anchors the beginning of the pattern with ^,
354 * but we will be tacking it onto the end of the current directory
355 * in add_file, so strip that off. Also, it anchors the end with
356 * $, but we need to match a trailing /, add it if it is not there
358 regex_path = stralloc(regex + 1);
360 if(regex_path[strlen(regex_path) - 2] != '/' ) {
361 regex_path[strlen(regex_path) - 1] = '\0';
362 strappend(regex_path, "/$");
365 /* convert path (assumed in cwd) to one on disk */
366 if (strcmp(disk_path, "/") == 0)
367 path_on_disk = stralloc2("/", regex_path);
369 char *clean_disk_path = clean_regex(disk_path);
370 path_on_disk = vstralloc(clean_disk_path, "/", regex_path, NULL);
371 amfree(clean_disk_path);
374 cd_dir(path_on_disk, uqglob);
377 amfree(path_on_disk);
390 char *path_on_disk = NULL;
392 if (disk_name == NULL) {
393 g_printf(_("Must select disk before changing directory\n"));
397 uq_orig_regex = unquote_string(regex);
398 uqregex = stralloc(uq_orig_regex);
400 /* Add a terminating '/' if it is not there, maybe before a '$' */
401 len_uqregex = strlen(uqregex);
402 if (uqregex[len_uqregex-1] == '$') {
403 if (uqregex[len_uqregex-2] != '/') {
404 uqregex[len_uqregex-1] = '\0';
405 strappend(uqregex, "/$");
407 } else if (uqregex[len_uqregex-1] != '/') {
408 //uqregex[len_uqregex-1] = '\0';
409 strappend(uqregex, "/");
411 if ((s = validate_regexp(uqregex)) != NULL) {
412 g_printf(_("\"%s\" is not a valid regular expression: "), uq_orig_regex);
414 amfree(uq_orig_regex);
419 /* convert path (assumed in cwd) to one on disk */
420 if (strcmp(disk_path, "/") == 0)
421 path_on_disk = stralloc2("/", uqregex);
423 char *clean_disk_path = clean_regex(disk_path);
424 path_on_disk = vstralloc(clean_disk_path, "/", regex, NULL);
425 amfree(clean_disk_path);
428 cd_dir(path_on_disk, uq_orig_regex);
430 amfree(path_on_disk);
432 amfree(uq_orig_regex);
447 if ((s = validate_regexp(path_on_disk)) != NULL) {
448 set_directory(default_dir);
454 for (ditem=get_dir_list(); ditem!=NULL && nb_found <= 1;
455 ditem=get_next_dir_item(ditem))
457 if (match(path_on_disk, ditem->path))
459 i = strlen(ditem->path);
460 if((i > 0 && ditem->path[i-1] == '/')
461 || (i > 1 && ditem->path[i-2] == '/' && ditem->path[i-1] == '.'))
462 { /* It is a directory */
465 dir = newstralloc(dir,ditem->path);
466 if(dir[strlen(dir)-1] == '/')
467 dir[strlen(dir)-1] = '\0'; /* remove last / */
468 /* remove everything before the last / */
469 dir1 = strrchr(dir,'/');
472 dir2 = stralloc(dir1);
481 set_directory(default_dir);
483 else if(nb_found==1) {
487 g_printf(_("Too many directories\n"));
497 char *new_dir = NULL;
502 /* do nothing if "." */
503 if(strcmp(dir,".")==0) {
504 show_directory(); /* say where we are */
509 if (disk_name == NULL) {
510 g_printf(_("Must select disk before setting directory\n"));
515 ldir = stralloc(dir);
516 clean_pathname(ldir);
518 /* convert directory into absolute path relative to disk mount point */
521 /* absolute path specified, must start with mount point */
522 if (strcmp(mount_point, "/") == 0)
524 new_dir = stralloc(ldir);
528 if (strncmp(mount_point, ldir, strlen(mount_point)) != 0)
530 g_printf(_("Invalid directory - Can't cd outside mount point \"%s\"\n"),
536 new_dir = stralloc(ldir+strlen(mount_point));
537 if (strlen(new_dir) == 0) {
538 new_dir = newstralloc(new_dir, "/");
539 /* i.e. ldir == mount_point */
545 new_dir = stralloc(disk_path);
547 /* strip any leading ..s */
548 while (strncmp(dp, "../", 3) == 0)
550 de = strrchr(new_dir, '/'); /* always at least 1 */
563 if (strcmp(dp, "..") == 0) {
564 if (strcmp(new_dir, "/") == 0) {
566 g_printf(_("Invalid directory - Can't cd outside mount point \"%s\"\n"),
575 de = strrchr(new_dir, '/'); /* always at least 1 */
587 if (strcmp(new_dir, "/") != 0) {
588 strappend(new_dir, "/");
590 strappend(new_dir, ldir);
595 qnew_dir = quote_string(new_dir);
596 cmd = stralloc2("OISD ", qnew_dir);
598 if (exchange(cmd) == -1) {
606 disk_path = newstralloc(disk_path, new_dir);
607 suck_dir_list_from_server(); /* get list of directory contents */
608 show_directory(); /* say where we moved to */
612 g_printf(_("Invalid directory - %s\n"), dir);
622 /* prints the current working directory */
626 if (mount_point == NULL || disk_path == NULL)
627 g_printf(_("Must select disk first\n"));
628 else if (strcmp(mount_point, "/") == 0)
629 g_printf("%s\n", disk_path);
630 else if (strcmp(disk_path, "/") == 0)
631 g_printf("%s\n", mount_point);
633 g_printf("%s%s\n", mount_point, disk_path);
637 /* set the tape server and device (deprecated version) */
642 char *uqtape = unquote_string(tape);
643 char *tapedev = strchr(uqtape, ':');
646 g_printf(_("NOTE: 'settape' is deprecated; use setdevice instead.\n"));
650 /* This command is deprecated because this parsing is going to fall
651 * behind the list of available device names at some point, or to shadow
652 * an interesting hostname (wouldn't 'tape' be a good name for a
654 if (tapedev != uqtape) {
655 if((strchr(tapedev+1, ':') == NULL) &&
656 (strncmp_const(uqtape, "null:") == 0 ||
657 strncmp_const(uqtape, "rait:") == 0 ||
658 strncmp_const(uqtape, "file:") == 0 ||
659 strncmp_const(uqtape, "s3:") == 0 ||
660 strncmp_const(uqtape, "tape:") == 0)) {
665 host = stralloc(uqtape);
676 if (strcmp(tapedev, "default") == 0)
680 /* call out to the new version */
681 set_device(host, tapedev);
687 /* set the tape server and device, for real */
694 tape_server_name = newstralloc(tape_server_name, host);
696 amfree(tape_server_name);
699 tape_device_name = newstralloc(tape_device_name, device);
701 amfree(tape_device_name);
703 /* print the current status */
704 if (tape_device_name)
705 g_printf (_("Using tape \"%s\""), tape_device_name);
707 g_printf (_("Using default tape"));
709 if (tape_server_name)
710 g_printf (_(" from server %s.\n"), tape_server_name);
712 g_printf (_(".\nTape server unspecified, assumed to be %s.\n"),
720 if (mode == SAMBA_SMBCLIENT) {
721 g_printf (_("SAMBA dumps will be extracted using smbclient\n"));
722 samba_extract_method = SAMBA_SMBCLIENT;
724 if (mode == SAMBA_TAR) {
725 g_printf (_("SAMBA dumps will be extracted as TAR dumps\n"));
726 samba_extract_method = SAMBA_TAR;
735 g_printf (_("SAMBA dumps are extracted "));
737 if (samba_extract_method == SAMBA_TAR) {
738 g_printf (_(" as TAR dumps\n"));
740 g_printf (_("using smbclient\n"));
742 #endif /* SAMBA_CLIENT */