Imported Upstream version 2.5.2p1
[debian/amanda] / oldrecover-src / set_commands.c
1 /*
2  * Amanda, The Advanced Maryland Automatic Network Disk Archiver
3  * Copyright (c) 1991-1998, 2000 University of Maryland at College Park
4  * All Rights Reserved.
5  *
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.
15  *
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.
22  *
23  * Authors: the Amanda Development Team.  Its members are listed in a
24  * file named AUTHORS, in the root directory of this distribution.
25  */
26 /*
27  * $Id: set_commands.c,v 1.3 2006/07/05 13:14:58 martinea Exp $
28  *
29  * implements the "set" commands in amrecover
30  */
31
32 #include "amanda.h"
33 #include "util.h"
34 #include "amrecover.h"
35
36 #ifdef SAMBA_CLIENT
37 extern unsigned short samba_extract_method;
38 #endif /* SAMBA_CLIENT */
39
40 /* sets a date, mapping given date into standard form if needed */
41 int
42 set_date(
43     char *      date)
44 {
45     char *cmd = NULL;
46
47     clear_dir_list();
48
49     cmd = stralloc2("DATE ", date);
50     if (converse(cmd) == -1)
51         exit(1);
52
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
55        mount_point */
56     if (disk_path != NULL) {
57         cmd = newstralloc2(cmd, "OISD ", disk_path);
58         if (exchange(cmd) == -1)
59             exit(1);
60         if (server_happy())
61         {
62             suck_dir_list_from_server();
63         }
64         else
65         {
66             printf("No index records for cwd on new date\n");
67             printf("Setting cwd to mount point\n");
68             disk_path = newstralloc(disk_path, "/");    /* fake it */
69             clear_dir_list();
70         }
71     }
72     amfree(cmd);
73     return 0;
74 }
75
76
77 void
78 set_host(
79     const char *        host)
80 {
81     char *cmd = NULL;
82     struct hostent *hp;
83     char **hostp;
84     int found_host = 0;
85     char *uqhost = unquote_string(host);
86
87     if (is_extract_list_nonempty())
88     {
89         printf("Must clear extract list before changing host\n");
90         return;
91     }
92
93     cmd = stralloc2("HOST ", uqhost);
94     if (converse(cmd) == -1)
95         exit(1);
96     if (server_happy())
97     {
98         found_host = 1;
99     }
100     else
101     {
102         /*
103          * Try converting the given host to a fully qualified name
104          * and then try each of the aliases.
105          */
106         if ((hp = gethostbyname(uqhost)) != NULL) {
107             host = hp->h_name;
108             printf("Trying host %s ...\n", host);
109             cmd = newstralloc2(cmd, "HOST ", host);
110             if (converse(cmd) == -1)
111                 exit(1);
112             if(server_happy())
113             {
114                 found_host = 1;
115             }
116             else
117             {
118                 for (hostp = hp->h_aliases; (host = *hostp) != NULL; hostp++)
119                 {
120                     printf("Trying host %s ...\n", host);
121                     cmd = newstralloc2(cmd, "HOST ", host);
122                     if (converse(cmd) == -1)
123                         exit(1);
124                     if(server_happy())
125                     {
126                         found_host = 1;
127                         break;
128                     }
129                 }
130             }
131         }
132     }
133     if(found_host)
134     {
135         dump_hostname = newstralloc(dump_hostname, host);
136         amfree(disk_name);
137         amfree(mount_point);
138         amfree(disk_path);
139         clear_dir_list();
140     }
141     amfree(cmd);
142     amfree(uqhost);
143 }
144
145
146 void
147 list_host(void)
148 {
149     char *cmd = NULL;
150
151     cmd = stralloc("LISTHOST");
152     if (converse(cmd) == -1)
153         exit(1);
154     amfree(cmd);
155 }
156
157 void
158 set_disk(
159     char *      dsk,
160     char *      mtpt)
161 {
162     char *cmd = NULL;
163     char *uqdsk;
164     char *uqmtpt = NULL;
165
166     if (is_extract_list_nonempty())
167     {
168         printf("Must clear extract list before changing disk\n");
169         return;
170     }
171
172     /* if mount point specified, check it is valid */
173     if (mtpt != NULL) {
174         uqmtpt = unquote_string(mtpt);
175         if (*mtpt != '/') {
176             printf("Mount point \"%s\" invalid - must start with /\n", uqmtpt);
177             amfree(uqmtpt);
178             return;
179         }
180     }
181
182     clear_dir_list();
183     uqdsk = unquote_string(dsk);
184     cmd = stralloc2("DISK ", uqdsk);
185     if (converse(cmd) == -1)
186         exit(1);
187     amfree(cmd);
188
189     if (!server_happy())
190         return;
191
192     disk_name = newstralloc(disk_name, uqdsk);
193     if (mtpt == NULL)
194     {
195         /* mount point not specified */
196         if (*uqdsk == '/')
197         {
198             /* disk specified by mount point, hence use it */
199             mount_point = newstralloc(mount_point, uqdsk);
200         }
201         else
202         {
203             /* device name given, use '/' because nothing better */
204             mount_point = newstralloc(mount_point, "/");
205         }
206     }
207     else
208     {
209         /* mount point specified */
210         mount_point = newstralloc(mount_point, uqmtpt);
211     }
212
213     /* set the working directory to the mount point */
214     /* there is the possibility that there are no index records for the
215        disk for the given date, hence setting the directory to the
216        mount point will fail. Preempt this by checking first so we can write
217        a more informative message. */
218     if (exchange("OISD /") == -1)
219         exit(1);
220     if (server_happy())
221     {
222         disk_path = newstralloc(disk_path, "/");
223         suck_dir_list_from_server();    /* get list of directory contents */
224     }
225     else
226     {
227         printf("No index records for disk for specified date\n");
228         printf("If date correct, notify system administrator\n");
229         disk_path = newstralloc(disk_path, "/");        /* fake it */
230         clear_dir_list();
231     }
232     amfree(uqmtpt);
233     amfree(uqdsk);
234 }
235
236 void
237 list_disk(
238     char *      amdevice)
239 {
240     char *cmd = NULL;
241     char *uqamdevice;
242
243     if(amdevice) {
244         uqamdevice = unquote_string(amdevice);
245         cmd = stralloc2("LISTDISK ", uqamdevice);
246         amfree(uqamdevice);
247         if (converse(cmd) == -1)
248             exit(1);
249         amfree(cmd);
250     }
251     else {
252         cmd = stralloc("LISTDISK");
253         if (converse(cmd) == -1)
254             exit(1);
255         amfree(cmd);
256     }
257 }
258
259 void
260 local_cd(
261     char *dir)
262 {
263     char *uqdir = unquote_string(dir);
264     if (chdir(uqdir) == -1) {
265         perror(uqdir);
266     }
267     amfree(uqdir);
268 }
269
270 void
271 cd_glob(
272     char *      glob)
273 {
274     char *regex;
275     char *regex_path;
276     char *s;
277     char *uqglob;
278
279     char *path_on_disk = NULL;
280
281     if (disk_name == NULL) {
282         printf("Must select disk before changing directory\n");
283         return;
284     }
285
286     uqglob = unquote_string(glob);
287     regex = glob_to_regex(uqglob);
288     dbprintf(("cd_glob (%s) -> %s\n", uqglob, regex));
289     if ((s = validate_regexp(regex)) != NULL) {
290         printf("\"%s\" is not a valid shell wildcard pattern: ", glob);
291         puts(s);
292         amfree(regex);
293         return;
294     }
295     /*
296      * glob_to_regex() anchors the beginning of the pattern with ^,
297      * but we will be tacking it onto the end of the current directory
298      * in add_file, so strip that off.  Also, it anchors the end with
299      * $, but we need to match a trailing /, add it if it is not there
300      */
301     regex_path = stralloc(regex + 1);
302     amfree(regex);
303     if(regex_path[strlen(regex_path) - 2] != '/' ) {
304         regex_path[strlen(regex_path) - 1] = '\0';
305         strappend(regex_path, "/$");
306     }
307
308     /* convert path (assumed in cwd) to one on disk */
309     if (strcmp(disk_path, "/") == 0)
310         path_on_disk = stralloc2("/", regex_path);
311     else {
312         char *clean_disk_path = clean_regex(disk_path);
313         path_on_disk = vstralloc(clean_disk_path, "/", regex_path, NULL);
314         amfree(clean_disk_path);
315     }
316
317     cd_dir(path_on_disk, uqglob);
318
319     amfree(regex_path);
320     amfree(path_on_disk);
321     amfree(uqglob);
322 }
323
324 void
325 cd_regex(
326     char *      regex)
327 {
328     char *s;
329     char *uqregex;
330
331     char *path_on_disk = NULL;
332
333     if (disk_name == NULL) {
334         printf("Must select disk before changing directory\n");
335         return;
336     }
337
338     uqregex = unquote_string(regex);
339     if ((s = validate_regexp(uqregex)) != NULL) {
340         printf("\"%s\" is not a valid regular expression: ", uqregex);
341         amfree(uqregex);
342         puts(s);
343         return;
344     }
345
346     /* convert path (assumed in cwd) to one on disk */
347     if (strcmp(disk_path, "/") == 0)
348         path_on_disk = stralloc2("/", regex);
349     else {
350         char *clean_disk_path = clean_regex(disk_path);
351         path_on_disk = vstralloc(clean_disk_path, "/", regex, NULL);
352         amfree(clean_disk_path);
353     }
354
355     cd_dir(path_on_disk, uqregex);
356
357     amfree(path_on_disk);
358     amfree(uqregex);
359 }
360
361 void
362 cd_dir(
363     char *      path_on_disk,
364     char *      default_dir)
365 {
366     char *path_on_disk_slash = NULL;
367     char *dir = NULL;
368
369     int nb_found;
370     size_t i;
371
372     DIR_ITEM *ditem;
373
374     path_on_disk_slash = stralloc2(path_on_disk, "/");
375
376     nb_found = 0;
377
378     for (ditem=get_dir_list(); ditem!=NULL && nb_found <= 1; 
379                                ditem=get_next_dir_item(ditem))
380     {
381         if (match(path_on_disk, ditem->path)
382             || match(path_on_disk_slash, ditem->path))
383         {
384             i = strlen(ditem->path);
385             if((i > 0 && ditem->path[i-1] == '/')
386                || (i > 1 && ditem->path[i-2] == '/' && ditem->path[i-1] == '.'))
387             {   /* It is a directory */
388                 char *dir1, *dir2;
389                 nb_found++;
390                 dir = newstralloc(dir,ditem->path);
391                 if(dir[strlen(dir)-1] == '/')
392                     dir[strlen(dir)-1] = '\0'; /* remove last / */
393                 /* remove everything before the last / */
394                 dir1 = rindex(dir,'/');
395                 if (dir1) {
396                     dir1++;
397                     dir2 = stralloc(dir1);
398                     amfree(dir);
399                     dir = dir2;
400                 }
401             }
402         }
403     }
404     amfree(path_on_disk_slash);
405
406     if(nb_found==0) {
407         set_directory(default_dir);
408     }
409     else if(nb_found==1) {
410         set_directory(dir);
411     }
412     else {
413         printf("Too many directory\n");
414     }
415     amfree(dir);
416 }
417
418 void
419 set_directory(
420     char *      dir)
421 {
422     char *cmd = NULL;
423     char *new_dir = NULL;
424     char *dp, *de;
425     char *ldir = NULL;
426
427     /* do nothing if "." */
428     if(strcmp(dir,".")==0) {
429         show_directory();               /* say where we are */
430         return;
431         /*NOTREACHED*/
432     }
433
434     if (disk_name == NULL) {
435         printf("Must select disk before setting directory\n");
436         return;
437         /*NOTREACHED*/
438     }
439
440     ldir = stralloc(dir);
441     clean_pathname(ldir);
442
443     /* convert directory into absolute path relative to disk mount point */
444     if (ldir[0] == '/')
445     {
446         /* absolute path specified, must start with mount point */
447         if (strcmp(mount_point, "/") == 0)
448         {
449             new_dir = stralloc(ldir);
450         }
451         else
452         {
453             if (strncmp(mount_point, ldir, strlen(mount_point)) != 0)
454             {
455                 printf("Invalid directory - Can't cd outside mount point \"%s\"\n",
456                        mount_point);
457                 amfree(ldir);
458                 return;
459                 /*NOTREACHED*/
460             }
461             new_dir = stralloc(ldir+strlen(mount_point));
462             if (strlen(new_dir) == 0) {
463                 new_dir = newstralloc(new_dir, "/");
464                                         /* i.e. ldir == mount_point */
465             }
466         }
467     }
468     else
469     {
470         new_dir = stralloc(disk_path);
471         dp = ldir;
472         /* strip any leading ..s */
473         while (strncmp(dp, "../", 3) == 0)
474         {
475             de = strrchr(new_dir, '/'); /* always at least 1 */
476             if (de == new_dir)
477             {
478                 /* at top of disk */
479                 *(de + 1) = '\0';
480                 dp = dp + 3;
481             }
482             else
483             {
484                 *de = '\0';
485                 dp = dp + 3;
486             }
487         }
488         if (strcmp(dp, "..") == 0) {
489             if (strcmp(new_dir, "/") == 0) {
490                 /* at top of disk */
491                 printf("Invalid directory - Can't cd outside mount point \"%s\"\n",
492                        mount_point);
493                 /*@ignore@*/
494                 amfree(new_dir);
495                 /*@end@*/
496                 amfree(ldir);
497                 return;
498                 /*NOTREACHED*/
499             }
500             de = strrchr(new_dir, '/'); /* always at least 1 */
501             if (de == new_dir)
502             {
503                 /* at top of disk */
504                 *(de+1) = '\0';
505             }
506             else
507             {
508                 *de = '\0';
509             }
510         } else {
511             /*@ignore@*/
512             if (strcmp(new_dir, "/") != 0) {
513                 strappend(new_dir, "/");
514             }
515             strappend(new_dir, ldir);
516             /*@end@*/
517         }
518     }
519
520     cmd = stralloc2("OISD ", new_dir);
521     if (exchange(cmd) == -1) {
522         exit(1);
523         /*NOTREACHED*/
524     }
525     amfree(cmd);
526
527     if (server_happy())
528     {
529         disk_path = newstralloc(disk_path, new_dir);
530         suck_dir_list_from_server();    /* get list of directory contents */
531         show_directory();               /* say where we moved to */
532     }
533     else
534     {
535         printf("Invalid directory - %s\n", dir);
536     }
537
538     /*@ignore@*/
539     amfree(new_dir);
540     amfree(ldir);
541     /*@end@*/
542 }
543
544
545 /* prints the current working directory */
546 void
547 show_directory(void)
548 {
549     if (mount_point == NULL || disk_path == NULL)
550         printf("Must select disk first\n");
551     else if (strcmp(mount_point, "/") == 0)
552         printf("%s\n", disk_path);
553     else if (strcmp(disk_path, "/") == 0)
554         printf("%s\n", mount_point);
555     else
556         printf("%s%s\n", mount_point, disk_path);
557 }
558
559
560 /* set the tape server and device */
561 void
562 set_tape(
563     char *      tape)
564 {
565     char *uqtape = unquote_string(tape);
566     char *tapedev = strchr(uqtape, ':');
567
568     if (tapedev)
569     {
570         if (tapedev != uqtape) {
571             if((strchr(tapedev+1, ':') == NULL) &&
572                (strncmp(uqtape, "null:", 5) == 0 ||
573                 strncmp(uqtape, "rait:", 5) == 0 ||
574                 strncmp(uqtape, "file:", 5) == 0 ||
575                 strncmp(uqtape, "tape:", 5) == 0)) {
576                 tapedev = uqtape;
577             }
578             else {
579                 *tapedev = '\0';
580                 tape_server_name = newstralloc(tape_server_name, uqtape);
581                 ++tapedev;
582             }
583         } else { /* reset server_name if start with : */
584             amfree(tape_server_name);
585             ++tapedev;
586         }
587     } else
588         tapedev = uqtape;
589     
590     if (tapedev[0])
591     {
592         if (strcmp(tapedev, "default") == 0)
593             amfree(tape_device_name);
594         else
595             tape_device_name = newstralloc(tape_device_name, tapedev);
596     }
597
598     if (tape_device_name)
599         printf ("Using tape \"%s\"", tape_device_name);
600     else
601         printf ("Using default tape");
602
603     if (tape_server_name)
604         printf (" from server %s.\n", tape_server_name);
605     else
606         printf (".\nTape server unspecified, assumed to be %s.\n",
607                 server_name);
608 }
609
610 void
611 set_mode(
612     int         mode)
613 {
614 #ifdef SAMBA_CLIENT
615   if (mode == SAMBA_SMBCLIENT) {
616     printf ("SAMBA dumps will be extracted using smbclient\n");
617     samba_extract_method = SAMBA_SMBCLIENT;
618   } else {
619     if (mode == SAMBA_TAR) {
620       printf ("SAMBA dumps will be extracted as TAR dumps\n");
621       samba_extract_method = SAMBA_TAR;
622     }
623   }
624 #else
625   (void)mode;   /* Quiet unused parameter warning */
626 #endif /* SAMBA_CLIENT */
627 }
628
629 void
630 show_mode(void) 
631 {
632 #ifdef SAMBA_CLIENT
633   printf ("SAMBA dumps are extracted ");
634
635   if (samba_extract_method == SAMBA_TAR) {
636     printf (" as TAR dumps\n");
637   } else {
638     printf ("using smbclient\n");
639   }
640 #endif /* SAMBA_CLIENT */
641 }