Imported Upstream version 3.3.3
[debian/amanda] / oldrecover-src / display_commands.c
1 /*
2  * Amanda, The Advanced Maryland Automatic Network Disk Archiver
3  * Copyright (c) 1991-1998 University of Maryland at College Park
4  * Copyright (c) 2007-2012 Zmanda, Inc.  All Rights Reserved.
5  * All Rights Reserved.
6  *
7  * Permission to use, copy, modify, distribute, and sell this software and its
8  * documentation for any purpose is hereby granted without fee, provided that
9  * the above copyright notice appear in all copies and that both that
10  * copyright notice and this permission notice appear in supporting
11  * documentation, and that the name of U.M. not be used in advertising or
12  * publicity pertaining to distribution of the software without specific,
13  * written prior permission.  U.M. makes no representations about the
14  * suitability of this software for any purpose.  It is provided "as is"
15  * without express or implied warranty.
16  *
17  * U.M. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL U.M.
19  * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
20  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
21  * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
22  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
23  *
24  * Authors: the Amanda Development Team.  Its members are listed in a
25  * file named AUTHORS, in the root directory of this distribution.
26  */
27 /*
28  * $Id: display_commands.c,v 1.3 2006/07/05 19:42:17 martinea Exp $
29  *
30  * implements the directory-display related commands in amrecover
31  */
32
33 #include "amanda.h"
34 #include "amrecover.h"
35 #include "util.h"
36
37 DIR_ITEM *get_dir_list(void);
38 DIR_ITEM *get_next_dir_item(DIR_ITEM *this);
39
40 void clear_dir_list(void);
41 void free_dir_item(DIR_ITEM *item);
42 static int add_dir_list_item(char *date,
43                                 int level,
44                                 char *tape,
45                                 off_t fileno,
46                                 char *path);
47 void list_disk_history(void);
48 void suck_dir_list_from_server(void);
49 void list_directory(void);
50
51 static DIR_ITEM *dir_list = NULL;
52
53 DIR_ITEM *
54 get_dir_list(void)
55 {
56     return dir_list;
57 }
58
59 DIR_ITEM *
60 get_next_dir_item(
61     /*@keep@*/ DIR_ITEM *       this)
62 {
63     return this->next;
64 }
65
66
67 void
68 clear_dir_list(void)
69 {
70     free_dir_item(dir_list); /* Frees all items from dir_list to end of list */
71     dir_list = NULL;
72 }
73
74 void
75 free_dir_item(
76     DIR_ITEM *  item)
77 {
78     DIR_ITEM *next;
79
80     while (item != NULL) {
81         next = item->next;
82         amfree(item->date);
83         amfree(item->tape);
84         amfree(item->path);
85         amfree(item);
86         item = next;
87     }
88 }
89
90 /* add item to list if path not already on list */
91 static int
92 add_dir_list_item(
93     char *      date,
94     int         level,
95     char *      tape,
96     off_t       fileno,
97     char *      path)
98 {
99     DIR_ITEM *next;
100
101     dbprintf(_("add_dir_list_item: Adding \"%s\" \"%d\" \"%s\" \"%lld\" \"%s\"\n"),
102               date, level, tape, (long long)fileno, path);
103
104     next = (DIR_ITEM *)alloc(sizeof(DIR_ITEM));
105     memset(next, 0, sizeof(DIR_ITEM));
106
107     next->date = stralloc(date);
108     next->level = level;
109     next->tape = stralloc(tape);
110     next->fileno = fileno;
111     next->path = stralloc(path);
112
113     next->next = dir_list;
114     dir_list = next;
115
116     return 0;
117 }
118
119
120 void
121 list_disk_history(void)
122 {
123     if (converse("DHST") == -1)
124         exit(1);
125 }
126
127
128 void
129 suck_dir_list_from_server(void)
130 {
131     char *cmd = NULL;
132     char *err = NULL;
133     int i;
134     char *l = NULL;
135     char *date;
136     int level = 0;
137     off_t fileno = (off_t)-1;
138     char *tape, *tape_undo, tape_undo_ch = '\0';
139     char *dir, *qdir;
140     char *disk_path_slash = NULL;
141     char *disk_path_slash_dot = NULL;
142     char *s;
143     int ch;
144
145     if (disk_path == NULL) {
146         g_printf(_("Directory must be set before getting listing\n"));
147         return;
148     } else if(strcmp(disk_path, "/") == 0) {
149         disk_path_slash = stralloc(disk_path);
150     } else {
151         disk_path_slash = stralloc2(disk_path, "/");
152     }
153
154     clear_dir_list();
155
156     cmd = stralloc2("OLSD ", disk_path);
157     if (send_command(cmd) == -1) {
158         amfree(cmd);
159         amfree(disk_path_slash);
160         exit(1);
161     }
162     amfree(cmd);
163     /* skip preamble */
164     if ((i = get_reply_line()) == -1) {
165         amfree(disk_path_slash);
166         exit(1);
167     }
168     if (i == 0)                         /* assume something wrong! */
169     {
170         amfree(disk_path_slash);
171         l = reply_line();
172         g_printf("%s\n", l);
173         return;
174     }
175     disk_path_slash_dot = stralloc2(disk_path_slash, ".");
176     amfree(cmd);
177     amfree(err);
178     tape_undo = NULL;
179     /* skip the last line -- duplicate of the preamble */
180     while ((i = get_reply_line()) != 0)
181     {
182         if (i == -1) {
183             amfree(disk_path_slash_dot);
184             amfree(disk_path_slash);
185             exit(1);
186         }
187         if(err) {
188             if(cmd == NULL) {
189                 if(tape_undo) *tape_undo = tape_undo_ch;
190                 tape_undo = NULL;
191                 cmd = stralloc(l);      /* save for the error report */
192             }
193             continue;                   /* throw the rest of the lines away */
194         }
195         l = reply_line();
196         if (!server_happy())
197         {
198             g_printf("%s\n", l);
199             continue;
200         }
201         s = l;
202         if (strncmp_const_skip(s, "201-", s, ch) != 0) {
203             err = "bad reply: not 201-";
204             continue;
205         }
206         ch = *s++;
207
208         skip_whitespace(s, ch);
209         if(ch == '\0') {
210             err = _("bad reply: missing date field");
211             continue;
212         }
213         date = s - 1;
214         skip_non_whitespace(s, ch);
215         *(s - 1) = '\0';
216
217         skip_whitespace(s, ch);
218         if(ch == '\0' || sscanf(s - 1, "%d", &level) != 1) {
219             err = _("bad reply: cannot parse level field");
220             continue;
221         }
222         skip_integer(s, ch);
223
224         skip_whitespace(s, ch);
225         if(ch == '\0') {
226             err = _("bad reply: missing tape field");
227             continue;
228         }
229         tape = s - 1;
230         skip_non_whitespace(s, ch);
231         tape_undo = s - 1;
232         tape_undo_ch = *tape_undo;
233         *tape_undo = '\0';
234
235         if(am_has_feature(indexsrv_features, fe_amindexd_fileno_in_OLSD)) {
236             long long fileno_ = (long long)0;
237             skip_whitespace(s, ch);
238             if(ch == '\0' || sscanf(s - 1, "%lld", &fileno_) != 1) {
239                 err = _("bad reply: cannot parse fileno field");
240                 continue;
241             }
242             fileno = (off_t)fileno_;
243             skip_integer(s, ch);
244         }
245         else {
246             fileno = (off_t)-1;
247         }
248
249         skip_whitespace(s, ch);
250         if(ch == '\0') {
251             err = _("bad reply: missing directory field");
252             continue;
253         }
254         qdir = s - 1;
255         dir = unquote_string(qdir);
256
257         /* add a '.' if it a the entry for the current directory */
258         if((strcmp(disk_path,dir)==0) || (strcmp(disk_path_slash,dir)==0)) {
259             amfree(dir);
260             dir = stralloc(disk_path_slash_dot);
261         }
262         add_dir_list_item(date, level, tape, fileno, dir);
263         amfree(dir);
264     }
265     amfree(disk_path_slash_dot);
266     amfree(disk_path_slash);
267     if(!server_happy()) {
268         puts(reply_line());
269     } else if(err) {
270         if(*err) {
271             puts(err);
272         }
273         if (cmd)
274            puts(cmd);
275         clear_dir_list();
276     }
277     amfree(cmd);
278 }
279
280
281 void
282 list_directory(void)
283 {
284     size_t i;
285     DIR_ITEM *item;
286     FILE *fp;
287     char *pager;
288     char *pager_command;
289     char *quoted;
290
291     if (disk_path == NULL) {
292         g_printf(_("Must select a disk before listing files; use the setdisk command.\n"));
293         return;
294     }
295
296     if ((pager = getenv("PAGER")) == NULL)
297     {
298         pager = "more";
299     }
300     /*
301      * Set up the pager command so if the pager is terminated, we do
302      * not get a SIGPIPE back.
303      */
304     pager_command = stralloc2(pager, " ; /bin/cat > /dev/null");
305     if ((fp = popen(pager_command, "w")) == NULL)
306     {
307         g_printf(_("Warning - can't pipe through %s\n"), pager);
308         fp = stdout;
309     }
310     amfree(pager_command);
311     i = strlen(disk_path);
312     if (i != 1)
313         i++;                            /* so disk_path != "/" */
314     for (item = get_dir_list(); item != NULL; item=get_next_dir_item(item)) {
315         quoted = quote_string(item->path + i);
316         g_fprintf(fp, "%s %s\n", item->date, quoted);
317         amfree(quoted);
318     }
319     apclose(fp);
320 }