তাহলে গতি গুরুত্বপূর্ণ এবং কম্প্রেশন প্রয়োজন নেই, আপনি প্রাপ্ত syscall দ্বারা ব্যবহৃত চাদরে হুক করতে পারেন tarব্যবহার LD_PRELOAD, পরিবর্তন করতে tarআমাদের জন্য এটি গণনা করা হবে। আমাদের প্রয়োজন অনুসারে এই ফাংশনগুলির কয়েকটি সংশোধন করে (সম্ভাব্য আউটপুট টের ডেটার আকার গণনা করে), আমরা প্রচুর পরিমাণে নির্মূল করতে সক্ষম readএবং writeএটি সাধারণ অপারেশনে সঞ্চালিত হয় tar। এটি tarতাত্পর্যপূর্ণ করে তোলে কারণ এর নিকটস্থ কোথাও কার্নেলের অভ্যন্তরে পিছনে স্যুইচ করার দরকার নেই এবং কেবলমাত্র statঅনুরোধ করা ইনপুট ফাইল / ফোল্ডার (গুলি) প্রকৃত ফাইল ডেটার পরিবর্তে ডিস্ক থেকে পড়তে হবে।
নিচের কোড এর বাস্তবায়নের অন্তর্ভুক্ত close, readএবং writePOSIX ফাংশন। আউটপুট ফাইল হিসাবে OUT_FDকোন ফাইল বর্ণনাকারী আমরা প্রত্যাশা করি tarতা ম্যাক্রো নিয়ন্ত্রণ করে । বর্তমানে এটি stdout সেট করা হয়।
readcountতথ্যের সাথে বুফ পূরণের পরিবর্তে কেবলমাত্র বাইটের সাফল্যের মান ফিরিয়ে আনার জন্য পরিবর্তন করা হয়েছিল , প্রকৃত ডেটা না পড়লে বুফেতে সংক্ষেপণে যাওয়ার জন্য বৈধ ডেটা থাকবে না এবং এইভাবে যদি সংক্ষেপণ ব্যবহার করা হত তবে আমরা একটি ভুল গণনা করব আকার।
writecountবৈশ্বিক ভেরিয়েবলের ইনপুট বাইটগুলি যোগ করতে totalএবং ফাইলের বর্ণনাকারীর সাথে মেলে কেবলমাত্রcount বাইটের সাফল্যের মান ফিরিয়ে আনার জন্য পরিবর্তন করা হয়েছিল , অন্যথায় এটি একই নামের সিস্কাল সম্পাদন করার মাধ্যমে অর্জিত আসল মোড়কে কল করে ।OUT_FDdlsym
closeতারপরেও তার মূল কার্যকারিতাটি সমস্তই প্রিফর্ম করে তবে ফাইল বর্ণনাকারী যদি OUT_FD এর সাথে মিলে যায় তবে এটি জানে যে tarএকটি টার ফাইল লেখার চেষ্টা করা হয়েছে, সুতরাং totalসংখ্যাটি চূড়ান্ত এবং এটি স্টাডআউটকে প্রিন্ট করে।
#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);
}
বেঞ্চমার্ক এমন একটি সমাধানের সাথে তুলনা করে যেখানে রিড ডিস্ক অ্যাক্সেস এবং সাধারণ টার অপারেশনের সমস্ত সিস্টোল LD_PRELOADসমাধানের বিপরীতে সঞ্চালিত হয় ।
$ 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
উপরের কোডটি, ভাগ করে নেওয়া লাইব্রেরি হিসাবে উপরেরটি তৈরির জন্য একটি বেসিক বিল্ড স্ক্রিপ্ট এবং LD_PRELOADএটি ব্যবহার করে " কৌশল" সহ একটি স্ক্রিপ্ট রেপোতে সরবরাহ করা হয়েছে:
https://github.com/G4Vi/tarsize
LD_PRELOAD ব্যবহার সম্পর্কে কিছু তথ্য: https ://rafalالنlak.wordpress.com/2013/04/02/dynamic-linker-tricks-used-ld_preload-to-cheat-inject-features-and-inquate-program/
--totalsবিকল্পটি দিয়ে খেলতে পারবেন । যে কোনও উপায়ে যদি আপনি ডিস্কটি পূরণ করেন তবে আপনি কেবল সংরক্ষণাগারটি মুছতে পারেন, imho। উপলব্ধ সমস্ত বিকল্প যাচাই করার জন্য আপনি যেতে পারেনtar --help।