Imported Upstream version 2.5.2p1
[debian/amanda] / server-src / amcheck.c
index 9e83962ea1ba19cdf84a5241a592870213b6a933..4498cd7a6bf77a04830c3ae677fe3817dcb6f11c 100644 (file)
@@ -141,7 +141,7 @@ main(
     server_probs = client_probs = 0;
     tempfd = mainfd = -1;
 
-    parse_server_conf(argc, argv, &new_argc, &new_argv);
+    parse_conf(argc, argv, &new_argc, &new_argv);
     my_argc = new_argc;
     my_argv = new_argv;
 
@@ -174,7 +174,7 @@ main(
                        exit(1);
 #endif
                        break;
-       case 's':       do_localchk = do_clientchk = do_tapechk = 1;
+       case 's':       do_localchk = do_tapechk = 1;
                        break;
        case 'c':       do_clientchk = 1;
                        break;
@@ -244,7 +244,7 @@ main(
       }
     }
 
-    conf_ctimeout = getconf_time(CNF_CTIMEOUT);
+    conf_ctimeout = (time_t)getconf_int(CNF_CTIMEOUT);
 
     conf_diskfile = getconf_str(CNF_DISKFILE);
     if (*conf_diskfile == '/') {
@@ -481,7 +481,7 @@ main(
                    error("mailfd write: %s", strerror(errno));
                    /*NOTREACHED*/
                } else {
-                   error("mailfd write: wrote %d instead of %d", w, r);
+                   error("mailfd write: wrote " SSIZE_T_FMT " instead of " SIZE_T_FMT, w, r);
                    /*NOTREACHED*/
                }
            }
@@ -601,6 +601,9 @@ start_server_check(
     int testtape = do_tapechk;
     tapetype_t *tp = NULL;
     char *quoted;
+    int res;
+    struct addrinfo *gaires;
+    struct addrinfo hints;
 
     switch(pid = fork()) {
     case -1:
@@ -668,10 +671,32 @@ start_server_check(
 #endif
        }
 
-       /* check that localhost is resolvable */
-       if ((gethostbyname("localhost")) == NULL) {
-           fprintf(outf, "ERROR: Cannot resolve `localhost'.\n");
+       /* Double-check that 'localhost' resolves properly */
+#ifdef WORKING_IPV6
+       hints.ai_flags = AI_CANONNAME | AI_V4MAPPED | AI_ALL;
+       hints.ai_family = AF_UNSPEC;
+#else
+       hints.ai_flags = AI_CANONNAME;
+       hints.ai_family = AF_INET;
+#endif
+       hints.ai_socktype = 0;
+       hints.ai_protocol = 0;
+       hints.ai_addrlen = 0;
+       hints.ai_addr = NULL;
+       hints.ai_canonname = NULL;
+       hints.ai_next = NULL;
+       res = getaddrinfo("localhost", NULL, &hints, &gaires);
+#ifdef WORKING_IPV6
+       if (res != 0) {
+           hints.ai_flags = AI_CANONNAME;
+           hints.ai_family = AF_UNSPEC;
+           res = getaddrinfo("localhost", NULL, &hints, &gaires);
        }
+#endif
+       if (res != 0) {
+           fprintf(outf, _("ERROR: Cannot resolve `localhost': %s\n"), gai_strerror(res));
+       }
+       if (gaires) freeaddrinfo(gaires);
     }
 
     /*
@@ -764,7 +789,7 @@ start_server_check(
        }
        else if(stat(tapefile, &statbuf) == -1) {
            quoted = quote_string(tape_dir);
-           fprintf(outf, "ERROR: tapefile %s (%s), "
+           fprintf(outf, "ERROR: tapelist %s (%s), "
                    "you must create an empty file.\n",
                    quoted, strerror(errno));
            tapebad = 1;
@@ -772,24 +797,24 @@ start_server_check(
        }
        else if(!S_ISREG(statbuf.st_mode)) {
            quoted = quote_string(tapefile);
-           fprintf(outf, "ERROR: tapefile %s: should be a regular file.\n",
+           fprintf(outf, "ERROR: tapelist %s: should be a regular file.\n",
                    quoted);
            tapebad = 1;
            amfree(quoted);
        }
        else if(access(tapefile, F_OK) != 0) {
            quoted = quote_string(tapefile);
-           fprintf(outf, "ERROR: can't access tape list %s\n", quoted);
+           fprintf(outf, "ERROR: can't access tapelist %s\n", quoted);
            tapebad = 1;
            amfree(quoted);
        } else if(access(tapefile, F_OK) == 0 && access(tapefile, W_OK) != 0) {
            quoted = quote_string(tapefile);
-           fprintf(outf, "ERROR: tape list %s: not writable\n", quoted);
+           fprintf(outf, "ERROR: tapelist %s: not writable\n", quoted);
            tapebad = 1;
            amfree(quoted);
        } else if(read_tapelist(tapefile)) {
            quoted = quote_string(tapefile);
-           fprintf(outf, "ERROR: tape list %s: parse error\n", quoted);
+           fprintf(outf, "ERROR: tapelist %s: parse error\n", quoted);
            tapebad = 1;
            amfree(quoted);
        }
@@ -803,7 +828,13 @@ start_server_check(
        amfree(tape_dir);
        amfree(holdfile);
        tapename = getconf_str(CNF_TAPEDEV);
-       if (strncmp(tapename, "null:", 5) == 0) {
+       if (tapename == NULL) {
+           if (getconf_str(CNF_TPCHANGER) == NULL) {
+               fprintf(outf, "WARNING: No tapedev or tpchanger specified\n");
+               testtape = 0;
+               do_tapechk = 0;
+           }
+       } else if (strncmp_const(tapename, "null:") == 0) {
            fprintf(outf,
                    "WARNING: tapedev is %s, dumps will be thrown away\n",
                    tapename);
@@ -855,14 +886,17 @@ start_server_check(
                else {
                    fprintf(outf,
                            "Holding disk %s: " OFF_T_FMT
-                           " %sB disk space available, that's plenty\n",
-                           quoted, (OFF_T_FMT_TYPE)(fs.avail/(off_t)unitdivisor),
+                           " %sB disk space available,"
+                           " using " OFF_T_FMT " %sB as requested\n",
+                           quoted,
+                           (OFF_T_FMT_TYPE)(fs.avail/(off_t)unitdivisor),
+                           displayunit,
+                           (OFF_T_FMT_TYPE)(holdingdisk_get_disksize(hdp)/(off_t)unitdivisor),
                            displayunit);
                }
            }
            else {
-               assert(holdingdisk_get_disksize(hdp) < (off_t)0);
-               if((fs.avail + holdingdisk_get_disksize(hdp)) <= (off_t)0) {
+               if((fs.avail + holdingdisk_get_disksize(hdp)) < (off_t)0) {
                    fprintf(outf,
                            "WARNING: holding disk %s: "
                            "only " OFF_T_FMT " %sB free, using nothing\n",
@@ -878,7 +912,7 @@ start_server_check(
                            quoted,
                            (OFF_T_FMT_TYPE)(fs.avail/(off_t)unitdivisor),
                            displayunit,
-                           (OFF_T_FMT_TYPE)(fs.avail + holdingdisk_get_disksize(hdp) / (off_t)unitdivisor),
+                           (OFF_T_FMT_TYPE)((fs.avail + holdingdisk_get_disksize(hdp)) / (off_t)unitdivisor),
                            displayunit);
                }
            }
@@ -917,7 +951,7 @@ start_server_check(
 
        if(access(logfile, F_OK) == 0) {
            testtape = 0;
-           logbad = 1;
+           logbad = 2;
            if(access(logfile, W_OK) != 0) {
                quoted = quote_string(logfile);
                fprintf(outf, "ERROR: log file %s: not writable\n", quoted);
@@ -931,14 +965,17 @@ start_server_check(
            if(!(S_ISDIR(stat_old.st_mode))) {
                fprintf(outf, "ERROR: oldlog directory %s is not a directory\n",
                        quoted);
+               logbad = 1;
            }
            if(access(olddir, W_OK) == -1) {
                fprintf(outf, "ERROR: oldlog dir %s: not writable\n", quoted);
+               logbad = 1;
            }
        }
        else if(lstat(olddir,&stat_old) == 0) {
            fprintf(outf, "ERROR: oldlog directory %s is not a directory\n",
                    quoted);
+           logbad = 1;
        }
        amfree(quoted);
 
@@ -946,7 +983,7 @@ start_server_check(
            logfile = newvstralloc(logfile, conf_logdir, "/amdump", NULL);
            if (access(logfile, F_OK) == 0) {
                testtape = 0;
-               logbad = 1;
+               logbad = 2;
            }
        }
 
@@ -970,6 +1007,23 @@ start_server_check(
 
         tape_status = taper_scan(NULL, &label, &datestamp, &tapename,
                                 FILE_taperscan_output_callback, outf);
+       if (tapename) {
+           if (tape_access(tapename,F_OK) == -1) {
+               fprintf(outf, "ERROR: Can't access device %s: %s\n", tapename,
+                       strerror(errno));
+               tapebad = 1;
+           }
+           if (tape_access(tapename,R_OK) == -1) {
+               fprintf(outf, "ERROR: Can't read device %s: %s\n", tapename,
+                       strerror(errno));
+               tapebad = 1;
+           }
+           if (tape_access(tapename,W_OK) == -1) {
+               fprintf(outf, "ERROR: Can't write to device %s: %s\n", tapename,
+                       strerror(errno));
+               tapebad = 1;
+           }
+       }
         if (tape_status < 0) {
            tape_t *exptape = lookup_last_reusable_tape(0);
            fprintf(outf, "       (expecting ");
@@ -1014,6 +1068,9 @@ start_server_check(
     } else if (do_tapechk) {
        fprintf(outf, "WARNING: skipping tape test because amdump or amflush seem to be running\n");
        fprintf(outf, "WARNING: if they are not, you must run amcleanup\n");
+    } else if (logbad == 2) {
+       fprintf(outf, "WARNING: amdump or amflush seem to be running\n");
+       fprintf(outf, "WARNING: if they are not, you must run amcleanup\n");
     } else {
        fprintf(outf, "NOTE: skipping tape checks\n");
     }
@@ -1071,6 +1128,7 @@ start_server_check(
            } else {
                fprintf(outf, "ERROR: conf info dir %s (%s)\n",
                        quoted, strerror(errno));
+               infobad = 1;
            }   
            amfree(conf_infofile);
        } else if (!S_ISDIR(statbuf.st_mode)) {
@@ -1082,6 +1140,12 @@ start_server_check(
            amfree(conf_infofile);
            infobad = 1;
        } else {
+           char *errmsg = NULL;
+           if (check_infofile(conf_infofile, &origq, &errmsg) == -1) {
+               fprintf(outf, "ERROR: Can't copy infofile: %s\n", errmsg);
+               infobad = 1;
+               amfree(errmsg);
+           }
            strappend(conf_infofile, "/");
        }
        amfree(quoted);
@@ -1103,6 +1167,7 @@ start_server_check(
                    } else {
                        fprintf(outf, "ERROR: host info dir %s (%s)\n",
                                quoted, strerror(errno));
+                       infobad = 1;
                    }   
                    amfree(hostinfodir);
                } else if (!S_ISDIR(statbuf.st_mode)) {
@@ -1139,6 +1204,7 @@ start_server_check(
                        } else {
                            fprintf(outf, "ERROR: info dir %s (%s)\n",
                                    quoted, strerror(errno));
+                           infobad = 1;
                        }       
                    } else if (!S_ISDIR(statbuf.st_mode)) {
                        fprintf(outf, "ERROR: info dir %s: not a directory\n",
@@ -1155,7 +1221,8 @@ start_server_check(
                            fprintf(outf, "NOTE: it will be created on the next run.\n");
                        } else {
                            fprintf(outf, "ERROR: info dir %s (%s)\n",
-                               quoted, strerror(errno));
+                                   quoted, strerror(errno));
+                           infobad = 1;
                        }       
                    } else if (!S_ISREG(statbuf.st_mode)) {
                        fprintf(outf, "ERROR: info file %s: not a file\n",
@@ -1177,11 +1244,12 @@ start_server_check(
                        if(stat(conf_indexdir, &statbuf) == -1) {
                            if (errno == ENOENT) {
                                fprintf(outf, "NOTE: index dir %s does not exist\n",
-                                   quoted);
+                                       quoted);
                                fprintf(outf, "NOTE: it will be created on the next run.\n");
                            } else {
                                fprintf(outf, "ERROR: index dir %s (%s)\n",
                                        quoted, strerror(errno));
+                               indexbad = 1;
                            }   
                            amfree(conf_indexdir);
                        } else if (!S_ISDIR(statbuf.st_mode)) {
@@ -1207,11 +1275,12 @@ start_server_check(
                            if(stat(hostindexdir, &statbuf) == -1) {
                                if (errno == ENOENT) {
                                    fprintf(outf, "NOTE: index dir %s does not exist\n",
-                                       quoted);
+                                           quoted);
                                    fprintf(outf, "NOTE: it will be created on the next run.\n");
                                } else {
                                    fprintf(outf, "ERROR: index dir %s (%s)\n",
                                            quoted, strerror(errno));
+                                   indexbad = 1;
                                }
                                amfree(hostindexdir);
                            } else if (!S_ISDIR(statbuf.st_mode)) {
@@ -1236,11 +1305,12 @@ start_server_check(
                            if(stat(diskdir, &statbuf) == -1) {
                                if (errno == ENOENT) {
                                    fprintf(outf, "NOTE: index dir %s does not exist\n",
-                                       quoted);
+                                           quoted);
                                    fprintf(outf, "NOTE: it will be created on the next run.\n");
                                } else {
                                    fprintf(outf, "ERROR: index dir %s (%s)\n",
                                        quoted, strerror(errno));
+                                   indexbad = 1;
                                }       
                            } else if (!S_ISDIR(statbuf.st_mode)) {
                                fprintf(outf, "ERROR: index dir %s: not a directory\n",
@@ -1267,7 +1337,7 @@ start_server_check(
                    pgmbad = 1;
                  }
                }
-               if ( dp->compress == COMP_SERV_CUST ) {
+               if ( dp->compress == COMP_SERVER_CUST ) {
                  if ( dp->srvcompprog[0] == '\0' ) {
                    fprintf(outf, "ERROR: server custom compression program not specified\n");
                    pgmbad = 1;
@@ -1353,7 +1423,7 @@ start_host(
        return;
     }
 
-    if (strncmp (hostp->hostname,"localhost",9) == 0) {
+    if (strcmp(hostp->hostname,"localhost") == 0) {
        fprintf(outf,
                     "WARNING: Usage of fully qualified hostname recommended for Client %s.\n",
                     hostp->hostname);
@@ -1477,8 +1547,8 @@ start_host(
                     hostp->hostname, qname, dp->device);
                }
            }
-           if(strncmp(dp->program,"DUMP",4) == 0 || 
-              strncmp(dp->program,"GNUTAR",6) == 0) {
+           if(strcmp(dp->program,"DUMP") == 0 || 
+              strcmp(dp->program,"GNUTAR") == 0) {
                if(strcmp(dp->program, "DUMP") == 0 &&
                   !am_has_feature(hostp->features, fe_program_dump)) {
                    fprintf(outf, "ERROR: %s:%s does not support DUMP.\n",
@@ -1513,9 +1583,9 @@ start_host(
                            "ERROR: Client %s does not support data encryption.\n",
                            hostp->hostname);
                    remote_errors++;
-                 } else if ( dp->compress == COMP_SERV_FAST || 
-                             dp->compress == COMP_SERV_BEST ||
-                             dp->compress == COMP_SERV_CUST ) {
+                 } else if ( dp->compress == COMP_SERVER_FAST || 
+                             dp->compress == COMP_SERVER_BEST ||
+                             dp->compress == COMP_SERVER_CUST ) {
                    fprintf(outf,
                            "ERROR: %s: Client encryption with server compression is not supported. See amanda.conf(5) for detail.\n", hostp->hostname);
                    remote_errors++;
@@ -1525,7 +1595,7 @@ start_host(
                    l = vstralloc(calcsize,
                                  dp->program, " ",
                                  qname, " ",
-                                 dp->device,
+                                 qdevice,
                                  " 0 OPTIONS |",
                                  o,
                                  "\n",
@@ -1541,20 +1611,31 @@ start_host(
                                  NULL);
                }
            } else {
-               if(!am_has_feature(hostp->features, fe_program_dumper_api)) {
-                   fprintf(outf, "ERROR: %s:%s does not support DUMPER-API.\n",
+               if(!am_has_feature(hostp->features, fe_program_backup_api)) {
+                   fprintf(outf, "ERROR: %s:%s does not support BACKUP-API.\n",
                            hostp->hostname, qname);
                }
-               l = vstralloc("DUMPER ",
-                             dp->program, 
-                             " ",
-                             qname,
-                             " ",
-                             dp->device,
-                             " 0 OPTIONS |",
-                             o,
-                             "\n",
-                             NULL);
+               if(dp->device) {
+                   l = vstralloc("BACKUP ",
+                                 dp->program, 
+                                 " ",
+                                 qname,
+                                 " ",
+                                 qdevice,
+                                 " 0 OPTIONS |",
+                                 o,
+                                 "\n",
+                                 NULL);
+               } else {
+                   l = vstralloc("BACKUP ",
+                                 dp->program, 
+                                 " ",
+                                 qname,
+                                 " 0 OPTIONS |",
+                                 o,
+                                 "\n",
+                                 NULL);
+               }
            }
            amfree(qname);
            amfree(qdevice);
@@ -1716,15 +1797,11 @@ handle_result(
            s[-2] = '\0';
        }
 
-#define sc "OPTIONS "
-       if(strncmp(line, sc, SIZEOF(sc)-1) == 0) {
-#undef sc
+       if(strncmp_const(line, "OPTIONS ") == 0) {
 
-#define sc "features="
-           t = strstr(line, sc);
+           t = strstr(line, "features=");
            if(t != NULL && (isspace((int)t[-1]) || t[-1] == ';')) {
-               t += SIZEOF(sc)-1;
-#undef sc
+               t += SIZEOF("features=")-1;
                am_release_feature_set(hostp->features);
                if((hostp->features = am_string_to_feature(t)) == NULL) {
                    fprintf(outf, "ERROR: %s: bad features value: %s\n",
@@ -1735,18 +1812,12 @@ handle_result(
            continue;
        }
 
-#define sc "OK "
-       if(strncmp(line, sc, SIZEOF(sc)-1) == 0) {
+       if(strncmp_const(line, "OK ") == 0) {
            continue;
-#undef sc
        }
 
-#define sc "ERROR "
-       if(strncmp(line, sc, SIZEOF(sc)-1) == 0) {
-           t = line + SIZEOF(sc) - 1;
-           tch = t[-1];
-#undef sc
-
+       t = line;
+       if(strncmp_const_skip(line, "ERROR ", t, tch) == 0) {
            skip_whitespace(t, tch);
            /*
             * If the "error" is that the "noop" service is unknown, it