Return back checking file for sparseness. Use lseek(SEEK_HOLE) if supported by the system, otherwise fallback to block check. This allows to workaround bugs with SMB client and not introduce new bugs for filesystems with compression and deduplication.

This has theoretical bug if our collection spans different
filesystems and some filesystems support holes, and some not.
If this ever encountered we should use pathconf(2) and cache
its result for directories.
This commit is contained in:
Gleb Smirnoff
2018-01-12 22:40:15 -08:00
committed by Justin Maggard
parent debb502ff3
commit 3e8da9bb1a
2 changed files with 28 additions and 7 deletions

View File

@ -19,6 +19,7 @@
#include <stdio.h>
#include <string.h>
#include <stdbool.h>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
@ -471,6 +472,30 @@ monitor_insert_file(const char *name, const char *path)
return depth;
}
static bool
check_notsparse(const char *path)
#if HAVE_DECL_SEEK_HOLE
{
int fd;
bool rv;
if ((fd = open(path, O_RDONLY)) == -1)
return (false);
if (lseek(fd, 0, SEEK_HOLE) == lseek(fd, 0, SEEK_END))
rv = true;
else
rv = false;
close(fd);
return (rv);
}
#else
{
struct stat st;
return (stat(path, &st) == 0 && (st.st_blocks << 9 >= st.st_size));
}
#endif
int
monitor_insert_directory(int fd, char *name, const char * path)
{
@ -480,7 +505,6 @@ monitor_insert_directory(int fd, char *name, const char * path)
char path_buf[PATH_MAX];
enum file_types type = TYPE_UNKNOWN;
media_types dir_types;
struct stat st;
if( access(path, R_OK|X_OK) != 0 )
{
@ -538,12 +562,8 @@ monitor_insert_directory(int fd, char *name, const char * path)
{
monitor_insert_directory(fd, esc_name, path_buf);
}
else if( type == TYPE_FILE )
{
if( (stat(path_buf, &st) == 0) )
{
monitor_insert_file(esc_name, path_buf);
}
else if( type == TYPE_FILE && check_notsparse(path_buf)) {
monitor_insert_file(esc_name, path_buf);
}
free(esc_name);
}