+ PARA_ERROR_LOG("failed to check table %s\n", table_name);
+ else
+ PARA_NOTICE_LOG("successfully checked table %s\n", table_name);
+ return ret;
+}
+
+static int check_all_tables(char *base_dir)
+{
+ DIR *dir;
+ struct dirent *entry;
+ int cwd_fd, ret2, ret = para_opendir(base_dir, &dir, &cwd_fd);
+
+ if (ret < 0)
+ return ret;
+ while ((entry = readdir(dir))) {
+ mode_t m;
+ struct stat s;
+ if (!strcmp(entry->d_name, "."))
+ continue;
+ if (!strcmp(entry->d_name, ".."))
+ continue;
+ if (lstat(entry->d_name, &s) == -1)
+ continue;
+ m = s.st_mode;
+ if (!S_ISDIR(m))
+ continue;
+ ret = check_table(base_dir, entry->d_name);
+ if (ret < 0)
+ break;
+ }
+ closedir(dir);
+ ret2 = para_fchdir(cwd_fd);
+ if (ret2 < 0 && ret >= 0)
+ ret = ret2;
+ close(cwd_fd);
+ return ret;
+}
+
+/**
+ * The praslash database check program.
+ *
+ * \param argc Usual arg count.
+ * \param argv Usual arg vector.
+ *
+ * \return \p EXIT_SUCCESS or \p EXIT_FAILURE.
+ */
+int main(int argc, char **argv)
+{
+ int i, ret;
+ char *base_dir = NULL;
+
+ ret = fsck_cmdline_parser(argc, argv, &conf);
+ if (ret < 0) {
+ ret = -E_FSCK_SYNTAX;
+ goto out;
+ }
+ HANDLE_VERSION_FLAG("fsck", conf);
+ loglevel = get_loglevel_by_name(conf.loglevel_arg);
+ if (conf.base_dir_given)
+ base_dir = para_strdup(conf.base_dir_arg);
+ else {
+ char *home = para_homedir();
+ base_dir = make_message("%s/.paraslash/afs_database", home);
+ free(home);
+ }
+ if (!conf.inputs_num) {
+ ret = check_all_tables(base_dir);
+ goto out;
+ }
+ for (i = 0; i < conf.inputs_num; i++) {
+ ret = check_table(base_dir, conf.inputs[i]);
+ if (ret < 0)
+ break;
+ }
+out:
+ if (ret < 0) {
+ PARA_ERROR_LOG("%s%s: %s\n",
+ base_dir? "base_dir: " : "",
+ base_dir? base_dir : "",
+ para_strerror(-ret)
+ );
+ } else
+ PARA_NOTICE_LOG("success\n");
+ if (base_dir)
+ free(base_dir);
+ return ret < 0? EXIT_FAILURE : EXIT_SUCCESS;