Gibt es einen Dateideskriptor oder einen Dateinamen, woher weiß ich, ob ich an einen beliebigen Ort schreiben kann, ohne auf den dazwischen liegenden Teil zu warten?Wie kann ich testen, ob die Sparse-Datei unterstützt wird?
Antwort
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.