using Invercargill; namespace Binman { public static void posix_to_error(int result) throws Error { if(result == 0) { return; } throw new Error(GLib.Quark.from_string("posix"), errno, Posix.strerror(errno)); } public static void reflink_copy(string src, string dest) throws Error { int pid = Posix.fork(); if (pid == 0) { posix_to_error(Posix.execv("/bin/cp", new string[] {"--reflink=always", src, dest})); Posix.exit(Posix.ENOENT); } int status; Posix.waitpid(pid, out status, 0); posix_to_error(status); } public static BinaryData calculate_file_checksum(string path, FileProgressCallback? progress_callback = null) throws Error { var stream = File.new_for_path(path).read(); var checksum = new Checksum(ChecksumType.SHA512); const int increment = 1024 * 1024 * 128; uint64 read = 0; var file_size = stream.query_info("*").get_size(); var to_read = file_size; while(read < to_read) { var data = new uint8[uint64.min(increment, to_read - read)]; data.length = (int)stream.read(data); checksum.update(data, data.length); read += data.length; if(progress_callback != null) { progress_callback((int64)read, file_size); } } var checksum_bytes = new uint8[ChecksumType.SHA512.get_length()]; size_t size = checksum_bytes.length; checksum.get_digest(checksum_bytes, ref size); return new Invercargill.BinaryData.from_byte_array(checksum_bytes); } }