Si la vitesse est importante et que la compression n'est pas nécessaire, vous pouvez accrocher les wrappers syscall utilisés à l' tar
aide de LD_PRELOAD
, pour les modifier tar
et les calculer pour nous. En réimplémentant quelques - unes de ces fonctions pour répondre à nos besoins (calcul de la taille des données de goudron de la production potentielle), nous sommes en mesure d' éliminer beaucoup de read
et write
qui est effectué en fonctionnement normal tar
. Cela rend tar
beaucoup plus rapide car il n'a pas besoin de basculer le contexte d'avant en arrière dans le noyau à peu près autant et seul le stat
fichier / dossier d'entrée requis doit être lu à partir du disque au lieu des données de fichier réelles.
Le code ci - dessous comprend les mises en œuvre des close
, read
et des write
fonctions POSIX. La macro OUT_FD
contrôle le descripteur de fichier que nous prévoyons tar
d'utiliser comme fichier de sortie. Actuellement, il est défini sur stdout.
read
a été modifié pour renvoyer simplement la valeur de succès des count
octets au lieu de remplir buf avec les données, étant donné que les données réelles n'ont pas été lues buf ne contiendrait pas de données valides pour passer à la compression, et donc si la compression était utilisée, nous calculerions une erreur Taille.
write
a été modifié pour additionner les count
octets d' entrée dans la variable globale total
et renvoyer la valeur de succès des count
octets uniquement si le descripteur de fichier correspond OUT_FD
, sinon il appelle l'encapsuleur d'origine acquis via dlsym
pour effectuer l'appel système du même nom.
close
préforme toujours toutes ses fonctionnalités d'origine, mais si le descripteur de fichier correspond à OUT_FD, il sait que cela tar
est fait en essayant d'écrire un fichier tar, donc le total
nombre est final et il l'imprime sur 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 comparant une solution où l'accès au disque de lecture et tous les appels système de l'opération tar normale sont effectués par rapport à la LD_PRELOAD
solution.
$ 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
Le code ci-dessus, un script de construction de base pour construire ce qui précède en tant que bibliothèque partagée et un script avec la " LD_PRELOAD
technique" l'utilisant sont fournis dans le référentiel:
https://github.com/G4Vi/tarsize
Quelques informations sur l'utilisation de LD_PRELOAD: https://rafalcieslak.wordpress.com/2013/04/02/dynamic-linker-tricks-using-ld_preload-to-cheat-inject-features-and-investigate-programs/
--totals
option. Quoi qu'il en soit, si vous remplissez le disque, vous pouvez simplement supprimer l'archive, à mon humble avis. Pour vérifier toutes les options disponibles, vous pouvez passer partar --help
.