+ }
+}
+
+
+void
+run_calcsize(
+ char *config,
+ char *program,
+ char *disk,
+ char *dirname,
+ GSList *levels,
+ char *file_exclude,
+ char *file_include)
+{
+ char *cmd, *cmdline;
+ char *command;
+ GPtrArray *argv_ptr = g_ptr_array_new();
+ char tmppath[PATH_MAX];
+ char number[NUM_STR_SIZE];
+ GSList *alevel;
+ guint level;
+ guint i;
+ char *match_expr;
+ int pipefd = -1, nullfd = -1;
+ pid_t calcpid;
+ times_t start_time;
+ FILE *dumpout = NULL;
+ int dumpsince;
+ char *errmsg = NULL;
+ char *line = NULL;
+ amwait_t wait_status;
+ int len;
+ char *qdisk;
+ amandates_t *amdp;
+ char *amandates_file;
+
+ qdisk = quote_string(disk);
+
+ amandates_file = getconf_str(CNF_AMANDATES);
+ if(!start_amandates(amandates_file, 0)) {
+ char *errstr = strerror(errno);
+ char *errmsg = vstrallocf(_("could not open %s: %s"), amandates_file, errstr);
+ char *qerrmsg = quote_string(errmsg);
+ g_printf(_("ERROR %s\n"), qerrmsg);
+ amfree(qdisk);
+ amfree(errmsg);
+ amfree(qerrmsg);
+ return;
+ }
+
+ startclock();
+ cmd = vstralloc(amlibexecdir, "/", "calcsize", NULL);
+
+
+ g_ptr_array_add(argv_ptr, stralloc("calcsize"));
+ if (config)
+ g_ptr_array_add(argv_ptr, stralloc(config));
+ else
+ g_ptr_array_add(argv_ptr, stralloc("NOCONFIG"));
+
+ g_ptr_array_add(argv_ptr, stralloc(program));
+
+ canonicalize_pathname(disk, tmppath);
+ g_ptr_array_add(argv_ptr, stralloc(tmppath));
+ canonicalize_pathname(dirname, tmppath);
+ g_ptr_array_add(argv_ptr, stralloc(tmppath));
+
+ if (file_exclude) {
+ g_ptr_array_add(argv_ptr, stralloc("-X"));
+ g_ptr_array_add(argv_ptr, stralloc(file_exclude));
+ }
+
+ if (file_include) {
+ g_ptr_array_add(argv_ptr, stralloc("-I"));
+ g_ptr_array_add(argv_ptr, stralloc(file_include));
+ }
+
+ for (alevel = levels; alevel != NULL; alevel = alevel->next) {
+ amdp = amandates_lookup(disk);
+ level = GPOINTER_TO_INT(alevel->data);
+ dbprintf("level: %d\n", level);
+ dumpsince = 0;
+ for (i=0; i < level; i++) {
+ if (dumpsince < amdp->dates[i])
+ dumpsince = amdp->dates[i];
+ }
+ g_snprintf(number, SIZEOF(number), "%d", level);
+ g_ptr_array_add(argv_ptr, stralloc(number));
+ g_snprintf(number, SIZEOF(number), "%d", dumpsince);
+ g_ptr_array_add(argv_ptr, stralloc(number));
+ }
+
+ g_ptr_array_add(argv_ptr, NULL);
+ command = (char *)g_ptr_array_index(argv_ptr, 0);
+ cmdline = stralloc(command);
+ for(i = 1; i < argv_ptr->len - 1; i++)
+ cmdline = vstrextend(&cmdline, " ",
+ (char *)g_ptr_array_index(argv_ptr,i), NULL);
+ dbprintf(_("running: \"%s\"\n"), cmdline);
+ amfree(cmdline);
+
+ start_time = curclock();
+
+ fflush(stderr); fflush(stdout);
+
+ if ((nullfd = open("/dev/null", O_RDWR)) == -1) {
+ errmsg = vstrallocf(_("Cannot access /dev/null : %s"),
+ strerror(errno));
+ dbprintf("%s\n", errmsg);
+ goto common_exit;
+ }
+
+ calcpid = pipespawnv(cmd, STDERR_PIPE, 0,
+ &nullfd, &nullfd, &pipefd, (char **)argv_ptr->pdata);
+ amfree(cmd);
+
+ dumpout = fdopen(pipefd,"r");
+ if (!dumpout) {
+ error(_("Can't fdopen: %s"), strerror(errno));
+ /*NOTREACHED*/
+ }
+
+ match_expr = vstralloc(" %d SIZE %lld", NULL);
+ len = strlen(qdisk);
+ for(; (line = agets(dumpout)) != NULL; free(line)) {
+ long long size_ = (long long)0;
+ if (line[0] == '\0' || (int)strlen(line) <= len)
+ continue;
+ /* Don't use sscanf for qdisk because it can have a '%'. */
+ if (strncmp(line, qdisk, len) == 0 &&
+ sscanf(line+len, match_expr, &level, &size_) == 2) {
+ g_printf("%d %lld %d\n", level, size_, 1); /* write to sendsize */
+ dbprintf(_("estimate size for %s level %d: %lld KB\n"),
+ qdisk, level, size_);
+ }
+ }
+ amfree(match_expr);
+
+ dbprintf(_("waiting for %s %s child (pid=%d)\n"),
+ command, qdisk, (int)calcpid);
+ waitpid(calcpid, &wait_status, 0);
+ if (WIFSIGNALED(wait_status)) {
+ errmsg = vstrallocf(_("%s terminated with signal %d: see %s"),
+ "calcsize", WTERMSIG(wait_status),
+ dbfn());
+ } else if (WIFEXITED(wait_status)) {
+ if (WEXITSTATUS(wait_status) != 0) {
+ errmsg = vstrallocf(_("%s exited with status %d: see %s"),
+ "calcsize", WEXITSTATUS(wait_status),
+ dbfn());
+ } else {
+ /* Normal exit */
+ }
+ } else {
+ errmsg = vstrallocf(_("%s got bad exit: see %s"),
+ "calcsize", dbfn());
+ }
+
+ dbprintf(_("after %s %s wait: child pid=%d status=%d\n"),
+ command, qdisk,
+ (int)calcpid, WEXITSTATUS(wait_status));
+
+ dbprintf(_(".....\n"));
+ dbprintf(_("estimate time for %s: %s\n"),
+ qdisk,
+ walltime_str(timessub(curclock(), start_time)));
+
+common_exit:
+ if (errmsg && errmsg[0] != '\0') {
+ char *qerrmsg = quote_string(errmsg);
+ dbprintf(_("errmsg is %s\n"), errmsg);
+ g_printf("ERROR %s\n", qerrmsg);
+ amfree(qerrmsg);
+ }
+ amfree(qdisk);
+ amfree(errmsg);
+ g_ptr_array_free_full(argv_ptr);
+ amfree(cmd);
+}
+
+
+gboolean
+check_access(
+ char * filename,
+ int mode)
+{
+ char *noun, *adjective;
+ char *quoted = quote_string(filename);
+
+ if(mode == F_OK)
+ noun = "find", adjective = "exists";
+ else if((mode & X_OK) == X_OK)
+ noun = "execute", adjective = "executable";
+ else if((mode & (W_OK|R_OK)) == (W_OK|R_OK))
+ noun = "read/write", adjective = "read/writable";
+ else
+ noun = "access", adjective = "accessible";
+
+ if(access(filename, mode) == -1) {
+ g_printf(_("ERROR [can not %s %s: %s]\n"), noun, quoted, strerror(errno));
+ amfree(quoted);
+ return FALSE;
+ } else {
+ g_printf(_("OK %s %s\n"), quoted, adjective);
+ }
+ amfree(quoted);
+ return TRUE;
+}
+
+gboolean
+check_file(
+ char * filename,
+ int mode)
+{
+ struct stat stat_buf;
+ char *quoted;
+
+ if(!stat(filename, &stat_buf)) {
+ if(!S_ISREG(stat_buf.st_mode)) {
+ quoted = quote_string(filename);
+ g_printf(_("ERROR [%s is not a file]\n"), quoted);
+ amfree(quoted);
+ return FALSE;
+ }
+ } else {
+ int save_errno = errno;
+ quoted = quote_string(filename);
+ g_printf(_("ERROR [can not stat %s: %s]\n"), quoted,
+ strerror(save_errno));
+ amfree(quoted);
+ return FALSE;
+ }
+ if (getuid() == geteuid()) {
+ return check_access(filename, mode);
+ } else {
+ quoted = quote_string(filename);
+ g_printf("OK %s\n", quoted);
+ amfree(quoted);
+ }
+ return TRUE;
+}
+
+gboolean
+check_dir(
+ char * dirname,
+ int mode)
+{
+ struct stat stat_buf;
+ char *quoted;
+ char *dir;
+
+ if(!stat(dirname, &stat_buf)) {
+ if(!S_ISDIR(stat_buf.st_mode)) {
+ quoted = quote_string(dirname);
+ g_printf(_("ERROR [%s is not a directory]\n"), quoted);
+ amfree(quoted);
+ return FALSE;
+ }
+ } else {
+ int save_errno = errno;
+ quoted = quote_string(dirname);
+ g_printf(_("ERROR [can not stat %s: %s]\n"), quoted,
+ strerror(save_errno));
+ amfree(quoted);
+ return FALSE;
+ }
+ if (getuid() == geteuid()) {
+ gboolean result;
+ dir = stralloc2(dirname, "/.");
+ result = check_access(dir, mode);
+ amfree(dir);
+ return result;
+ } else {
+ quoted = quote_string(dirname);
+ g_printf("OK %s\n", quoted);
+ amfree(quoted);
+ }
+ return TRUE;
+}
+
+gboolean
+check_suid(
+ char * filename)
+{
+#ifndef SINGLE_USERID
+ struct stat stat_buf;
+ char *quoted = quote_string(filename);
+
+ if(!stat(filename, &stat_buf)) {
+ if(stat_buf.st_uid != 0 ) {
+ g_printf(_("ERROR [%s is not owned by root]\n"), quoted);
+ amfree(quoted);
+ return FALSE;
+ }
+ if((stat_buf.st_mode & S_ISUID) != S_ISUID) {
+ g_printf(_("ERROR [%s is not SUID root]\n"), quoted);
+ amfree(quoted);
+ return FALSE;
+ }
+ }
+ else {
+ g_printf(_("ERROR [can not stat %s: %s]\n"), quoted, strerror(errno));
+ amfree(quoted);
+ return FALSE;
+ }
+ amfree(quoted);
+#else
+ (void)filename; /* Quiet unused parameter warning */
+#endif
+ return TRUE;
+}
+
+/*
+ * Returns the value of the first integer in a string.
+ */
+
+double
+the_num(
+ char * str,
+ int pos)
+{
+ char *num;
+ int ch;
+ double d;
+
+ do {
+ ch = *str++;
+ while(ch && !isdigit(ch)) ch = *str++;
+ if (pos == 1) break;
+ pos--;
+ while(ch && (isdigit(ch) || ch == '.')) ch = *str++;
+ } while (ch);
+ num = str - 1;
+ while(isdigit(ch) || ch == '.') ch = *str++;
+ str[-1] = '\0';
+ d = atof(num);
+ str[-1] = (char)ch;
+ return d;
+}
+
+
+char *
+config_errors_to_error_string(
+ GSList *errlist)
+{
+ char *errmsg;
+ gboolean multiple_errors = FALSE;
+
+ if (errlist) {
+ errmsg = (char *)errlist->data;
+ if (errlist->next)
+ multiple_errors = TRUE;
+ } else {
+ errmsg = _("(no error message)");
+ }
+
+ return vstrallocf("ERROR %s%s", errmsg,
+ multiple_errors? _(" (additional errors not displayed)"):"");
+}
+
+
+void
+add_type_table(
+ dmpline_t typ,
+ amregex_t **re_table,
+ amregex_t *orig_re_table,
+ GSList *normal_message,
+ GSList *ignore_message,
+ GSList *strange_message)
+{
+ amregex_t *rp;
+
+ for(rp = orig_re_table; rp->regex != NULL; rp++) {
+ if (rp->typ == typ) {
+ int found = 0;
+ GSList *mes;
+
+ for (mes = normal_message; mes != NULL; mes = mes->next) {
+ if (strcmp(rp->regex, (char *)mes->data) == 0)
+ found = 1;
+ }
+ for (mes = ignore_message; mes != NULL; mes = mes->next) {
+ if (strcmp(rp->regex, (char *)mes->data) == 0)
+ found = 1;
+ }
+ for (mes = strange_message; mes != NULL; mes = mes->next) {
+ if (strcmp(rp->regex, (char *)mes->data) == 0)
+ found = 1;
+ }
+ if (found == 0) {
+ (*re_table)->regex = rp->regex;
+ (*re_table)->srcline = rp->srcline;
+ (*re_table)->scale = rp->scale;
+ (*re_table)->field = rp->field;
+ (*re_table)->typ = rp->typ;
+ (*re_table)++;