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;
38 #endif /* SAMBA_CLIENT */
40 /* sets a date, mapping given date into standard form if needed */
50 cmd = stralloc2("DATE ", date);
51 if (converse(cmd) == -1)
54 /* if a host/disk/directory is set, then check if that directory
55 is still valid at the new date, and if not set directory to
57 if (disk_path != NULL) {
58 qdisk_path = quote_string(disk_path);
59 cmd = newstralloc2(cmd, "OISD ", qdisk_path);
61 if (exchange(cmd) == -1)
65 suck_dir_list_from_server();
69 printf("No index records for cwd on new date\n");
70 printf("Setting cwd to mount point\n");
71 disk_path = newstralloc(disk_path, "/"); /* fake it */
85 struct hostent *hp = NULL;
88 char *uqhost = unquote_string(host);
90 if (is_extract_list_nonempty())
92 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 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 printf(_("Trying host %s ...\n"), host);
133 cmd = newstralloc2(cmd, "HOST ", host);
134 if (converse(cmd) == -1)
146 * gethostbyname() will not return a canonical name for a host with no
147 * IPv4 addresses, so use getaddrinfo() (if supported)
151 struct addrinfo hints;
152 struct addrinfo *gaires = NULL;
155 hints.ai_flags = AI_CANONNAME;
156 hints.ai_family = AF_UNSPEC;
157 hints.ai_socktype = 0;
158 hints.ai_protocol = 0;
159 hints.ai_addrlen = 0;
160 hints.ai_addr = NULL;
161 hints.ai_canonname = NULL;
162 hints.ai_next = NULL;
163 if ((res = getaddrinfo(uqhost, NULL, &hints, &gaires)) == 0) {
164 if (gaires && (host = gaires->ai_canonname)) {
165 printf(_("Trying host %s ...\n"), host);
166 cmd = newstralloc2(cmd, "HOST ", host);
167 if (converse(cmd) == -1)
174 if (gaires) freeaddrinfo(gaires);
179 dump_hostname = newstralloc(dump_hostname, host);
194 cmd = stralloc("LISTHOST");
195 if (converse(cmd) == -1)
210 if (is_extract_list_nonempty())
212 printf("Must clear extract list before changing disk\n");
216 /* if mount point specified, check it is valid */
218 uqmtpt = unquote_string(mtpt);
220 printf("Mount point \"%s\" invalid - must start with /\n", uqmtpt);
227 uqdsk = unquote_string(dsk);
228 qdsk = quote_string(uqdsk);
229 cmd = stralloc2("DISK ", qdsk);
231 if (converse(cmd) == -1)
238 disk_name = newstralloc(disk_name, uqdsk);
241 /* mount point not specified */
244 /* disk specified by mount point, hence use it */
245 mount_point = newstralloc(mount_point, uqdsk);
249 /* device name given, use '/' because nothing better */
250 mount_point = newstralloc(mount_point, "/");
255 /* mount point specified */
256 mount_point = newstralloc(mount_point, uqmtpt);
259 /* set the working directory to the mount point */
260 /* there is the possibility that there are no index records for the
261 disk for the given date, hence setting the directory to the
262 mount point will fail. Preempt this by checking first so we can write
263 a more informative message. */
264 if (exchange("OISD /") == -1)
268 disk_path = newstralloc(disk_path, "/");
269 suck_dir_list_from_server(); /* get list of directory contents */
273 printf("No index records for disk for specified date\n");
274 printf("If date correct, notify system administrator\n");
275 disk_path = newstralloc(disk_path, "/"); /* fake it */
287 char *qamdevice, *uqamdevice;
290 uqamdevice = unquote_string(amdevice);
291 qamdevice = quote_string(uqamdevice);
292 cmd = stralloc2("LISTDISK ", qamdevice);
295 if (converse(cmd) == -1)
300 cmd = stralloc("LISTDISK");
301 if (converse(cmd) == -1)
311 char *uqdir = unquote_string(dir);
312 if (chdir(uqdir) == -1) {
327 char *path_on_disk = NULL;
329 if (disk_name == NULL) {
330 printf("Must select disk before changing directory\n");
334 uqglob = unquote_string(glob);
335 regex = glob_to_regex(uqglob);
336 dbprintf(("cd_glob (%s) -> %s\n", uqglob, regex));
337 if ((s = validate_regexp(regex)) != NULL) {
338 printf("\"%s\" is not a valid shell wildcard pattern: ", glob);
344 * glob_to_regex() anchors the beginning of the pattern with ^,
345 * but we will be tacking it onto the end of the current directory
346 * in add_file, so strip that off. Also, it anchors the end with
347 * $, but we need to match a trailing /, add it if it is not there
349 regex_path = stralloc(regex + 1);
351 if(regex_path[strlen(regex_path) - 2] != '/' ) {
352 regex_path[strlen(regex_path) - 1] = '\0';
353 strappend(regex_path, "/$");
356 /* convert path (assumed in cwd) to one on disk */
357 if (strcmp(disk_path, "/") == 0)
358 path_on_disk = stralloc2("/", regex_path);
360 char *clean_disk_path = clean_regex(disk_path);
361 path_on_disk = vstralloc(clean_disk_path, "/", regex_path, NULL);
362 amfree(clean_disk_path);
365 cd_dir(path_on_disk, uqglob);
368 amfree(path_on_disk);
379 char *path_on_disk = NULL;
381 if (disk_name == NULL) {
382 printf("Must select disk before changing directory\n");
386 uqregex = unquote_string(regex);
387 if ((s = validate_regexp(uqregex)) != NULL) {
388 printf("\"%s\" is not a valid regular expression: ", uqregex);
394 /* convert path (assumed in cwd) to one on disk */
395 if (strcmp(disk_path, "/") == 0)
396 path_on_disk = stralloc2("/", regex);
398 char *clean_disk_path = clean_regex(disk_path);
399 path_on_disk = vstralloc(clean_disk_path, "/", regex, NULL);
400 amfree(clean_disk_path);
403 cd_dir(path_on_disk, uqregex);
405 amfree(path_on_disk);
414 char *path_on_disk_slash = NULL;
423 path_on_disk_slash = stralloc2(path_on_disk, "/");
424 if ((s = validate_regexp(path_on_disk_slash)) != NULL) {
425 amfree(path_on_disk_slash);
428 if ((s = validate_regexp(path_on_disk)) != NULL) {
434 for (ditem=get_dir_list(); ditem!=NULL && nb_found <= 1;
435 ditem=get_next_dir_item(ditem))
437 if ((path_on_disk && match(path_on_disk, ditem->path))
438 || (path_on_disk_slash && match(path_on_disk_slash, ditem->path)))
440 i = strlen(ditem->path);
441 if((i > 0 && ditem->path[i-1] == '/')
442 || (i > 1 && ditem->path[i-2] == '/' && ditem->path[i-1] == '.'))
443 { /* It is a directory */
446 dir = newstralloc(dir,ditem->path);
447 if(dir[strlen(dir)-1] == '/')
448 dir[strlen(dir)-1] = '\0'; /* remove last / */
449 /* remove everything before the last / */
450 dir1 = rindex(dir,'/');
453 dir2 = stralloc(dir1);
460 amfree(path_on_disk_slash);
463 set_directory(default_dir);
465 else if(nb_found==1) {
469 printf("Too many directory\n");
479 char *new_dir = NULL;
484 /* do nothing if "." */
485 if(strcmp(dir,".")==0) {
486 show_directory(); /* say where we are */
491 if (disk_name == NULL) {
492 printf("Must select disk before setting directory\n");
497 ldir = stralloc(dir);
498 clean_pathname(ldir);
500 /* convert directory into absolute path relative to disk mount point */
503 /* absolute path specified, must start with mount point */
504 if (strcmp(mount_point, "/") == 0)
506 new_dir = stralloc(ldir);
510 if (strncmp(mount_point, ldir, strlen(mount_point)) != 0)
512 printf("Invalid directory - Can't cd outside mount point \"%s\"\n",
518 new_dir = stralloc(ldir+strlen(mount_point));
519 if (strlen(new_dir) == 0) {
520 new_dir = newstralloc(new_dir, "/");
521 /* i.e. ldir == mount_point */
527 new_dir = stralloc(disk_path);
529 /* strip any leading ..s */
530 while (strncmp(dp, "../", 3) == 0)
532 de = strrchr(new_dir, '/'); /* always at least 1 */
545 if (strcmp(dp, "..") == 0) {
546 if (strcmp(new_dir, "/") == 0) {
548 printf("Invalid directory - Can't cd outside mount point \"%s\"\n",
557 de = strrchr(new_dir, '/'); /* always at least 1 */
569 if (strcmp(new_dir, "/") != 0) {
570 strappend(new_dir, "/");
572 strappend(new_dir, ldir);
577 qnew_dir = quote_string(new_dir);
578 cmd = stralloc2("OISD ", qnew_dir);
580 if (exchange(cmd) == -1) {
588 disk_path = newstralloc(disk_path, new_dir);
589 suck_dir_list_from_server(); /* get list of directory contents */
590 show_directory(); /* say where we moved to */
594 printf("Invalid directory - %s\n", dir);
604 /* prints the current working directory */
608 if (mount_point == NULL || disk_path == NULL)
609 printf("Must select disk first\n");
610 else if (strcmp(mount_point, "/") == 0)
611 printf("%s\n", disk_path);
612 else if (strcmp(disk_path, "/") == 0)
613 printf("%s\n", mount_point);
615 printf("%s%s\n", mount_point, disk_path);
619 /* set the tape server and device */
624 char *uqtape = unquote_string(tape);
625 char *tapedev = strchr(uqtape, ':');
629 if (tapedev != uqtape) {
630 if((strchr(tapedev+1, ':') == NULL) &&
631 (strncmp(uqtape, "null:", 5) == 0 ||
632 strncmp(uqtape, "rait:", 5) == 0 ||
633 strncmp(uqtape, "file:", 5) == 0 ||
634 strncmp(uqtape, "tape:", 5) == 0)) {
639 tape_server_name = newstralloc(tape_server_name, uqtape);
642 } else { /* reset server_name if start with : */
643 amfree(tape_server_name);
651 if (strcmp(tapedev, "default") == 0)
652 amfree(tape_device_name);
654 tape_device_name = newstralloc(tape_device_name, tapedev);
657 if (tape_device_name)
658 printf ("Using tape \"%s\"", tape_device_name);
660 printf ("Using default tape");
662 if (tape_server_name)
663 printf (" from server %s.\n", tape_server_name);
665 printf (".\nTape server unspecified, assumed to be %s.\n",
674 if (mode == SAMBA_SMBCLIENT) {
675 printf ("SAMBA dumps will be extracted using smbclient\n");
676 samba_extract_method = SAMBA_SMBCLIENT;
678 if (mode == SAMBA_TAR) {
679 printf ("SAMBA dumps will be extracted as TAR dumps\n");
680 samba_extract_method = SAMBA_TAR;
684 (void)mode; /* Quiet unused parameter warning */
685 #endif /* SAMBA_CLIENT */
692 printf ("SAMBA dumps are extracted ");
694 if (samba_extract_method == SAMBA_TAR) {
695 printf (" as TAR dumps\n");
697 printf ("using smbclient\n");
699 #endif /* SAMBA_CLIENT */