Jika kecepatan penting dan kompresi tidak diperlukan, Anda dapat mengaitkan pembungkus syscall yang digunakan dengan tarmenggunakan LD_PRELOAD, untuk mengubah taruntuk menghitungnya bagi kami. Dengan mengimplementasikan kembali beberapa fungsi ini untuk memenuhi kebutuhan kita (menghitung ukuran data tar potensial), kita dapat menghilangkan banyak readdan writeyang dilakukan dalam operasi normal tar. Ini membuat tarlebih cepat karena tidak perlu konteks bolak-balik ke kernel di mana saja dekat sebanyak dan hanya statfile input / folder yang diminta harus dibaca dari disk daripada data file yang sebenarnya.
Kode di bawah meliputi implementasi dari close, read, dan writefungsi POSIX. Makro OUT_FDmengontrol deskriptor file mana yang kami harapkan taruntuk digunakan sebagai file output. Saat ini diatur ke stdout.
readdiubah menjadi hanya mengembalikan nilai keberhasilan countbyte 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.
writediubah untuk menjumlahkan countbyte input ke dalam variabel global totaldan mengembalikan nilai keberhasilan countbyte hanya jika file deskriptor cocok OUT_FD, jika tidak maka akan memanggil wrapper asli yang diperoleh melalui dlsymuntuk melakukan syscall dengan nama yang sama.
closemasih melakukan preforms semua fungsionalitas aslinya, tetapi jika deskriptor file cocok dengan OUT_FD, ia tahu bahwa tarsudah selesai mencoba untuk menulis file tar, jadi totalangkanya 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_PRELOADsolusi.
$ 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_PRELOADteknik" 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/
--totalsopsi. Either way jika Anda mengisi disk Anda hanya dapat menghapus arsip, imho. Untuk memeriksa semua opsi yang tersedia, Anda dapat melewatitar --help.