Skip to content

Commit e8269c4

Browse files
committed
Initial commit
This is wrong, but for sake of history it may be interesting to keep.
0 parents  commit e8269c4

File tree

4 files changed

+119
-0
lines changed

4 files changed

+119
-0
lines changed

dune-project

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
(lang dune 3.7)
2+
3+
(name gptar)
4+
5+
(generate_opam_files true)
6+
7+
(source
8+
(github reynir/gptar))
9+
10+
(authors "Reynir Björnsson <reynir@reynir.dk>")
11+
12+
(maintainers "Maintainer Name")
13+
14+
(license LICENSE)
15+
16+
(documentation https://url/to/documentation)
17+
18+
(package
19+
(name gptar)
20+
(synopsis "GPT headers that are also valid tar headers")
21+
(description "\
22+
A longer description")
23+
(depends ocaml dune gpt tar checkseum)
24+
(tags
25+
(gpt tar)))
26+
27+
; See the complete stanza docs at https://dune.readthedocs.io/en/stable/dune-files.html#dune-project

gptar.opam

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
# This file is generated by dune, edit dune-project instead
2+
opam-version: "2.0"
3+
synopsis: "GPT headers that are also valid tar headers"
4+
description: "A longer description"
5+
maintainer: ["Maintainer Name"]
6+
authors: ["Reynir Björnsson <reynir@reynir.dk>"]
7+
license: "LICENSE"
8+
tags: ["gpt" "tar"]
9+
homepage: "https://github.com/reynir/gptar"
10+
doc: "https://url/to/documentation"
11+
bug-reports: "https://github.com/reynir/gptar/issues"
12+
depends: [
13+
"ocaml"
14+
"dune" {>= "3.7"}
15+
"gpt"
16+
"tar"
17+
"checkseum"
18+
"odoc" {with-doc}
19+
]
20+
build: [
21+
["dune" "subst"] {dev}
22+
[
23+
"dune"
24+
"build"
25+
"-p"
26+
name
27+
"-j"
28+
jobs
29+
"@install"
30+
"@runtest" {with-test}
31+
"@doc" {with-doc}
32+
]
33+
]
34+
dev-repo: "git+https://github.com/reynir/gptar.git"

lib/Gptar.ml

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
(* https://sar.informatik.hu-berlin.de/research/publications/SAR-PR-2006-05/SAR-PR-2006-05_.pdf *)
2+
let magic_sequence = 0x2144df1cl
3+
let gpt_sizeof = 92 (* Gpt.sizeof *)
4+
let gpt_header_crc32_offset = 16
5+
let tar_link_indicator_offset = 156
6+
7+
let marshal_header ~sector_size buf t =
8+
if Cstruct.length buf < sector_size ||
9+
Cstruct.length buf < gpt_sizeof ||
10+
sector_size < Tar.Header.length + 4 then
11+
invalid_arg "Gptar.marshal";
12+
(* Replace the header crc32 with the magic sequence. This is (most likely)
13+
not the correct crc32 checksum for that header, but we will fix that
14+
later. *)
15+
let t = { t with Gpt.header_crc32 = magic_sequence } in
16+
let file_name =
17+
(* sector_size in [Gpt.marshal_header] is only used to figure out how much
18+
of the reserved space to zero out. We use [buf] even if Tar will
19+
overwrite the first 512 bytes. The 'reserved' part of the GPT header
20+
will be zeroed out. *)
21+
Gpt.marshal_header ~sector_size buf t;
22+
Cstruct.to_string buf ~len:gpt_sizeof
23+
in
24+
(* The "file" is the first LBA minus the tar header size plus the size of the
25+
partition table rounded up to [sector_size]. *)
26+
let file_size =
27+
let partition_table_size =
28+
Int32.to_int t.num_partition_entries * Int32.to_int t.partition_size
29+
in
30+
sector_size - Tar.Header.length +
31+
((partition_table_size + pred sector_size) / sector_size) * sector_size
32+
in
33+
let header =
34+
Tar.Header.make file_name (Int64.of_int file_size)
35+
in
36+
(* Now we marshal the tar header which will start with the GPT header (as the
37+
tar file name). The remainder of the tar fields are at least eight bytes
38+
into the reserved space of the GPT header (which should be all zero, but
39+
who's checking?). Tar itself has a checksum of its own header which
40+
includes the non-reserved part of our GPT header. *)
41+
Tar.Header.marshal buf header;
42+
(* Let's fix up the link indicator so tar utilities like GNU tar will skip
43+
the unknown type. The 'G' link indicator seems unused. *)
44+
Cstruct.set_char buf tar_link_indicator_offset 'G';
45+
(* Next, we compute the crc32 of the sector except for the last 4 bytes *)
46+
let crc32 =
47+
Checkseum.Crc32.digest_bigstring
48+
buf.buffer buf.off (buf.len - 4)
49+
Checkseum.Crc32.default
50+
in
51+
(* Since the tar header's checksum covers the GPT header's checksum we can't
52+
modify that. However, setting [crc32] at the end of the sector the crc32
53+
checksum of the buffer will be [magic_sequence]! This will ensure the the
54+
GPT header's checksum also works. *)
55+
Cstruct.LE.set_uint32 buf (sector_size - 4) (Optint.to_int32 crc32)

lib/dune

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
(library
2+
(name gptar)
3+
(libraries gpt tar checkseum))

0 commit comments

Comments
 (0)