9 #define _FILE_OFFSET_BITS 64
68 "CernVM File System consistency checker, version %s\n\n"
69 "This tool checks a cvmfs cache directory for consistency.\n"
70 "If necessary, the managed cache db is removed so that\n"
71 "it will be rebuilt on next mount.\n\n"
72 "Usage: cvmfs_fsck [-v] [-p] [-f] [-j #threads] <cache directory>\n"
74 " -v verbose output\n"
75 " -p try to fix automatically\n"
76 " -f force rebuild of managed cache db on next mount\n"
77 " -j number of concurrent integrity check worker threads\n",
82 static bool GetNextFile(
string *relative_path,
string *hash_name) {
88 const string name = d->d_name;
89 if ((name ==
".") || (name ==
".."))
95 const string path = *
g_cache_dir +
"/" + *relative_path;
102 if (!S_ISREG(info.st_mode)) {
119 snprintf(hex,
sizeof(hex),
"%02x",
g_num_dirs);
126 "Invalid cache directory, %s/%s does not exist",
130 goto get_next_file_again;
139 string relative_path;
143 const string path = *
g_cache_dir +
"/" + relative_path;
151 if (relative_path[relative_path.length() - 1] ==
'T') {
153 "Warning: temporary file catalog %s found", path.c_str());
156 if (unlink(relative_path.c_str()) == 0) {
168 int fd_src = open(relative_path.c_str(), O_RDONLY);
185 if (hash != expected_hash) {
192 if (hash != expected_hash) {
194 const string quarantaine_path =
"./quarantaine/" + hash_name;
196 if (rename(relative_path.c_str(), quarantaine_path.c_str()) == 0) {
198 "Fix: %s is corrupted, moved to quarantaine folder",
203 "Warning: failed to move %s into quarantaine folder",
205 if (unlink(relative_path.c_str()) == 0) {
207 "Fix: %s is corrupted, file unlinked", path.c_str());
211 "Error: %s is corrupted, could not unlink",
227 "Error: %s has compressed checksum %s, "
228 "delete this file from cache directory!",
229 path.c_str(), hash.
ToString().c_str());
242 int main(
int argc,
char **argv) {
248 while ((c = getopt(argc, argv,
"hvpfj:")) != -1) {
266 "There is at least one worker thread required");
278 if (optind >= argc) {
291 if ((dirp_txn = opendir(
"txn")) == NULL) {
293 "Invalid cache directory, %s/txn does not exist",
299 const string name = d->d_name;
300 if ((name ==
".") || (name ==
".."))
304 "Warning: temporary directory %s/txn is not empty\n"
305 "If this repository is currently _not_ mounted, "
306 "you can remove its contents",
318 pthread_t *workers =
reinterpret_cast<pthread_t *
>(
325 if (pthread_create(&workers[i], NULL,
MainCheck, NULL) != 0) {
330 for (
int i = g_num_threads - 1; i >= 0; --i) {
331 pthread_join(workers[i], NULL);
345 if (unlink(
"cachedb") == 0) {
347 "Fix: managed cache db unlinked, will be rebuilt on next mount");
350 if (errno != ENOENT) {
352 "Error: could not unlink managed cache database (%d)", errno);
361 "WARNING: There might by corrupted files in the kernel buffers.\n"
362 "Remount CernVM-FS or run 'echo 3 > /proc/sys/vm/drop_caches'"
bool HashFile(const std::string &filename, Any *any_digest)
static void Usage(const char *progname)
std::string ToString(const bool with_suffix=false) const
struct cvmcache_object_info __attribute__
atomic_int32 g_num_err_fixed
atomic_int32 g_num_tmp_catalog
bool CompressFd2Null(int fd_src, shash::Any *compressed_hash, uint64_t *processed_bytes)
static bool GetNextFile(string *relative_path, string *hash_name)
static void * MainCheck(void *data __attribute__((unused)))
pthread_mutex_t g_lock_traverse
atomic_int32 g_force_rebuild
atomic_int32 g_modified_cache
Any MkFromHexPtr(const HexPtr hex, const char suffix)
std::string MakeCanonicalPath(const std::string &path)
atomic_int32 g_num_err_operational
atomic_int32 g_num_err_unfixed
CVMFS_EXPORT void LogCvmfs(const LogSource source, const int mask, const char *format,...)