8d39cab6b5bbdd36c9b18c94b88bd2e3388a9c4d
[debian/amanda] / common-src / tapelist.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: tapelist.c,v 1.3 2006/01/15 21:00:59 martinea Exp $
28  *
29  * Support code for amidxtaped and amindexd.
30  */
31
32 #include "amanda.h"
33 #include "tapelist.h"
34
35 /*
36  * Count the number of entries in this tapelist
37  */
38 int num_entries (tapelist)
39 tapelist_t *tapelist;
40 {
41     tapelist_t *cur_tape;
42     int count = 0;
43
44     for(cur_tape = tapelist ; cur_tape ; cur_tape = cur_tape->next) count++;
45
46     return(count);
47 }
48
49 /*
50  * Add a tape entry with the given label to the given tapelist, creating a new
51  * tapelist if handed a NULL one.  Squashes duplicates.
52  */
53 tapelist_t *append_to_tapelist (tapelist, label, file, isafile)
54 tapelist_t *tapelist;
55 char *label;
56 int file, isafile;
57 {
58     tapelist_t *new_tape, *cur_tape;
59     int c;
60
61     /* see if we have this tape already, and if so just add to its file list */
62     for(cur_tape = tapelist; cur_tape; cur_tape = cur_tape->next){
63         if(!strcmp(label, cur_tape->label)){
64             int d_idx = 0;
65             int *newfiles;
66             if(file >= 0){
67                 newfiles = alloc(sizeof(int) * (cur_tape->numfiles + 1));
68                 for(c = 0; c < cur_tape->numfiles ; c++){
69                     if(cur_tape->files[c] > file && c == d_idx){
70                         newfiles[d_idx] = file;
71                         d_idx++;
72                     }
73                     newfiles[d_idx] = cur_tape->files[c];
74                     d_idx++;
75                 }
76                 if(c == d_idx) newfiles[d_idx] = file;
77                 cur_tape->numfiles++;
78                 amfree(cur_tape->files);
79                 cur_tape->files = newfiles;
80             }
81             return(tapelist);
82         }
83     }
84
85     new_tape = alloc(sizeof(tapelist_t));
86     memset(new_tape, 0, sizeof(tapelist_t));
87     new_tape->label = stralloc(label);
88     if(file >= 0){
89         new_tape->files = alloc(sizeof(int));
90         new_tape->files[0] = file;
91         new_tape->numfiles = 1;
92         new_tape->isafile = isafile;
93     }
94
95     /* first instance of anything, start our tapelist with it */
96     if(!tapelist){
97         tapelist = new_tape;
98         return(tapelist);
99     }
100
101     /* new tape, tack it onto the end of the list */
102     for(cur_tape = tapelist; cur_tape->next; cur_tape = cur_tape->next);
103     cur_tape->next = new_tape;
104
105     return(tapelist);
106 }
107
108 /*
109  * Backslash-escape all of the commas (and backslashes) in a label string.
110  */
111 char *escape_label (label)
112 char *label;
113 {
114     char *cooked_str, *temp_str;
115     int s_idx = 0, d_idx = 0;
116
117     if(!label) return(NULL);
118
119     temp_str = alloc(strlen(label) * 2);
120
121     do{
122         if(label[s_idx] == ',' || label[s_idx] == '\\' ||
123                 label[s_idx] == ';' || label[s_idx] == ':'){
124             temp_str[d_idx] = '\\';
125             d_idx++;
126         }
127         temp_str[d_idx] = label[s_idx];
128         s_idx++;
129         d_idx++;
130     } while(label[s_idx] != '\0');
131     temp_str[d_idx] = '\0';
132
133     cooked_str = stralloc(temp_str);
134     amfree(temp_str);
135     
136     return(cooked_str);
137 }
138
139 /*
140  * Strip out any escape characters (backslashes)
141  */
142 char *unescape_label(label)
143 char *label;
144 {
145     char *cooked_str, *temp_str;
146     int s_idx = 0, d_idx = 0, prev_esc = 0;
147     
148     if(!label) return(NULL);
149
150     temp_str = alloc(strlen(label));
151
152     do{
153         if(label[s_idx] == '\\' && !prev_esc){
154             s_idx++;
155             prev_esc = 1;
156             continue;
157         }
158         prev_esc = 0;
159         temp_str[d_idx] = label[s_idx];
160         s_idx++;
161         d_idx++;
162     } while(label[s_idx] != '\0');
163     temp_str[d_idx] = '\0';
164
165     cooked_str = stralloc(temp_str);
166     amfree(temp_str);
167     
168     return(cooked_str);
169 }
170
171 /*
172  * Convert a tapelist into a parseable string of tape labels and file numbers.
173  */
174 char *marshal_tapelist (tapelist, do_escape)
175 tapelist_t *tapelist;
176 int do_escape;
177 {
178     tapelist_t *cur_tape;
179     char *str = NULL;
180
181     for(cur_tape = tapelist; cur_tape; cur_tape = cur_tape->next){
182         char *esc_label;
183         char *files_str = NULL;
184         int c;
185
186         if(do_escape) esc_label = escape_label(cur_tape->label);
187         else esc_label = stralloc(cur_tape->label);
188
189         for(c = 0; c < cur_tape->numfiles ; c++){
190             char num_str[NUM_STR_SIZE];
191             snprintf(num_str, sizeof(num_str), "%d", cur_tape->files[c]);
192             if(!files_str) files_str = stralloc(num_str);
193             else files_str = vstralloc(files_str, ",", num_str, NULL);
194         }
195
196         if(!str) str = vstralloc(esc_label, ":", files_str, NULL);
197         else str = vstralloc(str, ";", esc_label, ":", files_str, NULL);
198
199         amfree(esc_label);
200         amfree(files_str);
201     }
202
203     return(str);
204 }
205
206 /*
207  * Convert a previously str-ified and escaped list of tapes back into a
208  * tapelist structure.
209  */
210 tapelist_t *unmarshal_tapelist_str (tapelist_str)
211 char *tapelist_str;
212 {
213     char *temp_label, *temp_filenum;
214     int l_idx, n_idx, input_length;
215     tapelist_t *tapelist = NULL;
216
217     if(!tapelist_str) return(NULL);
218
219     input_length = strlen(tapelist_str);
220
221     temp_label = alloc(input_length+1);
222     temp_filenum = alloc(input_length+1);
223
224     do{
225         /* first, read the label part */
226         memset(temp_label, '\0', input_length+1);
227         l_idx = 0;
228         while(*tapelist_str != ':' && *tapelist_str != '\0'){
229             if(*tapelist_str == '\\') *tapelist_str++; /* skip escapes */
230             temp_label[l_idx] = *tapelist_str;
231             if(*tapelist_str == '\0') break; /* bad format, should kvetch */
232             *tapelist_str++;
233             l_idx++;
234         }
235         if(*tapelist_str != '\0') *tapelist_str++;
236         tapelist = append_to_tapelist(tapelist, temp_label, -1, 0);
237
238         /* now read the list of file numbers */
239         while(*tapelist_str != ';' && *tapelist_str != '\0'){
240             int filenum = -1;
241             memset(temp_filenum, '\0', input_length+1);
242             n_idx = 0;
243             while(*tapelist_str != ';' && *tapelist_str != ',' &&
244                     *tapelist_str != '\0'){
245                 temp_filenum[n_idx] = *tapelist_str; 
246                 *tapelist_str++;
247                 n_idx++;
248             }
249             filenum = atoi(temp_filenum);
250
251             tapelist = append_to_tapelist(tapelist, temp_label, filenum, 0);
252             if(*tapelist_str != '\0' && *tapelist_str != ';') *tapelist_str++;
253         }
254         if(*tapelist_str != '\0') *tapelist_str++;
255
256     } while(*tapelist_str != '\0');
257
258     amfree(temp_label);
259     amfree(temp_filenum);
260
261     return(tapelist);
262 }
263
264 /*
265  * Free up a list of tapes
266  */
267 void free_tapelist (tapelist)
268 tapelist_t *tapelist;
269 {
270     tapelist_t *cur_tape;
271     tapelist_t *prev = NULL;
272
273     for(cur_tape = tapelist ; cur_tape ; cur_tape = cur_tape->next){
274         if(cur_tape->label) amfree(cur_tape->label);
275         if(cur_tape->files) amfree(cur_tape->files);
276         if(prev) amfree(prev);
277         prev = cur_tape;
278     }
279     if(prev) amfree(prev);
280
281 }