Commits

Mathias Panzenböck committed e5956d7

initial commit

Comments (0)

Files changed (4)

+syntax: glob
+build
+.*
+*~
+cmake_minimum_required(VERSION 2.0)
+
+project(crc)
+
+if(MSVC)
+  # Force to always compile with W4
+  if(CMAKE_CXX_FLAGS MATCHES "/W[0-4]")
+    string(REGEX REPLACE "/W[0-4]" "/W4" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
+  else()
+    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /W4")
+  endif()
+elseif(CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX)
+  # Update if necessary
+  set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -pedantic -Wno-long-long -O2")
+endif()
+
+find_package(Boost COMPONENTS system program_options REQUIRED)
+
+add_executable(crc crc.cpp)
+
+install(TARGETS crc RUNTIME DESTINATION bin)
+
+target_link_libraries(crc
+  ${Boost_SYSTEM_LIBRARY}
+  ${Boost_PROGRAM_OPTIONS_LIBRARY}
+)
+
+install(CODE "
+function(install_symlink TARGET NAME)
+	message(\"-- Installing Symlink: \${NAME} -> \${TARGET}\")
+	execute_process(
+		COMMAND @CMAKE_COMMAND@ -E create_symlink @TARGET@ @NAME@
+		OUTPUT_VARIABLE link_out
+		RESULT_VARIABLE link_res)
+	if(NOT \${link_res} EQUAL 0)
+		message(FATAL_ERROR \"Problem creating symlink \\\"\${NAME}\\\"\")
+	endif()
+
+	list(APPEND CMAKE_INSTALL_MANIFEST_FILES \"\${NAME}\")
+endfunction()
+
+install_symlink(crc @CMAKE_INSTALL_PREFIX@/bin/crc16)
+install_symlink(crc @CMAKE_INSTALL_PREFIX@/bin/crc32)
+install_symlink(crc @CMAKE_INSTALL_PREFIX@/bin/ccit)
+install_symlink(crc @CMAKE_INSTALL_PREFIX@/bin/xmodem)
+")
+
+# uninstall target
+configure_file(
+	"${CMAKE_CURRENT_SOURCE_DIR}/cmake_uninstall.cmake.in"
+	"${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake"
+	IMMEDIATE @ONLY)
+
+add_custom_target(uninstall
+	COMMAND ${CMAKE_COMMAND} -P "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake")

cmake_uninstall.cmake.in

+if (NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt")
+	message(FATAL_ERROR "Cannot find install manifest: \"@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt\"")
+endif()
+
+file(READ "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt" files)
+string(REGEX REPLACE "\n" ";" files "${files}")
+foreach (file ${files})
+	message(STATUS "Uninstalling \"$ENV{DESTDIR}${file}\"")
+	if (EXISTS "$ENV{DESTDIR}${file}")
+		execute_process(
+			COMMAND @CMAKE_COMMAND@ -E remove "$ENV{DESTDIR}${file}"
+			OUTPUT_VARIABLE rm_out
+			RESULT_VARIABLE rm_retval
+		)
+		if(NOT ${rm_retval} EQUAL 0)
+			message(FATAL_ERROR "Problem when removing \"$ENV{DESTDIR}${file}\"")
+		endif ()
+	else ()
+		message(STATUS "File \"$ENV{DESTDIR}${file}\" does not exist.")
+	endif ()
+endforeach()
+#include <string.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+
+#include <string>
+#include <limits>
+#include <iostream>
+#include <algorithm>
+
+#include <boost/filesystem/operations.hpp>
+#include <boost/program_options.hpp>
+#include <boost/crc.hpp>
+#include <boost/format.hpp>
+#include <boost/algorithm/string.hpp>
+
+#define VERSION "1.0"
+
+namespace fs = boost::filesystem;
+namespace po = boost::program_options;
+
+enum Alagorithm {
+	NONE,
+	CRC16,
+	CRC32,
+	CCIT,
+	XMODEM
+};
+
+static void usage(const po::options_description &desc);
+static Alagorithm get_algorithm(const std::string &algorithm);
+static std::string &toupper(std::string &s);
+static void usage_error(const std::string &message);
+static void c_error(int errnum, const std::string &arg);
+static void c_error(const std::string &arg) { c_error(errno, arg); }
+static int getline(FILE *stream, std::string &line);
+
+template<typename value_type>
+static value_type parse(const char *s, int base = 10);
+
+template<>
+unsigned long parse(const char *s, int base);
+
+template<>
+uint16_t parse(const char *s, int base);
+
+template<typename value_type>
+value_type parse(const std::string &s, int base = 10) {
+	return parse<value_type>(s.c_str(), base);
+}
+
+template<typename value_type>
+static value_type parse_small(const char *s, int base) {
+	unsigned long value = parse<unsigned long>(s, base);
+
+	if (value > std::numeric_limits<value_type>::max()) {
+		throw std::overflow_error("number to big for unsigned 16bit value");
+	}
+
+	return value;
+}
+
+template<>
+uint16_t parse(const char *s, int base) {
+	return parse_small<uint16_t>(s, base);
+}
+
+template<>
+unsigned int parse(const char *s, int base) {
+	return parse_small<unsigned int>(s, base);
+}
+
+template<>
+unsigned long parse(const char *s, int base) {
+	char *end = NULL;
+	errno = 0;
+	unsigned long value = strtoul(s, &end, base);
+
+	if (*end) {
+		switch (errno) {
+			case 0:      throw std::runtime_error("error parsing number");
+			case ERANGE: throw std::range_error(strerror(errno));
+			case EINVAL: throw std::invalid_argument(strerror(errno));
+			default:     throw std::runtime_error(strerror(errno));
+		}
+	}
+
+	return value;
+}
+
+
+template<typename CRCType>
+int check_sums(
+		const std::vector<std::string> &files,
+		bool warn,
+		bool quiet,
+		bool status);
+
+template<typename CRCType>
+static int print_sums(
+		const std::vector<std::string> &files,
+		bool binary);
+
+static std::string appname;
+
+int main(int argc, char *argv[]) {
+	appname = argc < 1 ? "crc" : argv[0];
+
+	Alagorithm algorithm = get_algorithm(appname);
+	
+	po::options_description desc("Options");
+	desc.add_options()
+		("binary,b",    "read in binary mode")
+		("check,c",     "read CRC sums from the FILEs and check them")
+		("text,t",      "read in text mode (default)")
+		("algorithm,a", po::value<std::string>(), "CRC algorithm to use. can be: CRC16, CCIT, XMODEM or CRC32")
+		("quiet",       "don't print OK for each successfully verified file")
+		("status",      "don't output anything, status code shows success")
+		("warn,w",      "warn about improperly formatted checksum lines")
+		("help,h",      "display this help and exit")
+		("version,v",   "output version information and exit");
+	
+	po::options_description hidden;
+	hidden.add_options()
+		("files", po::value< std::vector<std::string> >(), "files to process");
+	
+	po::options_description opts;
+	opts.add(desc).add(hidden);
+
+	po::positional_options_description pos;
+	pos.add("files", -1);
+	
+	po::variables_map vm;
+	try {
+		po::store(po::command_line_parser(argc, argv).options(opts).positional(pos).run(), vm);
+		po::notify(vm);
+	}
+	catch (const std::exception &exc) {
+		std::cerr << appname << ": " << exc.what() << std::endl;
+		usage(desc);
+		return 1;
+	}
+	
+	if (vm.count("help")) {
+		usage(desc);
+		return 0;
+	}
+	else if (vm.count("version")) {
+		std::cout << appname << " " << VERSION << std::endl;
+		return 0;
+	}
+
+	bool binary = vm.count("binary") > vm.count("text");
+	bool check  = vm.count("check")  > 0;
+	bool quiet  = vm.count("quiet")  > 0;
+	bool status = vm.count("status") > 0;
+	bool warn   = vm.count("warn")   > 0;
+	std::vector<std::string> files;
+	
+	if (vm.count("files") > 0) {
+		files = vm["files"].as< std::vector<std::string> >();
+	}
+
+	if (files.empty()) {
+		files.push_back("-");
+	}
+
+	if (vm.count("algorithm") > 0) {
+		algorithm = get_algorithm(vm["algorithm"].as<std::string>());
+
+		if (algorithm == NONE) {
+			usage_error("illegal algorithm name: " + vm["algorithm"].as<std::string>());
+			return 1;
+		}
+	}
+	else if (algorithm == NONE) {
+		usage_error("required option --algorithm missing");
+		return 1;
+	}
+
+	try {
+		if (check) {
+			if (vm.count("binary") > 0 || vm.count("text") > 0) {
+				usage_error("the --binary and --text options are meaningless when verifying checksums");
+				return 1;
+			}
+
+			switch (algorithm) {
+			case CRC16:  return check_sums<boost::crc_16_type>(files, warn, quiet, status);
+			case CRC32:  return check_sums<boost::crc_32_type>(files, warn, quiet, status);
+			case CCIT:   return check_sums<boost::crc_ccitt_type>(files, warn, quiet, status);
+			case XMODEM: return check_sums<boost::crc_xmodem_type>(files, warn, quiet, status);
+			default: break;
+			}
+		}
+		else if (warn) {
+			usage_error("the --warn option is meaningful only when verifying checksums");
+			return 1;
+		}
+		else if (quiet) {
+			usage_error("the --quiet option is meaningful only when verifying checksums");
+			return 1;
+		}
+		else if (status) {
+			usage_error("the --status option is meaningful only when verifying checksums");
+			return 1;
+		}
+		else {
+			switch (algorithm) {
+			case CRC16:  return print_sums<boost::crc_16_type>(files, binary);
+			case CRC32:  return print_sums<boost::crc_32_type>(files, binary);
+			case CCIT:   return print_sums<boost::crc_ccitt_type>(files, binary);
+			case XMODEM: return print_sums<boost::crc_xmodem_type>(files, binary);
+			default: break;
+			}
+		}
+	}
+	catch (const std::exception &exc) {
+		std::cerr << appname << ": " << exc.what() << std::endl;
+		return 1;
+	}
+
+	return 1;
+}
+
+void checksum_file_error(const std::string &file, size_t lineno) {
+	std::cerr << appname << ": " << file << ": " << lineno << ": " << "improperly formatted CRC checksum line\n";
+}
+
+template<typename CRCType>
+int check_sums(
+		const std::vector<std::string> &files,
+		bool warn,
+		bool quiet,
+		bool status) {
+	CRCType crc;
+	typedef typename CRCType::value_type sum_t;
+	int rv = 0;
+
+	for (std::vector<std::string>::const_iterator i = files.begin(); i < files.end(); ++ i) {
+		FILE *sums = (*i == "-" ? stdin : fopen(i->c_str(), "r"));
+
+		if (sums) {
+			for (size_t lineno = 1;; ++ lineno) {
+				std::string line;
+				int errnum = getline(sums, line);
+
+				if (errnum == EOF) {
+					break;
+				}
+				else if (errnum != 0) {
+					rv = 1;
+					if (!status) c_error(errnum, *i);
+					continue;
+				}
+
+				size_t pos = line.find(' ');
+				if (pos == 0 || pos == std::string::npos || pos+1 == line.size()) {
+					rv = 1;
+					if (warn) checksum_file_error(*i, lineno);
+					continue;
+				}
+
+				bool binary = line[pos-1] == '*';
+				if (!binary && line[pos+1] != ' ') {
+					rv = 1;
+					if (warn) checksum_file_error(*i, lineno);
+					continue;
+				}
+				size_t seppos = binary ? pos-1 : pos;
+				std::string strsum = line.substr(0, seppos);
+				std::string filename = line.substr(seppos + 2,
+					line[line.size() - 1] == '\n' ? line.size() - seppos - 3 : line.size() - seppos - 2);
+				
+				if (filename.empty()) {
+					rv = 1;
+					if (warn) checksum_file_error(*i, lineno);
+					continue;
+				}
+
+				sum_t sum = 0;
+				try {
+					sum = parse<sum_t>(strsum, 16);
+				}
+				catch (const std::exception &exc) {
+					rv = 1;
+					if (warn) checksum_file_error(*i, lineno);
+					continue;
+				}
+
+				FILE *stream = fopen(filename.c_str(), binary ? "rb" : "r");
+
+				if (stream) {
+					char buf[BUFSIZ];
+
+					for (;;) {
+						size_t count = fread(buf, 1, BUFSIZ, stream);
+						crc.process_bytes(buf, count);
+						if (count < BUFSIZ) {
+							if (feof(stream)) {
+								if (sum != crc.checksum()) {
+									if (!status) std::cout << filename << ": FAILED\n";
+								}
+								else if (!quiet && !status) {
+									if (!status) std::cout << filename << ": OK\n";
+								}
+							}
+							else { // ferror(stream)
+								rv = 1;
+								if (!status) c_error(*i);
+							}
+
+							if (fclose(stream) != 0) {
+								rv = 1;
+								if (!status) c_error(*i);
+							}
+							break;
+						}
+					}
+
+					crc.reset();
+				}
+				else {
+					rv = 1;
+					if (!status) c_error(*i);
+				}
+			}
+
+			if (*i != "-" && fclose(sums) != 0) {
+				rv = 1;
+				if (!status) c_error(*i);
+			}
+		}
+		else {
+			rv = 1;
+			if (!status) c_error(*i);
+		}
+	}
+	return rv;
+}
+
+template<typename CRCType>
+int print_sums(
+		const std::vector<std::string> &files,
+		bool binary) {
+	CRCType crc;
+	int rv = 0;
+	std::string fmt = (boost::format("%%0%dx%%c %%s\n") % (CRCType::bit_count / 4)).str();
+	for (std::vector<std::string>::const_iterator i = files.begin(); i < files.end(); ++ i) {
+		// using C FILEs to get useful error messages
+		FILE *stream = (*i == "-" ? stdin : fopen(i->c_str(), binary ? "rb" : "r"));
+
+		if (stream) {
+			char buf[BUFSIZ];
+			
+			for (;;) {
+				size_t count = fread(buf, 1, BUFSIZ, stream);
+				crc.process_bytes(buf, count);
+				if (count < BUFSIZ) {
+					if (feof(stream)) {
+						std::cout << boost::format(fmt) % crc.checksum() % (binary ? '*' : ' ') % *i;
+					}
+					else { // ferror(stream)
+						rv = 1;
+						c_error(*i);
+					}
+
+					if (*i != "-" && fclose(stream) != 0) {
+						rv = 1;
+						c_error(*i);
+					}
+					break;
+				}
+			}
+
+			crc.reset();
+		}
+		else {
+			rv = 1;
+			c_error(*i);
+		}
+	}
+
+	return rv;
+}
+
+void usage_error(const std::string &message) {
+	std::cerr <<
+		appname << ": " << message << "\n"
+		"Try `" << appname << " --help' for more information.\n";
+}
+
+void c_error(int errnum, const std::string &arg) {
+	std::cerr <<
+		appname << ": " << strerror(errnum) << ": " << arg << std::endl;
+}
+
+void usage(const po::options_description &desc) {
+	std::cout <<
+		"Usage: " << appname << " [OPTION...] FILE...\n"
+		"Print or check CRC checksums.\n"
+		"With no FILE, or when FILE is -, read standard input.\n"
+		"\n" <<
+		desc <<
+		"\n"
+		"The sums are computed using Boosts CRC library.  When checking, the input\n"
+		"should be a former output of this program.  The default mode is to print\n"
+		"a line with checksum, a character indicating type (`*' for binary, ` ' for\n"
+		"text), and name for each FILE.\n"
+		"\n"
+		"(c) 2011 Mathias Panzenböck\n";
+}
+
+std::string &toupper(std::string &s) {
+	std::transform(s.begin(), s.end(), s.begin(), (int (*)(int)) std::toupper);
+	return s;
+}
+
+Alagorithm get_algorithm(const std::string &algorithm) {
+	std::string s = algorithm;
+	toupper(s);
+	
+	if (s == "CRC16") {
+		return CRC16;
+	}
+	else if (s == "CRC32") {
+		return CRC32;
+	}
+	else if (s == "CCIT") {
+		return CCIT;
+	}
+	else if (s == "XMODEM") {
+		return XMODEM;
+	}
+	else {
+		return NONE;
+	}
+}
+
+int getline(FILE *stream, std::string &line) {
+	int ch = fgetc(stream);
+	switch (ch) {
+	case EOF:
+		if (ferror(stream)) {
+			return errno;
+		}
+		return EOF;
+	case '\n':
+		return 0;
+	default:
+		line += (char) ch;
+	}
+
+	for (;;) {
+		ch = fgetc(stream);
+		switch (ch) {
+		case EOF:  if (ferror(stream)) return errno;
+		case '\n': return 0;
+		default:   line += (char) ch;
+		}
+	}
+	return 0;
+}
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.