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 g_printf(_("No index records for cwd on new date\n"));
70 g_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 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)
222 disk_name = newstralloc(disk_name, uqdsk);
225 /* mount point not specified */
228 /* disk specified by mount point, hence use it */
229 mount_point = newstralloc(mount_point, uqdsk);
233 /* device name given, use '/' because nothing better */
234 mount_point = newstralloc(mount_point, "/");
239 /* mount point specified */
240 mount_point = newstralloc(mount_point, uqmtpt);
243 /* set the working directory to the mount point */
244 /* there is the possibility that there are no index records for the
245 disk for the given date, hence setting the directory to the
246 mount point will fail. Preempt this by checking first so we can write
247 a more informative message. */
248 if (exchange("OISD /") == -1)
252 disk_path = newstralloc(disk_path, "/");
253 suck_dir_list_from_server(); /* get list of directory contents */
257 g_printf(_("No index records for disk for specified date\n"));
258 g_printf(_("If date correct, notify system administrator\n"));
259 disk_path = newstralloc(disk_path, "/"); /* fake it */
271 char *qamdevice, *uqamdevice;
274 uqamdevice = unquote_string(amdevice);
275 qamdevice = quote_string(uqamdevice);
276 cmd = stralloc2("LISTDISK ", qamdevice);
279 if (converse(cmd) == -1)
284 cmd = stralloc("LISTDISK");
285 if (converse(cmd) == -1)
295 char *uqdir = unquote_string(dir);
296 if (chdir(uqdir) == -1) {
311 char *path_on_disk = NULL;
313 if (disk_name == NULL) {
314 g_printf(_("Must select disk before changing directory\n"));
318 uqglob = unquote_string(glob);
319 regex = glob_to_regex(uqglob);
320 dbprintf(_("cd_glob (%s) -> %s\n"), uqglob, regex);
321 if ((s = validate_regexp(regex)) != NULL) {
322 g_printf(_("\"%s\" is not a valid shell wildcard pattern: "), glob);
328 * glob_to_regex() anchors the beginning of the pattern with ^,
329 * but we will be tacking it onto the end of the current directory
330 * in add_file, so strip that off. Also, it anchors the end with
331 * $, but we need to match a trailing /, add it if it is not there
333 regex_path = stralloc(regex + 1);
335 if(regex_path[strlen(regex_path) - 2] != '/' ) {
336 regex_path[strlen(regex_path) - 1] = '\0';
337 strappend(regex_path, "/$");
340 /* convert path (assumed in cwd) to one on disk */
341 if (strcmp(disk_path, "/") == 0)
342 path_on_disk = stralloc2("/", regex_path);
344 char *clean_disk_path = clean_regex(disk_path);
345 path_on_disk = vstralloc(clean_disk_path, "/", regex_path, NULL);
346 amfree(clean_disk_path);
349 cd_dir(path_on_disk, uqglob);
352 amfree(path_on_disk);
365 char *path_on_disk = NULL;
367 if (disk_name == NULL) {
368 g_printf(_("Must select disk before changing directory\n"));
372 uq_orig_regex = unquote_string(regex);
373 uqregex = stralloc(uq_orig_regex);
375 /* Add a terminating '/' if it is not there, maybe before a '$' */
376 len_uqregex = strlen(uqregex);
377 if (uqregex[len_uqregex-1] == '$') {
378 if (uqregex[len_uqregex-2] != '/') {
379 uqregex[len_uqregex-1] = '\0';
380 strappend(uqregex, "/$");
382 } else if (uqregex[len_uqregex-1] != '/') {
383 //uqregex[len_uqregex-1] = '\0';
384 strappend(uqregex, "/");
386 if ((s = validate_regexp(uqregex)) != NULL) {
387 g_printf(_("\"%s\" is not a valid regular expression: "), uq_orig_regex);
393 /* convert path (assumed in cwd) to one on disk */
394 if (strcmp(disk_path, "/") == 0)
395 path_on_disk = stralloc2("/", uqregex);
397 char *clean_disk_path = clean_regex(disk_path);
398 path_on_disk = vstralloc(clean_disk_path, "/", regex, NULL);
399 amfree(clean_disk_path);
402 cd_dir(path_on_disk, uq_orig_regex);
404 amfree(path_on_disk);
406 amfree(uq_orig_regex);
421 if ((s = validate_regexp(path_on_disk)) != NULL) {
422 set_directory(default_dir);
428 for (ditem=get_dir_list(); ditem!=NULL && nb_found <= 1;
429 ditem=get_next_dir_item(ditem))
431 if (match(path_on_disk, ditem->path))
433 i = strlen(ditem->path);
434 if((i > 0 && ditem->path[i-1] == '/')
435 || (i > 1 && ditem->path[i-2] == '/' && ditem->path[i-1] == '.'))
436 { /* It is a directory */
439 dir = newstralloc(dir,ditem->path);
440 if(dir[strlen(dir)-1] == '/')
441 dir[strlen(dir)-1] = '\0'; /* remove last / */
442 /* remove everything before the last / */
443 dir1 = rindex(dir,'/');
446 dir2 = stralloc(dir1);
455 set_directory(default_dir);
457 else if(nb_found==1) {
461 g_printf(_("Too many directories\n"));
471 char *new_dir = NULL;
476 /* do nothing if "." */
477 if(strcmp(dir,".")==0) {
478 show_directory(); /* say where we are */
483 if (disk_name == NULL) {
484 g_printf(_("Must select disk before setting directory\n"));
489 ldir = stralloc(dir);
490 clean_pathname(ldir);
492 /* convert directory into absolute path relative to disk mount point */
495 /* absolute path specified, must start with mount point */
496 if (strcmp(mount_point, "/") == 0)
498 new_dir = stralloc(ldir);
502 if (strncmp(mount_point, ldir, strlen(mount_point)) != 0)
504 g_printf(_("Invalid directory - Can't cd outside mount point \"%s\"\n"),
510 new_dir = stralloc(ldir+strlen(mount_point));
511 if (strlen(new_dir) == 0) {
512 new_dir = newstralloc(new_dir, "/");
513 /* i.e. ldir == mount_point */
519 new_dir = stralloc(disk_path);
521 /* strip any leading ..s */
522 while (strncmp(dp, "../", 3) == 0)
524 de = strrchr(new_dir, '/'); /* always at least 1 */
537 if (strcmp(dp, "..") == 0) {
538 if (strcmp(new_dir, "/") == 0) {
540 g_printf(_("Invalid directory - Can't cd outside mount point \"%s\"\n"),
549 de = strrchr(new_dir, '/'); /* always at least 1 */
561 if (strcmp(new_dir, "/") != 0) {
562 strappend(new_dir, "/");
564 strappend(new_dir, ldir);
569 qnew_dir = quote_string(new_dir);
570 cmd = stralloc2("OISD ", qnew_dir);
572 if (exchange(cmd) == -1) {
580 disk_path = newstralloc(disk_path, new_dir);
581 suck_dir_list_from_server(); /* get list of directory contents */
582 show_directory(); /* say where we moved to */
586 g_printf(_("Invalid directory - %s\n"), dir);
596 /* prints the current working directory */
600 if (mount_point == NULL || disk_path == NULL)
601 g_printf(_("Must select disk first\n"));
602 else if (strcmp(mount_point, "/") == 0)
603 g_printf("%s\n", disk_path);
604 else if (strcmp(disk_path, "/") == 0)
605 g_printf("%s\n", mount_point);
607 g_printf("%s%s\n", mount_point, disk_path);
611 /* set the tape server and device (deprecated version) */
616 char *uqtape = unquote_string(tape);
617 char *tapedev = strchr(uqtape, ':');
620 g_printf(_("NOTE: 'settape' is deprecated; use setdevice instead.\n"));
624 /* This command is deprecated because this parsing is going to fall
625 * behind the list of available device names at some point, or to shadow
626 * an interesting hostname (wouldn't 'tape' be a good name for a
628 if (tapedev != uqtape) {
629 if((strchr(tapedev+1, ':') == NULL) &&
630 (strncmp_const(uqtape, "null:") == 0 ||
631 strncmp_const(uqtape, "rait:") == 0 ||
632 strncmp_const(uqtape, "file:") == 0 ||
633 strncmp_const(uqtape, "s3:") == 0 ||
634 strncmp_const(uqtape, "tape:") == 0)) {
639 host = stralloc(uqtape);
650 if (strcmp(tapedev, "default") == 0)
654 /* call out to the new version */
655 set_device(host, tapedev);
661 /* set the tape server and device, for real */
668 tape_server_name = newstralloc(tape_server_name, host);
670 amfree(tape_server_name);
673 tape_device_name = newstralloc(tape_device_name, device);
675 amfree(tape_device_name);
677 /* print the current status */
678 if (tape_device_name)
679 g_printf (_("Using tape \"%s\""), tape_device_name);
681 g_printf (_("Using default tape"));
683 if (tape_server_name)
684 g_printf (_(" from server %s.\n"), tape_server_name);
686 g_printf (_(".\nTape server unspecified, assumed to be %s.\n"),
695 if (mode == SAMBA_SMBCLIENT) {
696 g_printf (_("SAMBA dumps will be extracted using smbclient\n"));
697 samba_extract_method = SAMBA_SMBCLIENT;
699 if (mode == SAMBA_TAR) {
700 g_printf (_("SAMBA dumps will be extracted as TAR dumps\n"));
701 samba_extract_method = SAMBA_TAR;
705 (void)mode; /* Quiet unused parameter warning */
706 #endif /* SAMBA_CLIENT */
713 g_printf (_("SAMBA dumps are extracted "));
715 if (samba_extract_method == SAMBA_TAR) {
716 g_printf (_(" as TAR dumps\n"));
718 g_printf (_("using smbclient\n"));
720 #endif /* SAMBA_CLIENT */