2016-08-02 51 views

Antwort

2

Sie können die Datei, um die Dateigröße und die Anzahl der Festplattenblöcke zu erhalten, eine relativ kleine Anzahl von Festplattenblöcken nach dem Ende der Datei suchen, eine bekannte Anzahl von Blöcken schreiben und dann die Datei erneut formatieren. Vergleichen Sie die ursprüngliche Anzahl der Datenträgerblöcke mit der endgültigen Nummer. Nur ein paar Festplattenblöcke sollten nicht zu lange zum Schreiben benötigen, wenn das Dateisystem keine Sparse-Datei unterstützt.

Angesichts der ursprünglichen und endgültigen Anzahl der Datenträgerblöcke, dann versuchen Sie festzustellen, ob das Dateisystem Sparse-Dateien unterstützt. Ich sage "try", weil einige Dateisysteme dies erschweren können - z. B. ZFS mit aktivierter Komprimierung.

Etwas wie folgt aus:

#include <unistd.h> 
#include <stdlib.h> 
#include <sys/types.h> 
#include <sys/stat.h> 
#include <fcntl.h> 
#include <stdio.h> 
#include <string.h> 
#include <errno.h> 

int check(const char *filename) 
{ 
    struct stat sb; 
    long blocksize; 
    off_t filesize; 
    blkcnt_t origblocks; 
    char *buffer; 
    int fd; 

    fd = open(filename, O_CREAT | O_RDWR, 0644); 

    fstat(fd, &sb); 
    blocksize = sb.st_blksize; 
    filesize = sb.st_size; 
    origblocks = sb.st_blocks; 

    lseek(fd, 16UL * blocksize, SEEK_END); 

    buffer = malloc(blocksize); 
    memset(buffer, 0xAA, blocksize); 

    write(fd, buffer, blocksize); 
    fsync(fd); 

    free(buffer); 

    // kludge to give ZFS time to update metadata 
    for (;;) 
    { 
     stat(filename, &sb); 
     if (sb.st_blocks != origblocks) 
     { 
      break; 
     } 
    } 

    printf("file: %s\n filesystem: %s\n blocksize: %d\n size: %zd\n" 
     " blocks: %zd\n orig blocks: %zd\n disk space: %zd\n", 
     filename, sb.st_fstype, blocksize, sb.st_size, 
     (size_t) sb.st_blocks, (size_t) origblocks, 
     (size_t) (512UL * sb.st_blocks)); 

    // return file to original size 
    ftruncate(fd, filesize); 
    return(0); 
} 

int main(int argc, char **argv) 
{ 
    for (int ii = 1; ii < argc; ii++) 
    { 
     check(argv[ ii ]); 
    } 

    return(0); 
} 

(Fehlerüberprüfung aus Gründen der Übersichtlichkeit weggelassen)

ZFS mit Komprimierung aktiviert scheint nicht die Datei-Metadaten schnell zu aktualisieren, damit die Spinnen für die Änderungen zu warten erscheinen.

Wenn auf einem Solaris 11-Box mit den Dateien asdf (ZFS Dateisystem, Kompression aktiviert) laufen /tmp/asdf (tmpfs Dateisystem) und /var/tmp/asdf (ZFS, keine Kompression), erzeugt der Code die folgende Ausgabe:

file: asdf 
filesystem: zfs 
blocksize: 131072 
size: 2228224 
blocks: 10 
orig blocks: 1 
disk space: 5120 
file: /tmp/asdf 
filesystem: tmpfs 
blocksize: 4096 
size: 69632 
blocks: 136 
orig blocks: 0 
disk space: 69632 
file: /var/tmp/asdf 
filesystem: zfs 
blocksize: 131072 
size: 2228224 
blocks: 257 
orig blocks: 1 
disk space: 131584 

Von dieser Ausgabe sollte es offensichtlich sein, dass /tmp/asdf auf einem Dateisystem ist, das keine Sparse-Dateien unterstützt, und /var/tmp/asdf ist in einem Dateisystem, das solche Dateien unterstützt.

Und plain asdf ist auf etwas ganz anderes, wo Schreiben von 128 kB Daten alle 9 512-Byte-Festplattenblöcke hinzugefügt. Daraus können Sie schließen, dass im Dateisystem eine Art Kompression stattfindet. Ich vermute, es ist ziemlich sicher anzunehmen, dass jedes Dateisystem, das solche native Komprimierung unterstützt, auch dünn besetzte Dateien unterstützen wird.

Und der schnellste Weg, um zu bestimmen, ob ein Dateisystem Sparse-Dateien unterstützt, wenn ein Dateiname oder offene Dateideskriptor geben ist stat() auf den Dateinamen oder fstat() auf dem Dateideskriptor zu nennen, aus den struct stat das st_fstype Feld erhalten, und vergleichen Sie die Datei Dateisystemtyp in eine Gruppe von Strings von Dateisystemtypen, von denen bekannt ist, dass sie Sparse-Dateien unterstützen.