2 * Amanda, The Advanced Maryland Automatic Network Disk Archiver
3 * Copyright (c) 1991-1998 University of Maryland at College Park
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.
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.
23 * Authors: the Amanda Development Team. Its members are listed in a
24 * file named AUTHORS, in the root directory of this distribution.
28 * $Id: amfeatures.c,v 1.24 2006/07/19 17:46:07 martinea Exp $
30 * Feature test related code.
34 #include "amfeatures.h"
37 *=====================================================================
38 * Initialize the base feature set for this version of Amanda.
40 * am_feature_t *am_init_feature_set()
43 * exit: dynamically allocated feature set structure
44 *=====================================================================
48 am_init_feature_set(void)
52 if ((f = am_allocate_feature_set()) != NULL) {
54 * Whenever a new feature is added, a new line usually needs
55 * to be added here to show that we support it.
57 am_add_feature(f, have_feature_support);
58 am_add_feature(f, fe_options_auth);
60 am_add_feature(f, fe_selfcheck_req);
61 am_add_feature(f, fe_selfcheck_req_device);
62 am_add_feature(f, fe_selfcheck_rep);
63 am_add_feature(f, fe_sendsize_req_no_options);
64 am_add_feature(f, fe_sendsize_req_options);
65 am_add_feature(f, fe_sendsize_req_device);
66 am_add_feature(f, fe_sendsize_rep);
67 am_add_feature(f, fe_sendbackup_req);
68 am_add_feature(f, fe_sendbackup_req_device);
69 am_add_feature(f, fe_sendbackup_rep);
70 am_add_feature(f, fe_noop_req);
71 am_add_feature(f, fe_noop_rep);
73 am_add_feature(f, fe_program_dump);
74 am_add_feature(f, fe_program_gnutar);
75 am_add_feature(f, fe_program_backup_api);
77 am_add_feature(f, fe_options_compress_fast);
78 am_add_feature(f, fe_options_compress_best);
79 am_add_feature(f, fe_options_srvcomp_fast);
80 am_add_feature(f, fe_options_srvcomp_best);
81 am_add_feature(f, fe_options_no_record);
82 am_add_feature(f, fe_options_bsd_auth);
83 am_add_feature(f, fe_options_index);
84 am_add_feature(f, fe_options_exclude_file);
85 am_add_feature(f, fe_options_exclude_list);
86 am_add_feature(f, fe_options_multiple_exclude);
87 am_add_feature(f, fe_options_optional_exclude);
88 am_add_feature(f, fe_options_include_file);
89 am_add_feature(f, fe_options_include_list);
90 am_add_feature(f, fe_options_multiple_include);
91 am_add_feature(f, fe_options_optional_include);
92 am_add_feature(f, fe_options_krb4_auth);
93 am_add_feature(f, fe_options_kencrypt);
95 am_add_feature(f, fe_req_options_maxdumps);
96 am_add_feature(f, fe_req_options_hostname);
97 am_add_feature(f, fe_req_options_features);
99 am_add_feature(f, fe_rep_options_features);
101 am_add_feature(f, fe_amindexd_fileno_in_OLSD);
102 am_add_feature(f, fe_amindexd_fileno_in_ORLD);
103 am_add_feature(f, fe_amidxtaped_fsf);
104 am_add_feature(f, fe_amidxtaped_label);
105 am_add_feature(f, fe_amidxtaped_device);
106 am_add_feature(f, fe_amidxtaped_host);
107 am_add_feature(f, fe_amidxtaped_disk);
108 am_add_feature(f, fe_amidxtaped_datestamp);
109 am_add_feature(f, fe_amidxtaped_header);
110 am_add_feature(f, fe_amidxtaped_nargs);
111 am_add_feature(f, fe_amidxtaped_config);
113 am_add_feature(f, fe_recover_splits);
114 am_add_feature(f, fe_amidxtaped_exchange_features);
115 am_add_feature(f, fe_partial_estimate);
116 am_add_feature(f, fe_calcsize_estimate);
117 am_add_feature(f, fe_selfcheck_calcsize);
118 am_add_feature(f, fe_options_compress_cust);
119 am_add_feature(f, fe_options_srvcomp_cust);
120 am_add_feature(f, fe_options_encrypt_cust);
121 am_add_feature(f, fe_options_encrypt_serv_cust);
122 am_add_feature(f, fe_options_client_decrypt_option);
123 am_add_feature(f, fe_options_server_decrypt_option);
125 am_add_feature(f, fe_amindexd_marshall_in_OLSD);
126 am_add_feature(f, fe_amindexd_marshall_in_ORLD);
127 am_add_feature(f, fe_amindexd_marshall_in_DHST);
129 am_add_feature(f, fe_amrecover_FEEDME);
130 am_add_feature(f, fe_amrecover_timestamp);
132 am_add_feature(f, fe_interface_quoted_text);
134 am_add_feature(f, fe_program_star);
136 am_add_feature(f, fe_amindexd_options_hostname);
137 am_add_feature(f, fe_amindexd_options_features);
138 am_add_feature(f, fe_amindexd_options_auth);
140 am_add_feature(f, fe_amidxtaped_options_hostname);
141 am_add_feature(f, fe_amidxtaped_options_features);
142 am_add_feature(f, fe_amidxtaped_options_auth);
144 am_add_feature(f, fe_amrecover_message);
145 am_add_feature(f, fe_amrecover_feedme_tape);
147 am_add_feature(f, fe_req_options_config);
149 am_add_feature(f, fe_rep_sendsize_quoted_error);
155 *=====================================================================
156 * Set a default feature set for client that doesn't have noop service.
157 * This is all the features available in 2.4.2p2.
160 * exit: dynamically allocated feature set
161 *=====================================================================
165 am_set_default_feature_set(void)
169 if ((f = am_allocate_feature_set()) != NULL) {
171 am_add_feature(f, fe_selfcheck_req);
172 am_add_feature(f, fe_selfcheck_rep);
173 am_add_feature(f, fe_sendsize_req_no_options);
174 am_add_feature(f, fe_sendsize_rep);
175 am_add_feature(f, fe_sendbackup_req);
176 am_add_feature(f, fe_sendbackup_rep);
178 am_add_feature(f, fe_program_dump);
179 am_add_feature(f, fe_program_gnutar);
181 am_add_feature(f, fe_options_compress_fast);
182 am_add_feature(f, fe_options_compress_best);
183 am_add_feature(f, fe_options_srvcomp_fast);
184 am_add_feature(f, fe_options_srvcomp_best);
185 am_add_feature(f, fe_options_no_record);
186 am_add_feature(f, fe_options_bsd_auth);
187 am_add_feature(f, fe_options_index);
188 am_add_feature(f, fe_options_exclude_file);
189 am_add_feature(f, fe_options_exclude_list);
190 am_add_feature(f, fe_options_krb4_auth);
191 am_add_feature(f, fe_options_kencrypt);
193 am_add_feature(f, fe_req_options_maxdumps);
194 am_add_feature(f, fe_req_options_hostname);
195 am_add_feature(f, fe_req_options_features);
197 am_add_feature(f, fe_rep_options_sendbackup_options);
203 *=====================================================================
204 * Allocate space for a feature set.
206 * am_feature_t *am_allocate_feature_set()
209 * exit: dynamically allocated feature set structure
210 *=====================================================================
214 am_allocate_feature_set(void)
217 am_feature_t *result;
219 result = (am_feature_t *)alloc(SIZEOF(*result));
220 memset(result, 0, SIZEOF(*result));
221 nbytes = (((size_t)last_feature) + 8) >> 3;
222 result->size = nbytes;
223 result->bytes = (unsigned char *)alloc(nbytes);
224 memset(result->bytes, 0, nbytes);
229 *=====================================================================
230 * Release space allocated to a feature set.
232 * void am_release_feature_set(am_feature_t *f)
234 * entry: f = feature set to release
236 *=====================================================================
240 am_release_feature_set(
251 *=====================================================================
252 * Add a feature to a feature set.
254 * int am_add_feature(am_feature_t *f, am_feature_e n)
256 * entry: f = feature set to add to
258 * exit: non-zero if feature added, else zero (e.g. if the feature
259 * is beyond what is currently supported)
260 *=====================================================================
272 if (f != NULL && (int)n >= 0) {
273 byte = ((size_t)n) >> 3;
274 if (byte < f->size) {
275 bit = ((int)n) & 0x7;
276 f->bytes[byte] = (unsigned char)((int)f->bytes[byte] | (unsigned char)(1 << bit));
284 *=====================================================================
285 * Remove a feature from a feature set.
287 * int am_remove_feature(am_feature_t *f, am_feature_e n)
289 * entry: f = feature set to remove from
290 * n = feature to remove
291 * exit: non-zero if feature removed, else zero (e.g. if the feature
292 * is beyond what is currently supported)
293 *=====================================================================
305 if (f != NULL && (int)n >= 0) {
306 byte = ((size_t)n) >> 3;
307 if (byte < f->size) {
308 bit = ((int)n) & 0x7;
309 f->bytes[byte] = (unsigned char)((int)f->bytes[byte] & (unsigned char)~(1 << bit));
317 *=====================================================================
318 * Return true if a given feature is available.
320 * int am_has_feature(am_feature_t *f, am_feature_e n)
322 * entry: f = feature set to test
323 * n = feature to test
324 * exit: non-zero if feature is enabled
325 *=====================================================================
337 if (f != NULL && (int)n >= 0) {
338 byte = ((size_t)n) >> 3;
339 if (byte < f->size) {
340 bit = ((int)n) & 0x7;
341 result = ((f->bytes[byte] & (1 << bit)) != 0);
348 *=====================================================================
349 * Convert a feature set to string.
351 * char *am_feature_to_string(am_feature_t *f)
353 * entry: f = feature set to convet
354 * exit: dynamically allocated string
355 *=====================================================================
359 am_feature_to_string(
366 result = stralloc("UNKNOWNFEATURE");
368 result = alloc((f->size * 2) + 1);
369 for (i = 0; i < f->size; i++) {
370 snprintf(result + (i * 2), 2 + 1, "%02x", f->bytes[i]);
372 result[i * 2] = '\0';
378 *=====================================================================
379 * Convert a sting back to a feature set.
381 * am_feature_t *am_string_to_feature(char *s)
383 * entry: s = string to convert
384 * exit: dynamically allocated feature set
386 * Note: if the string is longer than the list of features we support,
387 * the remaining input features are ignored. If it is shorter, the
388 * missing features are disabled.
390 * If the string is not formatted properly (not a multiple of two bytes),
393 * Conversion stops at the first non-hex character.
394 *=====================================================================
398 am_string_to_feature(
401 am_feature_t *f = NULL;
405 if (s != NULL && strcmp(s,"UNKNOWNFEATURE") != 0) {
406 f = am_allocate_feature_set();
407 for (i = 0; i < f->size && (ch1 = *s++) != '\0'; i++) {
410 } else if (ch1 >= 'a' && ch1 <= 'f') {
413 } else if (ch1 >= 'A' && ch1 <= 'F') {
422 } else if (ch2 >= 'a' && ch2 <= 'f') {
425 } else if (ch2 >= 'A' && ch2 <= 'F') {
429 amfree(f); /* bad conversion */
432 f->bytes[i] = (unsigned char)((ch1 << 4) | ch2);
451 f = am_init_feature_set();
453 fprintf(stderr, "cannot initialize feature set\n");
457 s = am_feature_to_string(f);
458 printf("base features=%s\n", s);
460 f1 = am_string_to_feature(s);
461 s1 = am_feature_to_string(f1);
462 if (strcmp(s, s1) != 0) {
463 fprintf(stderr, "base feature -> string -> feature set mismatch\n");
464 fprintf(stderr, "conv features=%s\n", s);
470 for (i = 1; i < argc; i++) {
471 if (argv[i][0] == '+') {
472 n = atoi(&argv[i][1]);
473 if (am_add_feature(f, (am_feature_e)n)) {
474 printf("added feature number %d\n", n);
476 printf("could not add feature number %d\n", n);
478 } else if (argv[i][0] == '-') {
479 n = atoi(&argv[i][1]);
480 if (am_remove_feature(f, (am_feature_e)n)) {
481 printf("removed feature number %d\n", n);
483 printf("could not remove feature number %d\n", n);
487 if (am_has_feature(f, (am_feature_e)n)) {
488 printf("feature %d is set\n", n);
490 printf("feature %d is not set\n", n);
495 s = am_feature_to_string(f);
496 printf(" new features=%s\n", s);