Add a new option to create files with the MD5 and SHA512 checksums of all the disk image types produced. This was implemented in diskimage-builder upstream as commit 2ea5feca5c4b64867ac327736edfb20408f8840e and commit 22952b7ea0543bb4f446752976d1d8ba232b021a. --- dib/cmdline.ml | 7 +++++- dib/cmdline.mli | 1 + dib/dib.ml | 69 ++++++++++++++++++++++++++++++++++++++++++++++++++++---- dib/virt-dib.pod | 13 +++++++++++ 4 files changed, 85 insertions(+), 5 deletions(-) diff --git a/dib/cmdline.ml b/dib/cmdline.ml index 144e5a7..418dbbd 100644 --- a/dib/cmdline.ml +++ b/dib/cmdline.ml @@ -56,6 +56,7 @@ type cmdline = { arch : string; envvars : string list; docker_target : string option; + checksum : bool; } let parse_cmdline () = @@ -158,6 +159,8 @@ read the man page virt-dib(1). let docker_target = ref None in let set_docker_target arg = docker_target := Some arg in + let checksum = ref false in + let argspec = [ [ S 'p'; L"element-path" ], Getopt.String ("path", append_element_path), s_"Add new a elements location"; [ L"exclude-element" ], Getopt.String ("element", append_excluded_element), @@ -177,6 +180,7 @@ read the man page virt-dib(1). [ L"extra-packages" ], Getopt.String ("pkg,...", append_extra_packages), s_"Add extra packages to install"; [ L"docker-target" ], Getopt.String ("target", set_docker_target), s_"Repo and tag for docker"; + [ L"checksum" ], Getopt.Set checksum, s_"Generate MD5 and SHA256 checksum files"; [ L"ramdisk" ], Getopt.Set is_ramdisk, "Switch to a ramdisk build"; [ L"ramdisk-element" ], Getopt.Set_string ("name", ramdisk_element), s_"Main element for building ramdisks"; @@ -234,6 +238,7 @@ read the man page virt-dib(1). let machine_readable = !machine_readable in let extra_packages = List.rev !extra_packages in let docker_target = !docker_target in + let checksum = !checksum in (* No elements and machine-readable mode? Print some facts. *) if elements = [] && machine_readable then ( @@ -266,5 +271,5 @@ read the man page virt-dib(1). extra_packages = extra_packages; memsize = memsize; network = network; smp = smp; delete_on_failure = delete_on_failure; formats = formats; arch = arch; envvars = envvars; - docker_target = docker_target; + docker_target = docker_target; checksum = checksum; } diff --git a/dib/cmdline.mli b/dib/cmdline.mli index 79364fb..2e004a0 100644 --- a/dib/cmdline.mli +++ b/dib/cmdline.mli @@ -48,6 +48,7 @@ type cmdline = { arch : string; envvars : string list; docker_target : string option; + checksum : bool; } val parse_cmdline : unit -> cmdline diff --git a/dib/dib.ml b/dib/dib.ml index 9505c52..7f05870 100644 --- a/dib/dib.ml +++ b/dib/dib.ml @@ -27,6 +27,10 @@ open Printf module G = Guestfs +let checksums = [ "md5"; "sha512" ] +and tool_of_checksum csum = + csum ^ "sum" + let exclude_elements elements = function | [] -> (* No elements to filter out, so just don't bother iterating through @@ -68,9 +72,10 @@ let envvars_string l = String.concat "\n" l let prepare_external ~envvars ~dib_args ~dib_vars ~out_name ~root_label - ~rootfs_uuid ~image_cache ~arch ~network ~debug ~fs_type + ~rootfs_uuid ~image_cache ~arch ~network ~debug ~fs_type ~checksum destdir libdir hooksdir fakebindir all_elements element_paths = let network_string = if network then "" else "1" in + let checksum_string = if checksum then "1" else "" in let run_extra = sprintf "\ #!/bin/bash @@ -106,6 +111,7 @@ export TMPDIR=\"${TMP_MOUNT_PATH}/tmp\" export TMP_DIR=\"${TMPDIR}\" export DIB_DEBUG_TRACE=%d export FS_TYPE=%s +export DIB_CHECKSUM=%s ENVIRONMENT_D_DIR=$target_dir/../environment.d @@ -136,13 +142,15 @@ $target_dir/$script (String.concat ":" element_paths) (quote dib_vars) debug - fs_type in + fs_type + checksum_string in write_script (destdir // "run-part-extra.sh") run_extra let prepare_aux ~envvars ~dib_args ~dib_vars ~log_file ~out_name ~rootfs_uuid ~arch ~network ~root_label ~install_type ~debug ~extra_packages ~fs_type - destdir all_elements = + ~checksum destdir all_elements = let network_string = if network then "" else "1" in + let checksum_string = if checksum then "1" else "" in let script_run_part = sprintf "\ #!/bin/bash @@ -191,6 +199,7 @@ export DIB_ENV=%s export DIB_DEBUG_TRACE=%d export DIB_NO_TMPFS=1 export FS_TYPE=%s +export DIB_CHECKSUM=%s export TMP_BUILD_DIR=$mysysroot/tmp/aux export TMP_IMAGE_DIR=$mysysroot/tmp/aux @@ -229,7 +238,8 @@ $target_dir/$script (String.concat " " (StringSet.elements all_elements)) (quote dib_vars) debug - fs_type in + fs_type + checksum_string in write_script (destdir // "run-part.sh") script_run_part; let script_run_and_log = "\ #!/bin/bash @@ -487,6 +497,8 @@ let main () = require_tool "qemu-img"; if List.mem "vhd" cmdline.formats then require_tool "vhd-util"; + if cmdline.checksum then + List.iter (fun x -> require_tool (tool_of_checksum x)) checksums; let image_basename = Filename.basename cmdline.image_name in let image_basename_d = image_basename ^ ".d" in @@ -600,6 +612,7 @@ let main () = ~install_type:cmdline.install_type ~debug ~extra_packages:cmdline.extra_packages ~fs_type:cmdline.fs_type + ~checksum:cmdline.checksum auxtmpdir all_elements; let delete_output_file = ref cmdline.delete_on_failure in @@ -617,6 +630,7 @@ let main () = ~root_label ~rootfs_uuid ~image_cache ~arch ~network:cmdline.network ~debug ~fs_type:cmdline.fs_type + ~checksum:cmdline.checksum tmpdir cmdline.basepath hookstmpdir (auxtmpdir // "fake-bin") all_elements cmdline.element_paths; @@ -939,6 +953,53 @@ let main () = ) formats_img_nonraw; ); + if not is_ramdisk_build && cmdline.checksum then ( + let file_flags = [ Unix.O_WRONLY; Unix.O_CREAT; Unix.O_TRUNC; Unix.O_CLOEXEC; ] in + List.iter ( + fun fmt -> + let fn = output_filename cmdline.image_name fmt in + message (f_"Generating checksums for %s") fn; + let pids = + List.map ( + fun csum -> + let csum_fn = fn ^ "." ^ csum in + let csum_tool = tool_of_checksum csum in + let outfd = Unix.openfile csum_fn file_flags 0o640 in + let args = [| csum_tool; fn; |] in + Common_utils.debug "%s" (stringify_args (Array.to_list args)); + let pid = Unix.create_process csum_tool args Unix.stdin + outfd Unix.stderr in + (pid, csum_tool, outfd) + ) checksums in + let pids = ref pids in + while !pids <> [] do + let pid, stat = Unix.waitpid [] 0 in + let matching_pair, new_pids = + List.partition ( + fun (p, tool, outfd) -> + pid = p + ) !pids in + if matching_pair <> [] then ( + let matching_pair = List.hd matching_pair in + let _, csum_tool, outfd = matching_pair in + Unix.close outfd; + pids := new_pids; + match stat with + | Unix.WEXITED 0 -> () + | Unix.WEXITED i -> + error (f_"external command '%s' exited with error %d") + csum_tool i + | Unix.WSIGNALED i -> + error (f_"external command '%s' killed by signal %d") + csum_tool i + | Unix.WSTOPPED i -> + error (f_"external command '%s' stopped by signal %d") + csum_tool i + ); + done; + ) formats_img; + ); + message (f_"Done") let () = run_main_and_handle_errors main diff --git a/dib/virt-dib.pod b/dib/virt-dib.pod index eca3768..09251c7 100644 --- a/dib/virt-dib.pod +++ b/dib/virt-dib.pod @@ -72,6 +72,11 @@ Right now this option does nothing more than setting the C<ARCH> environment variable for the elements, and it's up to them to produce an image for the requested architecture. +=item B<--checksum> + +Generate checksum files for the generated image. The supported +checksums are MD5, and SHA256. + =item B<--colors> =item B<--colours> @@ -320,6 +325,14 @@ A directory containing any files created by the elements, for example F<dib-manifests> directory (created by the C<manifests> element), ramdisks and kernels in ramdisk mode, and so on. +=item F<$NAME.ext.checksum> + +When I<--checksum> is specified, there will be files for each +supported checksum type; for example: F<$NAME.ext.md5>, +F<$NAME.ext.sha256>, etc. + +Not applicable in ramdisk mode, see L</RAMDISK BUILDING>. + =back =item B<--no-delete-on-failure> -- 2.9.3