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.
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.
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.
24 * Authors: the Amanda Development Team. Its members are listed in a
25 * file named AUTHORS, in the root directory of this distribution.
28 * $Id: tapelist.c,v 1.8 2006/06/12 15:34:48 martinea Exp $
30 * Support code for amidxtaped and amindexd.
37 * Count the number of entries in this tapelist
41 tapelist_t * tapelist)
46 for(cur_tape = tapelist ; cur_tape ; cur_tape = cur_tape->next)
49 dbprintf("num_entries(tapelist=%p)=%d\n", tapelist, count);
61 dbprintf("dump_tapelist(%p):\n", tapelist);
62 for(cur_tape = tapelist ; cur_tape != NULL ; cur_tape = cur_tape->next) {
63 dbprintf(" %p->next = %p\n", cur_tape, cur_tape->next);
64 dbprintf(" %p->label = %s\n", cur_tape, cur_tape->label);
65 dbprintf(" %p->isafile = %d\n", cur_tape, cur_tape->isafile);
66 dbprintf(" %p->numfiles = %d\n", cur_tape, cur_tape->numfiles);
67 for (file=0; file < cur_tape->numfiles; file++) {
68 dbprintf(" %p->files[%d] = %lld, %p->partnum[%d] = %lld\n",
69 cur_tape, file, (long long)cur_tape->files[file],
70 cur_tape, file, (long long)cur_tape->partnum[file]);
74 dbprintf(" %p count = %d\n", tapelist, count);
78 * Add a tape entry with the given label to the given tapelist, creating a new
79 * tapelist if handed a NULL one. Squashes duplicates.
89 tapelist_t *new_tape, *cur_tape;
92 dbprintf("append_to_tapelist(tapelist=%p, label='%s', file=%lld, partnum=%d, isafile=%d)\n",
93 tapelist, label, (long long)file, partnum, isafile);
95 /* see if we have this tape already, and if so just add to its file list */
96 for(cur_tape = tapelist; cur_tape; cur_tape = cur_tape->next) {
97 if(strcmp(label, cur_tape->label) == 0) {
102 if(file >= (off_t)0) {
103 newfiles = alloc(SIZEOF(*newfiles) *
104 (cur_tape->numfiles + 1));
105 newpartnum = alloc(SIZEOF(*newpartnum) *
106 (cur_tape->numfiles + 1));
107 for(c = 0; c < cur_tape->numfiles ; c++) {
108 if(cur_tape->files[c] > file && c == d_idx) {
109 newfiles[d_idx] = file;
110 newpartnum[d_idx] = partnum;
113 newfiles[d_idx] = cur_tape->files[c];
114 newpartnum[d_idx] = cur_tape->partnum[c];
118 newfiles[d_idx] = file;
119 newpartnum[d_idx] = partnum;
121 cur_tape->numfiles++;
122 amfree(cur_tape->files);
123 amfree(cur_tape->partnum);
124 cur_tape->files = newfiles;
125 cur_tape->partnum = newpartnum;
131 new_tape = alloc(SIZEOF(tapelist_t));
132 memset(new_tape, 0, SIZEOF(tapelist_t));
133 new_tape->label = stralloc(label);
134 if(file >= (off_t)0){
135 new_tape->files = alloc(SIZEOF(*(new_tape->files)));
136 new_tape->files[0] = file;
137 new_tape->partnum = alloc(SIZEOF(*(new_tape->partnum)));
138 new_tape->partnum[0] = partnum;
139 new_tape->numfiles = 1;
140 new_tape->isafile = isafile;
143 /* first instance of anything, start our tapelist with it */
147 /* new tape, tack it onto the end of the list */
149 while (cur_tape->next != NULL)
150 cur_tape = cur_tape->next;
151 cur_tape->next = new_tape;
158 * Backslash-escape all of the commas (and backslashes) in a label string.
164 char *cooked_str, *temp_str;
165 int s_idx = 0, d_idx = 0;
167 if(!label) return(NULL);
169 temp_str = alloc(strlen(label) * 2);
172 if(label[s_idx] == ',' || label[s_idx] == '\\' ||
173 label[s_idx] == ';' || label[s_idx] == ':'){
174 temp_str[d_idx] = '\\';
177 temp_str[d_idx] = label[s_idx];
180 } while(label[s_idx] != '\0');
181 temp_str[d_idx] = '\0';
183 cooked_str = stralloc(temp_str);
190 * Strip out any escape characters (backslashes)
196 char *cooked_str, *temp_str;
197 int s_idx = 0, d_idx = 0, prev_esc = 0;
199 if(!label) return(NULL);
201 temp_str = alloc(strlen(label));
204 if(label[s_idx] == '\\' && !prev_esc){
210 temp_str[d_idx] = label[s_idx];
213 } while(label[s_idx] != '\0');
214 temp_str[d_idx] = '\0';
216 cooked_str = stralloc(temp_str);
223 * Convert a tapelist into a parseable string of tape labels and file numbers.
227 tapelist_t *tapelist,
230 tapelist_t *cur_tape;
233 for(cur_tape = tapelist; cur_tape; cur_tape = cur_tape->next){
235 char *files_str = NULL;
238 if(do_escape) esc_label = escape_label(cur_tape->label);
239 else esc_label = stralloc(cur_tape->label);
241 for(c = 0; c < cur_tape->numfiles ; c++){
242 char num_str[NUM_STR_SIZE];
243 g_snprintf(num_str, SIZEOF(num_str), "%lld",
244 (long long)cur_tape->files[c]);
246 files_str = stralloc(num_str);
248 vstrextend(&files_str, ",", num_str, NULL);
252 str = vstralloc(esc_label, ":", files_str, NULL);
254 vstrextend(&str, ";", esc_label, ":", files_str, NULL);
264 * Convert a previously str-ified and escaped list of tapes back into a
265 * tapelist structure.
268 unmarshal_tapelist_str(
271 char *temp_label, *temp_filenum;
274 tapelist_t *tapelist = NULL;
276 if(!tapelist_str) return(NULL);
278 input_length = strlen(tapelist_str);
280 temp_label = alloc(input_length+1);
281 temp_filenum = alloc(input_length+1);
284 /* first, read the label part */
285 memset(temp_label, '\0', input_length+1);
287 while(*tapelist_str != ':' && *tapelist_str != '\0'){
288 if(*tapelist_str == '\\')
289 tapelist_str++; /* skip escapes */
290 temp_label[l_idx] = *tapelist_str;
291 if(*tapelist_str == '\0')
292 break; /* bad format, should kvetch */
296 if(*tapelist_str != '\0')
298 tapelist = append_to_tapelist(tapelist, temp_label, (off_t)-1, -1, 0);
300 /* now read the list of file numbers */
301 while(*tapelist_str != ';' && *tapelist_str != '\0'){
304 memset(temp_filenum, '\0', input_length+1);
306 while(*tapelist_str != ';' && *tapelist_str != ',' &&
307 *tapelist_str != '\0'){
308 temp_filenum[n_idx] = *tapelist_str;
312 filenum = OFF_T_ATOI(temp_filenum);
314 tapelist = append_to_tapelist(tapelist, temp_label, filenum, -1, 0);
315 if(*tapelist_str != '\0' && *tapelist_str != ';')
318 if(*tapelist_str != '\0')
321 } while(*tapelist_str != '\0');
324 amfree(temp_filenum);
330 * Free up a list of tapes
334 tapelist_t * tapelist)
336 tapelist_t *cur_tape;
337 tapelist_t *prev = NULL;
339 for(cur_tape = tapelist ; cur_tape ; cur_tape = cur_tape->next){
340 amfree(cur_tape->label);
341 amfree(cur_tape->files);
342 amfree(cur_tape->partnum);