Itu bisa dilakukan, secara teori. Tapi itu sangat jelek dan pada dasarnya melibatkan membangun arsip kami dengan tangan.
Apa yang kita hadapi
The tar
Format beroperasi pada blok 512-byte . Ukuran ini diperbaiki, dan dimaksudkan agar sesuai dengan ukuran sektor disk tradisional. Saat menyimpan file dalam arsip, blok 512-byte pertama adalah header yang berisi metadata file (nama, ukuran, jenis, dll.), Dan blok berikut berisi konten file. Jadi data yang diarsipkan akan disejajarkan dengan 512 byte.
Ukuran blok ("--sectorsize") dari btrfs biasanya 4.096 byte . Secara teori kita dapat memilih ini, tetapi dalam praktiknya sepertinya harus sesuai dengan ukuran halaman CPU kita. Jadi kita tidak bisa mengecilkan blok btrf.
The tar
Program memiliki konsep yang lebih besar ukuran "record", yang didefinisikan sebagai kelipatan dari ukuran blok, yang hampir terlihat seperti itu akan berguna. Ternyata ini dimaksudkan untuk menentukan ukuran sektor dari tape drive yang diberikan, sehingga tar
akan menghindari penulisan sebagian rekaman tape. Namun, data masih dibangun dan dikemas dalam unit 512 byte, jadi kami tidak dapat menggunakan ini untuk menumbuhkan tar
blok seperti yang Anda harapkan.
Sebuah titik terakhir dari data yang tahu adalah bahwa tar
's akhir-arsip marker adalah dua berturut-turut semua-nol blok, kecuali bila mereka blok file data di dalam. Jadi segala macam blok bantalan naif mungkin tidak akan diterima.
Peretasan
Apa yang bisa kita lakukan adalah memasukkan file padding. Di awal arsip kami, sebelum kami menambahkan file yang ingin kami deduplicate (sebut saja dup
), kami menambahkan file pad
, berukuran sehingga
pad's header + pad's data + dup's header = 4096 bytes.
Dengan begitu, dup
data dimulai pada batas blok dan dapat dideduplikasi.
Kemudian, untuk setiap file berikutnya, kami juga harus melacak ukuran file sebelumnya untuk menghitung padding yang benar. Kami juga harus memperkirakan apakah diperlukan ekstensi ekstensi: misalnya, header tar dasar hanya memiliki ruang untuk 100 byte jalur file, sehingga jalur yang lebih panjang disandikan menggunakan apa yang secara struktural file dengan nama khusus yang datanya adalah jalan penuh. Secara umum ada banyak potensi kompleksitas dalam memprediksi ukuran header - tar
format file memiliki banyak kesalahan dari beberapa implementasi historis.
Sebuah garis kecil perak adalah bahwa semua file padding dapat berbagi nama yang sama, jadi ketika kita menghapusnya kita hanya akan berakhir dengan satu file tambahan berukuran kurang dari 4096 byte.
Cara terbersih untuk membuat arsip seperti ini adalah dengan memodifikasi tar
program GNU . Tetapi jika Anda ingin cepat dan kotor dengan mengorbankan CPU dan waktu I / O, Anda dapat, untuk setiap file, melakukan sesuatu seperti:
#!/bin/bash
# Proof of concept and probably buggy.
# If I ever find this script in a production environment,
# I don't know whether I'll laugh or cry.
my_file="$2"
my_archive="$1"
file_size="$(wc -c <"$my_file")"
arch_size="$(tar cb 1 "$my_file" | wc -c)" # "b 1": Remember that record size I mentioned? Set it to equal the block size so we can measure usefully.
end_marker_size=1024 # End-of-archive marker: 2 blocks' worth of 0 bytes
hdr_size="$(( (arch_size - file_size - end_marker_size) % 4096 ))"
pad_size="$(( (4096 - 512 - hdr_size) % 4096 ))"
(( pad_size < 512 )) && pad_size="$(( pad_size + 4096 ))"
# Assume the pre-existing archive is already a multiple of 4096 bytes long
# (not including the end-of-archive marker), and add extra padding to the end
# so that it stays that way.
file_blocks_size="$(( ((file_size+511) / 512) * 512 ))"
end_pad_size="$(( 4096 - 512 - (file_blocks_size % 4096) ))"
(( end_pad_size < 512 )) && end_pad_size="$(( end_pad_size + 4096 ))"
head -c $pad_size /dev/zero > _PADDING_
tar rf "$my_archive" _PADDING_ "$my_file"
head -c $end_pad_size /dev/zero > _PADDING_
tar rf "$my_archive" _PADDING_