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