Imported Upstream version 2.6.0
[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  * 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: display_commands.c,v 1.3 2006/07/05 19:42:17 martinea Exp $
28  *
29  * implements the directory-display related commands in amrecover
30  */
31
32 #include "amanda.h"
33 #include "amrecover.h"
34 #include "util.h"
35
36 DIR_ITEM *get_dir_list(void);
37 DIR_ITEM *get_next_dir_item(DIR_ITEM *this);
38
39 void clear_dir_list(void);
40 void free_dir_item(DIR_ITEM *item);
41 static int add_dir_list_item(char *date,
42                                 int level,
43                                 char *tape,
44                                 off_t fileno,
45                                 char *path);
46 void list_disk_history(void);
47 void suck_dir_list_from_server(void);
48 void list_directory(void);
49
50 static DIR_ITEM *dir_list = NULL;
51
52 DIR_ITEM *
53 get_dir_list(void)
54 {
55     return dir_list;
56 }
57
58 DIR_ITEM *
59 get_next_dir_item(
60     /*@keep@*/ DIR_ITEM *       this)
61 {
62     return this->next;
63 }
64
65
66 void
67 clear_dir_list(void)
68 {
69     free_dir_item(dir_list); /* Frees all items from dir_list to end of list */
70     dir_list = NULL;
71 }
72
73 void
74 free_dir_item(
75     DIR_ITEM *  item)
76 {
77     DIR_ITEM *next;
78
79     while (item != NULL) {
80         next = item->next;
81         amfree(item->date);
82         amfree(item->tape);
83         amfree(item->path);
84         amfree(item);
85         item = next;
86     }
87 }
88
89 /* add item to list if path not already on list */
90 static int
91 add_dir_list_item(
92     char *      date,
93     int         level,
94     char *      tape,
95     off_t       fileno,
96     char *      path)
97 {
98     DIR_ITEM *next;
99
100     dbprintf(_("add_dir_list_item: Adding \"%s\" \"%d\" \"%s\" \"%lld\" \"%s\"\n"),
101               date, level, tape, (long long)fileno, path);
102
103     next = (DIR_ITEM *)alloc(sizeof(DIR_ITEM));
104     memset(next, 0, sizeof(DIR_ITEM));
105
106     next->date = stralloc(date);
107     next->level = level;
108     next->tape = stralloc(tape);
109     next->fileno = fileno;
110     next->path = stralloc(path);
111
112     next->next = dir_list;
113     dir_list = next;
114
115     return 0;
116 }
117
118
119 void
120 list_disk_history(void)
121 {
122     if (converse("DHST") == -1)
123         exit(1);
124 }
125
126
127 void
128 suck_dir_list_from_server(void)
129 {
130     char *cmd = NULL;
131     char *err = NULL;
132     int i;
133     char *l = NULL;
134     char *date;
135     int level = 0;
136     off_t fileno = (off_t)-1;
137     char *tape, *tape_undo, tape_undo_ch = '\0';
138     char *dir, *qdir;
139     char *disk_path_slash = NULL;
140     char *disk_path_slash_dot = NULL;
141     char *s;
142     int ch;
143
144     if (disk_path == NULL) {
145         g_printf(_("Directory must be set before getting listing\n"));
146         return;
147     } else if(strcmp(disk_path, "/") == 0) {
148         disk_path_slash = stralloc(disk_path);
149     } else {
150         disk_path_slash = stralloc2(disk_path, "/");
151     }
152
153     clear_dir_list();
154
155     cmd = stralloc2("OLSD ", disk_path);
156     if (send_command(cmd) == -1) {
157         amfree(cmd);
158         amfree(disk_path_slash);
159         exit(1);
160     }
161     amfree(cmd);
162     /* skip preamble */
163     if ((i = get_reply_line()) == -1) {
164         amfree(disk_path_slash);
165         exit(1);
166     }
167     if (i == 0)                         /* assume something wrong! */
168     {
169         amfree(disk_path_slash);
170         l = reply_line();
171         g_printf("%s\n", l);
172         return;
173     }
174     disk_path_slash_dot = stralloc2(disk_path_slash, ".");
175     amfree(cmd);
176     amfree(err);
177     tape_undo = NULL;
178     /* skip the last line -- duplicate of the preamble */
179     while ((i = get_reply_line()) != 0)
180     {
181         if (i == -1) {
182             amfree(disk_path_slash_dot);
183             amfree(disk_path_slash);
184             exit(1);
185         }
186         if(err) {
187             if(cmd == NULL) {
188                 if(tape_undo) *tape_undo = tape_undo_ch;
189                 tape_undo = NULL;
190                 cmd = stralloc(l);      /* save for the error report */
191             }
192             continue;                   /* throw the rest of the lines away */
193         }
194         l = reply_line();
195         if (!server_happy())
196         {
197             g_printf("%s\n", l);
198             continue;
199         }
200         s = l;
201         if (strncmp_const_skip(s, "201-", s, ch) != 0) {
202             err = "bad reply: not 201-";
203             continue;
204         }
205         ch = *s++;
206
207         skip_whitespace(s, ch);
208         if(ch == '\0') {
209             err = _("bad reply: missing date field");
210             continue;
211         }
212         date = s - 1;
213         skip_non_whitespace(s, ch);
214         *(s - 1) = '\0';
215
216         skip_whitespace(s, ch);
217         if(ch == '\0' || sscanf(s - 1, "%d", &level) != 1) {
218             err = _("bad reply: cannot parse level field");
219             continue;
220         }
221         skip_integer(s, ch);
222
223         skip_whitespace(s, ch);
224         if(ch == '\0') {
225             err = _("bad reply: missing tape field");
226             continue;
227         }
228         tape = s - 1;
229         skip_non_whitespace(s, ch);
230         tape_undo = s - 1;
231         tape_undo_ch = *tape_undo;
232         *tape_undo = '\0';
233
234         if(am_has_feature(indexsrv_features, fe_amindexd_fileno_in_OLSD)) {
235             long long fileno_ = (long long)0;
236             skip_whitespace(s, ch);
237             if(ch == '\0' || sscanf(s - 1, "%lld", &fileno_) != 1) {
238                 err = _("bad reply: cannot parse fileno field");
239                 continue;
240             }
241             fileno = (off_t)fileno_;
242             skip_integer(s, ch);
243         }
244         else {
245             fileno = (off_t)-1;
246         }
247
248         skip_whitespace(s, ch);
249         if(ch == '\0') {
250             err = _("bad reply: missing directory field");
251             continue;
252         }
253         qdir = s - 1;
254         dir = unquote_string(qdir);
255
256         /* add a '.' if it a the entry for the current directory */
257         if((strcmp(disk_path,dir)==0) || (strcmp(disk_path_slash,dir)==0)) {
258             amfree(dir);
259             dir = stralloc(disk_path_slash_dot);
260         }
261         add_dir_list_item(date, level, tape, fileno, dir);
262         amfree(dir);
263     }
264     amfree(disk_path_slash_dot);
265     amfree(disk_path_slash);
266     if(!server_happy()) {
267         puts(reply_line());
268     } else if(err) {
269         if(*err) {
270             puts(err);
271         }
272         if (cmd)
273            puts(cmd);
274         clear_dir_list();
275     }
276     amfree(cmd);
277 }
278
279
280 void
281 list_directory(void)
282 {
283     size_t i;
284     DIR_ITEM *item;
285     FILE *fp;
286     char *pager;
287     char *pager_command;
288     char *quoted;
289
290     if (disk_path == NULL) {
291         g_printf(_("Must select a disk before listing files; use the setdisk command.\n"));
292         return;
293     }
294
295     if ((pager = getenv("PAGER")) == NULL)
296     {
297         pager = "more";
298     }
299     /*
300      * Set up the pager command so if the pager is terminated, we do
301      * not get a SIGPIPE back.
302      */
303     pager_command = stralloc2(pager, " ; /bin/cat > /dev/null");
304     if ((fp = popen(pager_command, "w")) == NULL)
305     {
306         g_printf(_("Warning - can't pipe through %s\n"), pager);
307         fp = stdout;
308     }
309     amfree(pager_command);
310     i = strlen(disk_path);
311     if (i != 1)
312         i++;                            /* so disk_path != "/" */
313     for (item = get_dir_list(); item != NULL; item=get_next_dir_item(item)) {
314         quoted = quote_string(item->path + i);
315         g_fprintf(fp, "%s %s\n", item->date, quoted);
316         amfree(quoted);
317     }
318     apclose(fp);
319 }