Jika kecepatan penting dan kompresi tidak diperlukan, Anda dapat mengaitkan pembungkus syscall yang digunakan dengan tar
menggunakan LD_PRELOAD
, untuk mengubah tar
untuk menghitungnya bagi kami. Dengan mengimplementasikan kembali beberapa fungsi ini untuk memenuhi kebutuhan kita (menghitung ukuran data tar potensial), kita dapat menghilangkan banyak read
dan write
yang dilakukan dalam operasi normal tar
. Ini membuat tar
lebih cepat karena tidak perlu konteks bolak-balik ke kernel di mana saja dekat sebanyak dan hanya stat
file input / folder yang diminta harus dibaca dari disk daripada data file yang sebenarnya.
Kode di bawah meliputi implementasi dari close
, read
, dan write
fungsi POSIX. Makro OUT_FD
mengontrol deskriptor file mana yang kami harapkan tar
untuk digunakan sebagai file output. Saat ini diatur ke stdout.
read
diubah menjadi hanya mengembalikan nilai keberhasilan count
byte alih-alih mengisi buf dengan data, mengingat bahwa data aktual tidak dibaca buf tidak akan berisi data yang valid untuk diteruskan ke kompresi, dan dengan demikian jika kompresi digunakan kami akan menghitung yang salah ukuran.
write
diubah untuk menjumlahkan count
byte input ke dalam variabel global total
dan mengembalikan nilai keberhasilan count
byte hanya jika file deskriptor cocok OUT_FD
, jika tidak maka akan memanggil wrapper asli yang diperoleh melalui dlsym
untuk melakukan syscall dengan nama yang sama.
close
masih melakukan preforms semua fungsionalitas aslinya, tetapi jika deskriptor file cocok dengan OUT_FD, ia tahu bahwa tar
sudah selesai mencoba untuk menulis file tar, jadi total
angkanya adalah final dan mencetaknya ke stdout.
#define _GNU_SOURCE
#include <unistd.h>
#include <stdio.h>
#include <stdint.h>
#include <inttypes.h>
#include <stdlib.h>
#include <errno.h>
#include <dlfcn.h>
#include <string.h>
#define OUT_FD 1
uint64_t total = 0;
ssize_t (*original_write)(int, const void *, size_t) = NULL;
int (*original_close)(int) = NULL;
void print_total(void)
{
printf("%" PRIu64 "\n", total);
}
int close(int fd)
{
if(! original_close)
{
original_close = dlsym(RTLD_NEXT, "close");
}
if(fd == OUT_FD)
{
print_total();
}
return original_close(fd);
}
ssize_t read(int fd, void *buf, size_t count)
{
return count;
}
ssize_t write(int fd, const void *buf, size_t count)
{
if(!original_write)
{
original_write = dlsym(RTLD_NEXT, "write");
}
if(fd == OUT_FD)
{
total += count;
return count;
}
return original_write(fd, buf, count);
}
Benchmark membandingkan solusi di mana akses disk baca dan semua syscalls operasi tar normal dilakukan terhadap LD_PRELOAD
solusi.
$ time tar -c /media/storage/music/Macintosh\ Plus-\ Floral\ Shoppe\ \(2011\)\ \[Flac\]/ | wc -c
332308480
real 0m0.457s
user 0m0.064s
sys 0m0.772s
tarsize$ time ./tarsize.sh -c /media/storage/music/Macintosh\ Plus-\ Floral\ Shoppe\ \(2011\)\ \[Flac\]/
332308480
real 0m0.016s
user 0m0.004s
sys 0m0.008s
Kode di atas, skrip build dasar untuk membangun di atas sebagai pustaka bersama, dan skrip dengan " LD_PRELOAD
teknik" menggunakannya disediakan dalam repo:
https://github.com/G4Vi/tarsize
Beberapa info tentang cara menggunakan LD_PRELOAD: https://rafalcieslak.wordpress.com/2013/04/02/dynamic-linker-tricks-using-ld_preload-to-cheat-inject-features-and-investigate-programs/
--totals
opsi. Either way jika Anda mengisi disk Anda hanya dapat menghapus arsip, imho. Untuk memeriksa semua opsi yang tersedia, Anda dapat melewatitar --help
.