Example #1
0
void
process_file(const char* path)
{
	struct stat stat;
	if (::lstat(path, &stat) != 0) {
		fprintf(stderr, "Could not stat file \"%s\": %s\n", path,
			strerror(errno));
		return;
	}

	if (S_ISDIR(stat.st_mode)) {
		process_directory(path);
		return;
	}
	if (S_ISLNK(stat.st_mode))
		return;

	int file = open(path, O_RDONLY);
	if (file < 0) {
		fprintf(stderr, "Could not open file \"%s\": %s\n", path,
			strerror(errno));
		return;
	}

	status_t status = gSHA.Process(file);
	if (status != B_OK) {
		fprintf(stderr, "Computing SHA failed \"%s\": %s\n", path,
			strerror(status));
		return;
	}

	file_entry entry;
	memcpy(entry.hash, gSHA.Digest(), SHA_DIGEST_LENGTH);
	entry.node = stat.st_ino;
	entry.path = path;

	//printf("%s  %s\n", entry.HashString().c_str(), path);

	gFiles.push_back(entry);

	static bigtime_t sLastUpdate = -1;
	if (system_time() - sLastUpdate > 500000) {
		printf("%ld files scanned\33[1A\n", gFiles.size());
		sLastUpdate = system_time();
	}
}
void
process_file(const file_entry& entry, int number)
{
	struct stat stat;
	if (::stat(entry.path.c_str(), &stat) != 0) {
		fprintf(stderr, "Could not stat file \"%s\": %s\n", entry.path.c_str(),
			strerror(errno));
		return;
	}

	if (stat.st_ino != entry.node) {
		fprintf(stderr, "\"%s\": inode changed from %Ld to %Ld\n",
			entry.path.c_str(), entry.node, stat.st_ino);
	}

	int file = open(entry.path.c_str(), O_RDONLY);
	if (file < 0) {
		fprintf(stderr, "Could not open file \"%s\": %s\n", entry.path.c_str(),
			strerror(errno));
		return;
	}

	status_t status = gSHA.Process(file);
	if (status != B_OK) {
		fprintf(stderr, "Computing SHA failed \"%s\": %s\n", entry.path.c_str(),
			strerror(status));
		return;
	}

	if (memcmp(entry.hash, gSHA.Digest(), SHA_DIGEST_LENGTH))
		fprintf(stderr, "\"%s\": Contents differ!\n", entry.path.c_str());

	static bigtime_t sLastUpdate = -1;
	if (system_time() - sLastUpdate > 500000) {
		printf("%ld files scanned\33[1A\n", number);
		sLastUpdate = system_time();
	}
}
Example #3
0
int
main(int argc, char** argv)
{
	if (argc < 2) {
		fprintf(stderr, "usage: %s <hash-file> [<files> ...]\n"
			"\tWhen invoked without files, the hash-file is updated only.\n",
			kProgramName);
		return 1;
	}

	const char* hashFileName = argv[1];

	status_t status = gSHA.Init();
	if (status != B_OK) {
		fprintf(stderr, "%s: Could not initialize SHA processor: %s\n",
			kProgramName, strerror(status));
		return 1;
	}

	int fileCount = argc - 2;
	char** files = argv + 2;

	if (argc == 2) {
		// read files from hash file

		int file = open(hashFileName, O_RDONLY);
		if (file < 0) {
			fprintf(stderr, "%s: Could not open hash file \"%s\": %s\n",
				kProgramName, hashFileName, strerror(status));
			return 1;
		}

		char buffer[2048];
		read(file, buffer, 4);
		if (memcmp(buffer, "HASH", 4)) {
			fprintf(stderr, "%s: \"%s\" is not a hash file\n",
				kProgramName, hashFileName);
			close(file);
			return 1;
		}
		read(file, &fileCount, sizeof(int));
		TRACE("Found %d path(s):\n", fileCount);

		files = (char**)malloc(fileCount * sizeof(char*));
		if (files == NULL) {
			fprintf(stderr, "%s: Could not allocate %ld bytes\n",
				kProgramName, fileCount * sizeof(char*));
			close(file);
			return 1;
		}

		for (int i = 0; i < fileCount; i++) {
			int length;
			read(file, &length, sizeof(int));

			files[i] = (char*)malloc(length + 1);
			if (files[i] == NULL) {
				fprintf(stderr, "%s: Could not allocate %d bytes\n",
					kProgramName, length + 1);
				close(file);
				// TODO: we actually leak memory here, but it's not important in this context
				return 1;
			}
			read(file, files[i], length + 1);
			TRACE("\t%s\n", files[i]);
		}

		close(file);
	} else {
		// Normalize paths
		char** normalizedFiles = (char**)malloc(fileCount * sizeof(char*));
		if (normalizedFiles == NULL) {
			fprintf(stderr, "%s: Could not allocate %ld bytes\n",
				kProgramName, fileCount * sizeof(char*));
			return 1;
		}

		for (int i = 0; i < fileCount; i++) {
			BPath path(files[i], NULL, true);
			normalizedFiles[i] = strdup(path.Path());
			if (normalizedFiles[i] == NULL) {
				fprintf(stderr, "%s: Could not allocate %ld bytes\n",
					kProgramName, strlen(path.Path()) + 1);
				return 1;
			}
		}

		files = normalizedFiles;
	}

	bigtime_t start = system_time();

	for (int i = 0; i < fileCount; i++) {
		process_file(files[i]);
	}

	sort(gFiles.begin(), gFiles.end());

	bigtime_t runtime = system_time() - start;

	write_hash_file(hashFileName, fileCount, files);

	if (gFiles.size() > 0) {
		printf("Generated hashes for %ld files in %g seconds, %g msec per "
			"file.\n", gFiles.size(), runtime / 1000000.0,
			runtime / 1000.0 / gFiles.size());
	}

	for (int i = 0; i < fileCount; i++) {
		free(files[i]);
	}
	free(files);

	return 0;
}
int
main(int argc, char** argv)
{
	if (argc != 2) {
		fprintf(stderr, "usage: %s <hash-file>\n", kProgramName);
		return 1;
	}

	const char* hashFileName = argv[1];

	status_t status = gSHA.Init();
	if (status != B_OK) {
		fprintf(stderr, "%s: Could not initialize SHA processor: %s\n",
			kProgramName, strerror(status));
		return 1;
	}

	// read files from hash file

	int file = open(hashFileName, O_RDONLY);
	if (file < 0) {
		fprintf(stderr, "%s: Could not open hash file \"%s\": %s\n",
			kProgramName, hashFileName, strerror(status));
		return 1;
	}

	char buffer[2048];
	read(file, buffer, 4);
	if (memcmp(buffer, "HASH", 4)) {
		fprintf(stderr, "%s: \"%s\" is not a hash file\n",
			kProgramName, hashFileName);
		close(file);
		return 1;
	}

	int fileCount;
	read(file, &fileCount, sizeof(int));
	TRACE("Skip %d path(s)\n", fileCount);

	// Skip paths, we don't need it for the consistency check

	for (int i = 0; i < fileCount; i++) {
		int length;
		read(file, &length, sizeof(int));
		lseek(file, length + 1, SEEK_CUR);
	}

	// Read file names and their hash

	read(file, &fileCount, sizeof(int));
	TRACE("Found %d file(s)\n", fileCount);

	for (int i = 0; i < fileCount; i++) {
		file_entry entry;
		read(file, entry.hash, SHA_DIGEST_LENGTH);
		read(file, &entry.node, sizeof(ino_t));

		int length;
		read(file, &length, sizeof(int));
		read(file, buffer, length + 1);

		entry.path = buffer;

		gFiles.push_back(entry);
	}

	close(file);

	bigtime_t start = system_time();

	for (int i = 0; i < fileCount; i++) {
		process_file(gFiles[i], i);
	}

	bigtime_t runtime = system_time() - start;

	if (gFiles.size() > 0) {
		printf("Consistency check for %ld files in %g seconds, %g msec per "
			"file.\n", gFiles.size(), runtime / 1000000.0,
			runtime / 1000.0 / gFiles.size());
	}

	return 0;
}