1 /*
2 * Amanda, The Advanced Maryland Automatic Network Disk Archiver
3 * Copyright (c) 1991-1999 University of Maryland at College Park
4 * Copyright (c) 2007-2013 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: server_util.c,v 1.17 2006/05/25 01:47:20 johnfranks Exp $
29 *
30 */
31
32 #include "amanda.h"
33 #include "server_util.h"
34 #include "arglist.h"
35 #include "logfile.h"
36 #include "util.h"
37 #include "conffile.h"
38 #include "diskfile.h"
39 #include "pipespawn.h"
40 #include "conffile.h"
41 #include "infofile.h"
42 #include "sys/wait.h"
43
44 const char *cmdstr[] = {
45 "BOGUS", "QUIT", "QUITTING", "DONE", "PARTIAL",
46 "START", "FILE-DUMP", "PORT-DUMP", "CONTINUE", "ABORT",/* dumper cmds */
47 "FAILED", "TRY-AGAIN", "NO-ROOM", "RQ-MORE-DISK", /* dumper results */
48 "ABORT-FINISHED", "BAD-COMMAND", /* dumper results */
49 "START-TAPER", "FILE-WRITE", "NEW-TAPE", "NO-NEW-TAPE",
50
51 "PARTDONE", "PORT-WRITE", "DUMPER-STATUS", /* taper cmds */
52 "PORT", "TAPE-ERROR", "TAPER-OK", /* taper results */
53 "REQUEST-NEW-TAPE", "DIRECTTCP-PORT", "TAKE-SCRIBE-FROM",
54 "START-SCAN", "CLOSE-VOLUME", "READY", "LAST_TOK",
55 NULL
56 };
57
58
59 struct cmdargs *
getcmd(void)60 getcmd(void)
61 {
62 char *line;
63 cmd_t cmd_i;
64 struct cmdargs *cmdargs = g_new0(struct cmdargs, 1);
65
66 if (isatty(0)) {
67 g_printf("%s> ", get_pname());
68 fflush(stdout);
69 line = agets(stdin);
70 } else {
71 line = agets(stdin);
72 }
73 if (line == NULL) {
74 line = stralloc("QUIT");
75 }
76
77 dbprintf(_("getcmd: %s\n"), line);
78
79 cmdargs->argv = split_quoted_strings(line);
80 cmdargs->argc = g_strv_length(cmdargs->argv);
81 cmdargs->cmd = BOGUS;
82
83 amfree(line);
84
85 if (cmdargs->argc < 1) {
86 return cmdargs;
87 }
88
89 for(cmd_i=BOGUS; cmdstr[cmd_i] != NULL; cmd_i++)
90 if(strcmp(cmdargs->argv[0], cmdstr[cmd_i]) == 0) {
91 cmdargs->cmd = cmd_i;
92 return cmdargs;
93 }
94 return cmdargs;
95 }
96
97 struct cmdargs *
get_pending_cmd(void)98 get_pending_cmd(void)
99 {
100 SELECT_ARG_TYPE ready;
101 struct timeval to;
102 int nfound;
103
104 FD_ZERO(&ready);
105 FD_SET(0, &ready);
106 to.tv_sec = 0;
107 to.tv_usec = 0;
108
109 nfound = select(1, &ready, NULL, NULL, &to);
110 if (nfound && FD_ISSET(0, &ready)) {
111 return getcmd();
112 } else {
113 return NULL;
114 }
115 }
116
117 void
free_cmdargs(struct cmdargs * cmdargs)118 free_cmdargs(
119 struct cmdargs *cmdargs)
120 {
121 if (!cmdargs)
122 return;
123 if (cmdargs->argv)
124 g_strfreev(cmdargs->argv);
125 g_free(cmdargs);
126 }
127
printf_arglist_function1(void putresult,cmd_t,result,const char *,format)128 printf_arglist_function1(void putresult, cmd_t, result, const char *, format)
129 {
130 va_list argp;
131
132 arglist_start(argp, format);
133 dbprintf(_("putresult: %d %s\n"), result, cmdstr[result]);
134 g_printf("%s ", cmdstr[result]);
135 g_vprintf(format, argp);
136 fflush(stdout);
137 arglist_end(argp);
138 }
139
140 char *
amhost_get_security_conf(char * string,void * arg)141 amhost_get_security_conf(
142 char * string,
143 void * arg)
144 {
145 if(!string || !*string)
146 return(NULL);
147
148 if(strcmp(string, "krb5principal")==0)
149 return(getconf_str(CNF_KRB5PRINCIPAL));
150 else if(strcmp(string, "krb5keytab")==0)
151 return(getconf_str(CNF_KRB5KEYTAB));
152
153 if(!arg || !((am_host_t *)arg)->disks) return(NULL);
154
155 if(strcmp(string, "amandad_path")==0)
156 return ((am_host_t *)arg)->disks->amandad_path;
157 else if(strcmp(string, "client_username")==0)
158 return ((am_host_t *)arg)->disks->client_username;
159 else if(strcmp(string, "client_port")==0)
160 return ((am_host_t *)arg)->disks->client_port;
161 else if(strcmp(string, "ssh_keys")==0)
162 return ((am_host_t *)arg)->disks->ssh_keys;
163
164 return(NULL);
165 }
166
check_infofile(char * infodir,disklist_t * dl,char ** errmsg)167 int check_infofile(
168 char *infodir,
169 disklist_t *dl,
170 char **errmsg)
171 {
172 disk_t *dp, *diskp;
173 char *hostinfodir, *old_hostinfodir, *Xhostinfodir;
174 char *diskdir, *old_diskdir, *Xdiskdir;
175 char *infofile, *old_infofile, *Xinfofile;
176 struct stat statbuf;
177 int other_dle_match;
178
179 if (stat(infodir, &statbuf) != 0) {
180 return 0;
181 }
182
183 for (dp = dl->head; dp != NULL; dp = dp->next) {
184 hostinfodir = sanitise_filename(dp->host->hostname);
185 diskdir = sanitise_filename(dp->name);
186 infofile = vstralloc(infodir, "/", hostinfodir, "/", diskdir,
187 "/info", NULL);
188 if (stat(infofile, &statbuf) == -1 && errno == ENOENT) {
189 old_hostinfodir = old_sanitise_filename(dp->host->hostname);
190 old_diskdir = old_sanitise_filename(dp->name);
191 old_infofile = vstralloc(infodir, old_hostinfodir, "/",
192 old_diskdir, "/info", NULL);
193 if (stat(old_infofile, &statbuf) == 0) {
194 other_dle_match = 0;
195 diskp = dl->head;
196 while (diskp != NULL) {
197 Xhostinfodir = sanitise_filename(diskp->host->hostname);
198 Xdiskdir = sanitise_filename(diskp->name);
199 Xinfofile = vstralloc(infodir, "/", Xhostinfodir, "/",
200 Xdiskdir, "/info", NULL);
201 if (strcmp(old_infofile, Xinfofile) == 0) {
202 other_dle_match = 1;
203 diskp = NULL;
204 }
205 else {
206 diskp = diskp->next;
207 }
208 }
209 if (other_dle_match == 0) {
210 if(mkpdir(infofile, (mode_t)0755, (uid_t)-1,
211 (gid_t)-1) == -1) {
212 *errmsg = vstralloc("Can't create directory for ",
213 infofile, NULL);
214 return -1;
215 }
216 if(copy_file(infofile, old_infofile, errmsg) == -1)
217 return -1;
218 }
219 }
220 amfree(old_hostinfodir);
221 amfree(old_diskdir);
222 amfree(old_infofile);
223 }
224 amfree(diskdir);
225 amfree(hostinfodir);
226 amfree(infofile);
227 }
228 return 0;
229 }
230
231 void
run_server_script(pp_script_t * pp_script,execute_on_t execute_on,char * config,disk_t * dp,int level)232 run_server_script(
233 pp_script_t *pp_script,
234 execute_on_t execute_on,
235 char *config,
236 disk_t *dp,
237 int level)
238 {
239 pid_t scriptpid;
240 int scriptin, scriptout, scripterr;
241 char *cmd;
242 char *command = NULL;
243 GPtrArray *argv_ptr = g_ptr_array_new();
244 FILE *streamout;
245 char *line;
246 char *plugin;
247 char level_number[NUM_STR_SIZE];
248 struct stat cmd_stat;
249 int result;
250
251 if ((pp_script_get_execute_on(pp_script) & execute_on) == 0)
252 return;
253 if (pp_script_get_execute_where(pp_script) != ES_SERVER)
254 return;
255
256 plugin = pp_script_get_plugin(pp_script);
257
258 cmd = vstralloc(APPLICATION_DIR, "/", plugin, NULL);
259 result = stat(cmd, &cmd_stat);
260 if (result == -1) {
261 dbprintf("Can't stat script '%s': %s\n", cmd, strerror(errno));
262 amfree(cmd);
263 cmd = vstralloc(get_config_dir(), "/application/", plugin, NULL);
264 result = stat(cmd, &cmd_stat);
265 if (result == -1) {
266 dbprintf("Can't stat script '%s': %s\n", cmd, strerror(errno));
267 amfree(cmd);
268 cmd = vstralloc(CONFIG_DIR, "/application/", plugin, NULL);
269 result = stat(cmd, &cmd_stat);
270 if (result == -1) {
271 dbprintf("Can't stat script '%s': %s\n", cmd, strerror(errno));
272 amfree(cmd);
273 cmd = vstralloc(APPLICATION_DIR, "/", plugin, NULL);
274 }
275 }
276 }
277
278 g_ptr_array_add(argv_ptr, stralloc(plugin));
279
280 switch (execute_on) {
281 case EXECUTE_ON_PRE_AMCHECK:
282 command = "PRE-AMCHECK";
283 break;
284 case EXECUTE_ON_PRE_DLE_AMCHECK:
285 command = "PRE-DLE-AMCHECK";
286 break;
287 case EXECUTE_ON_PRE_HOST_AMCHECK:
288 command = "PRE-HOST-AMCHECK";
289 break;
290 case EXECUTE_ON_POST_AMCHECK:
291 command = "POST-AMCHECK";
292 break;
293 case EXECUTE_ON_POST_DLE_AMCHECK:
294 command = "POST-DLE-AMCHECK";
295 break;
296 case EXECUTE_ON_POST_HOST_AMCHECK:
297 command = "POST-HOST-AMCHECK";
298 break;
299 case EXECUTE_ON_PRE_ESTIMATE:
300 command = "PRE-ESTIMATE";
301 break;
302 case EXECUTE_ON_PRE_DLE_ESTIMATE:
303 command = "PRE-DLE-ESTIMATE";
304 break;
305 case EXECUTE_ON_PRE_HOST_ESTIMATE:
306 command = "PRE-HOST-ESTIMATE";
307 break;
308 case EXECUTE_ON_POST_ESTIMATE:
309 command = "POST-ESTIMATE";
310 break;
311 case EXECUTE_ON_POST_DLE_ESTIMATE:
312 command = "POST-DLE-ESTIMATE";
313 break;
314 case EXECUTE_ON_POST_HOST_ESTIMATE:
315 command = "POST-HOST-ESTIMATE";
316 break;
317 case EXECUTE_ON_PRE_BACKUP:
318 command = "PRE-BACKUP";
319 break;
320 case EXECUTE_ON_PRE_DLE_BACKUP:
321 command = "PRE-DLE-BACKUP";
322 break;
323 case EXECUTE_ON_PRE_HOST_BACKUP:
324 command = "PRE-HOST-BACKUP";
325 break;
326 case EXECUTE_ON_POST_BACKUP:
327 command = "POST-BACKUP";
328 break;
329 case EXECUTE_ON_POST_DLE_BACKUP:
330 command = "POST-DLE-BACKUP";
331 break;
332 case EXECUTE_ON_POST_HOST_BACKUP:
333 command = "POST-HOST-BACKUP";
334 break;
335 case EXECUTE_ON_PRE_RECOVER:
336 case EXECUTE_ON_POST_RECOVER:
337 case EXECUTE_ON_PRE_LEVEL_RECOVER:
338 case EXECUTE_ON_POST_LEVEL_RECOVER:
339 case EXECUTE_ON_INTER_LEVEL_RECOVER:
340 {
341 // ERROR these script can't be executed on server.
342 return;
343 }
344 }
345
346 g_ptr_array_add(argv_ptr, stralloc(command));
347 g_ptr_array_add(argv_ptr, stralloc("--execute-where"));
348 g_ptr_array_add(argv_ptr, stralloc("server"));
349
350 if (config) {
351 g_ptr_array_add(argv_ptr, stralloc("--config"));
352 g_ptr_array_add(argv_ptr, stralloc(config));
353 }
354 if (dp->host->hostname) {
355 g_ptr_array_add(argv_ptr, stralloc("--host"));
356 g_ptr_array_add(argv_ptr, stralloc(dp->host->hostname));
357 }
358 if (dp->name) {
359 g_ptr_array_add(argv_ptr, stralloc("--disk"));
360 g_ptr_array_add(argv_ptr, stralloc(dp->name));
361 }
362 if (dp->device) {
363 g_ptr_array_add(argv_ptr, stralloc("--device"));
364 g_ptr_array_add(argv_ptr, stralloc(dp->device));
365 }
366 if (level >= 0) {
367 g_snprintf(level_number, SIZEOF(level_number), "%d", level);
368 g_ptr_array_add(argv_ptr, stralloc("--level"));
369 g_ptr_array_add(argv_ptr, stralloc(level_number));
370 }
371
372 property_add_to_argv(argv_ptr, pp_script_get_property(pp_script));
373 g_ptr_array_add(argv_ptr, NULL);
374
375 scripterr = fileno(stderr);
376 scriptpid = pipespawnv(cmd, STDIN_PIPE|STDOUT_PIPE, 0, &scriptin,
377 &scriptout, &scripterr,
378 (char **)argv_ptr->pdata);
379 close(scriptin);
380
381 streamout = fdopen(scriptout, "r");
382 if (streamout) {
383 while((line = agets(streamout)) != NULL) {
384 dbprintf("script: %s\n", line);
385 amfree(line);
386 }
387 }
388 fclose(streamout);
389 waitpid(scriptpid, NULL, 0);
390 g_ptr_array_free_full(argv_ptr);
391 amfree(cmd);
392 }
393
394
395 void
run_server_dle_scripts(execute_on_t execute_on,char * config,disk_t * dp,int level)396 run_server_dle_scripts(
397 execute_on_t execute_on,
398 char *config,
399 disk_t *dp,
400 int level)
401 {
402 identlist_t pp_scriptlist;
403
404 for (pp_scriptlist = dp->pp_scriptlist; pp_scriptlist != NULL;
405 pp_scriptlist = pp_scriptlist->next) {
406 pp_script_t *pp_script = lookup_pp_script((char *)pp_scriptlist->data);
407 g_assert(pp_script != NULL);
408 run_server_script(pp_script, execute_on, config, dp, level);
409 }
410 }
411
412 void
run_server_host_scripts(execute_on_t execute_on,char * config,am_host_t * hostp)413 run_server_host_scripts(
414 execute_on_t execute_on,
415 char *config,
416 am_host_t *hostp)
417 {
418 identlist_t pp_scriptlist;
419 disk_t *dp;
420
421 GHashTable* executed = g_hash_table_new_full(g_str_hash, g_str_equal,
422 NULL, NULL);
423 for (dp = hostp->disks; dp != NULL; dp = dp->hostnext) {
424 if (dp->todo) {
425 for (pp_scriptlist = dp->pp_scriptlist; pp_scriptlist != NULL;
426 pp_scriptlist = pp_scriptlist->next) {
427 int todo = 1;
428 pp_script_t *pp_script = lookup_pp_script((char *)pp_scriptlist->data);
429 g_assert(pp_script != NULL);
430 if (pp_script_get_single_execution(pp_script)) {
431 todo = g_hash_table_lookup(executed,
432 pp_script_get_plugin(pp_script))
433 == NULL;
434 }
435 if (todo) {
436 run_server_script(pp_script, execute_on, config, dp, -1);
437 if (pp_script_get_single_execution(pp_script)) {
438 g_hash_table_insert(executed,
439 pp_script_get_plugin(pp_script),
440 GINT_TO_POINTER(1));
441 }
442 }
443 }
444 }
445 }
446
447 g_hash_table_destroy(executed);
448 }
449
450 void
run_server_global_scripts(execute_on_t execute_on,char * config)451 run_server_global_scripts(
452 execute_on_t execute_on,
453 char *config)
454 {
455 identlist_t pp_scriptlist;
456 disk_t *dp;
457 am_host_t *host;
458
459 GHashTable* executed = g_hash_table_new_full(g_str_hash, g_str_equal,
460 NULL, NULL);
461 for (host = get_hostlist(); host != NULL; host = host->next) {
462 for (dp = host->disks; dp != NULL; dp = dp->hostnext) {
463 if (dp->todo) {
464 for (pp_scriptlist = dp->pp_scriptlist; pp_scriptlist != NULL;
465 pp_scriptlist = pp_scriptlist->next) {
466 int todo = 1;
467 pp_script_t *pp_script =
468 lookup_pp_script((char *)pp_scriptlist->data);
469 g_assert(pp_script != NULL);
470 if (pp_script_get_single_execution(pp_script)) {
471 todo = g_hash_table_lookup(executed,
472 pp_script_get_plugin(pp_script)) == NULL;
473 }
474 if (todo) {
475 run_server_script(pp_script, execute_on, config,
476 dp, -1);
477 if (pp_script_get_single_execution(pp_script)) {
478 g_hash_table_insert(executed,
479 pp_script_get_plugin(pp_script),
480 GINT_TO_POINTER(1));
481 }
482 }
483 }
484 }
485 }
486 }
487 g_hash_table_destroy(executed);
488 }
489
490 void
run_amcleanup(char * config_name)491 run_amcleanup(
492 char *config_name)
493 {
494 pid_t amcleanup_pid;
495 char *amcleanup_program;
496 char *amcleanup_options[4];
497
498 switch(amcleanup_pid = fork()) {
499 case -1:
500 return;
501 break;
502 case 0: /* child process */
503 amcleanup_program = vstralloc(sbindir, "/", "amcleanup", NULL);
504 amcleanup_options[0] = amcleanup_program;
505 amcleanup_options[1] = "-p";
506 amcleanup_options[2] = config_name;
507 amcleanup_options[3] = NULL;
508 execve(amcleanup_program, amcleanup_options, safe_env());
509 error("exec %s: %s", amcleanup_program, strerror(errno));
510 /*NOTREACHED*/
511 default:
512 break;
513 }
514 waitpid(amcleanup_pid, NULL, 0);
515 }
516
517 char *
get_master_process(char * logfile)518 get_master_process(
519 char *logfile)
520 {
521 FILE *log;
522 char line[1024];
523 char *s, ch;
524 char *process_name;
525
526 log = fopen(logfile, "r");
527 if (!log)
528 return stralloc("UNKNOWN");
529
530 while(fgets(line, 1024, log)) {
531 if (strncmp_const(line, "INFO ") == 0) {
532 s = line+5;
533 ch = *s++;
534 process_name = s-1;
535 skip_non_whitespace(s, ch);
536 s[-1] = '\0';
537 skip_whitespace(s, ch);
538 skip_non_whitespace(s, ch);
539 s[-1] = '\0';
540 skip_whitespace(s, ch);
541 if (strncmp_const(s-1, "pid ") == 0) {
542 process_name = stralloc(process_name);
543 fclose(log);
544 return process_name;
545 }
546 }
547 }
548 fclose(log);
549 return stralloc("UNKNOWN");
550 }
551
552
553 gint64
internal_server_estimate(disk_t * dp,info_t * info,int level,int * stats)554 internal_server_estimate(
555 disk_t *dp,
556 info_t *info,
557 int level,
558 int *stats)
559 {
560 int j;
561 gint64 size = 0;
562
563 *stats = 0;
564
565 if (level == 0) { /* use latest level 0, should do extrapolation */
566 gint64 est_size = (gint64)0;
567 int nb_est = 0;
568
569 for (j=NB_HISTORY-2; j>=0; j--) {
570 if (info->history[j].level == 0) {
571 if (info->history[j].size <= (gint64)0) continue;
572 est_size = info->history[j].size;
573 nb_est++;
574 }
575 }
576 if (nb_est > 0) {
577 size = est_size;
578 *stats = 1;
579 } else if (info->inf[level].size > (gint64)1000) { /* stats */
580 size = info->inf[level].size;
581 *stats = 1;
582 } else {
583 char *conf_tapetype = getconf_str(CNF_TAPETYPE);
584 tapetype_t *tape = lookup_tapetype(conf_tapetype);
585 size = (gint64)1000000;
586 if (size > tapetype_get_length(tape)/2)
587 size = tapetype_get_length(tape)/2;
588 *stats = 0;
589 }
590 } else if (level == info->last_level) {
591 /* means of all X day at the same level */
592 #define NB_DAY 30
593 int nb_day = 0;
594 gint64 est_size_day[NB_DAY];
595 int nb_est_day[NB_DAY];
596
597 for (j=0; j<NB_DAY; j++) {
598 est_size_day[j] = (gint64)0;
599 nb_est_day[j] = 0;
600 }
601
602 for (j=NB_HISTORY-2; j>=0; j--) {
603 if (info->history[j].level <= 0) continue;
604 if (info->history[j].size <= (gint64)0) continue;
605 if (info->history[j].level == info->history[j+1].level) {
606 if (nb_day <NB_DAY-1) nb_day++;
607 est_size_day[nb_day] += info->history[j].size;
608 nb_est_day[nb_day]++;
609 } else {
610 nb_day=0;
611 }
612 }
613 nb_day = info->consecutive_runs + 1;
614 if (nb_day > NB_DAY-1) nb_day = NB_DAY-1;
615
616 while (nb_day > 0 && nb_est_day[nb_day] == 0) nb_day--;
617
618 if (nb_est_day[nb_day] > 0) {
619 size = est_size_day[nb_day] / (gint64)nb_est_day[nb_day];
620 *stats = 1;
621 }
622 else if (info->inf[level].size > (gint64)1000) { /* stats */
623 size = info->inf[level].size;
624 *stats = 1;
625 }
626 else {
627 int level0_stat;
628 gint64 level0_size;
629 char *conf_tapetype = getconf_str(CNF_TAPETYPE);
630 tapetype_t *tape = lookup_tapetype(conf_tapetype);
631
632 level0_size = internal_server_estimate(dp, info, 0, &level0_stat);
633 size = (gint64)10000;
634 if (size > tapetype_get_length(tape)/2)
635 size = tapetype_get_length(tape)/2;
636 if (level0_size > 0 && dp->strategy != DS_NOFULL) {
637 if (size > level0_size/2)
638 size = level0_size/2;
639 }
640 *stats = 0;
641 }
642 }
643 else if (level == info->last_level + 1) {
644 /* means of all first day at a new level */
645 gint64 est_size = (gint64)0;
646 int nb_est = 0;
647
648 for (j=NB_HISTORY-2; j>=0; j--) {
649 if (info->history[j].level <= 0) continue;
650 if (info->history[j].size <= (gint64)0) continue;
651 if (info->history[j].level == info->history[j+1].level + 1 ) {
652 est_size += info->history[j].size;
653 nb_est++;
654 }
655 }
656 if (nb_est > 0) {
657 size = est_size / (gint64)nb_est;
658 *stats = 1;
659 } else if (info->inf[level].size > (gint64)1000) { /* stats */
660 size = info->inf[level].size;
661 *stats = 1;
662 } else {
663 int level0_stat;
664 gint64 level0_size;
665 char *conf_tapetype = getconf_str(CNF_TAPETYPE);
666 tapetype_t *tape = lookup_tapetype(conf_tapetype);
667
668 level0_size = internal_server_estimate(dp, info, 0, &level0_stat);
669 size = (gint64)100000;
670 if (size > tapetype_get_length(tape)/2)
671 size = tapetype_get_length(tape)/2;
672 if (level0_size > 0 && dp->strategy != DS_NOFULL) {
673 if (size > level0_size/2)
674 size = level0_size/2;
675 }
676 *stats = 0;
677 }
678 } else {
679 char *conf_tapetype = getconf_str(CNF_TAPETYPE);
680 tapetype_t *tape = lookup_tapetype(conf_tapetype);
681 size = (gint64)100000;
682 if (size > tapetype_get_length(tape)/2)
683 size = tapetype_get_length(tape)/2;
684 }
685
686 return size;
687 }
688
689 int
server_can_do_estimate(disk_t * dp,info_t * info,int level)690 server_can_do_estimate(
691 disk_t *dp,
692 info_t *info,
693 int level)
694 {
695 int stats;
696
697 internal_server_estimate(dp, info, level, &stats);
698 return stats;
699 }
700
701