readfile: use regular file access when not a gzip

Allows for different behavior w/ compressed files,
will also make it simpler to support other compression types,
see: T56162
This commit is contained in:
Campbell Barton
2019-02-24 12:34:41 +11:00
parent 519982fd3e
commit 8ed82e82e6
2 changed files with 104 additions and 8 deletions

View File

@@ -1118,6 +1118,30 @@ static int *read_file_thumbnail(FileData *fd)
/** \name File Data API
* \{ */
/* Regular file reading. */
static int fd_read_data_from_file(FileData *filedata, void *buffer, uint size)
{
int readsize = read(filedata->filedes, buffer, size);
if (readsize < 0) {
readsize = EOF;
}
else {
filedata->file_offset += readsize;
}
return (readsize);
}
static off_t fd_seek_data_from_file(FileData *filedata, off_t offset, int whence)
{
filedata->file_offset = lseek(filedata->filedes, offset, whence);
return filedata->file_offset;
}
/* GZip file reading. */
static int fd_read_gzip_from_file(FileData *filedata, void *buffer, uint size)
{
int readsize = gzread(filedata->gzfiledes, buffer, size);
@@ -1138,6 +1162,8 @@ static off_t fd_seek_gzip_from_file(FileData *filedata, off_t offset, int whence
return filedata->file_offset;
}
/* Memory reading. */
static int fd_read_from_memory(FileData *filedata, void *buffer, uint size)
{
/* don't read more bytes then there are available in the buffer */
@@ -1149,6 +1175,8 @@ static int fd_read_from_memory(FileData *filedata, void *buffer, uint size)
return (readsize);
}
/* MemFile reading. */
static int fd_read_from_memfile(FileData *filedata, void *buffer, uint size)
{
static size_t seek = SIZE_MAX; /* the current position */
@@ -1214,6 +1242,7 @@ static FileData *filedata_new(void)
{
FileData *fd = MEM_callocN(sizeof(FileData), "FileData");
fd->filedes = -1;
fd->gzfiledes = NULL;
fd->memsdna = DNA_sdna_current_get();
@@ -1250,18 +1279,72 @@ static FileData *blo_decode_and_check(FileData *fd, ReportList *reports)
static FileData *blo_filedata_from_file_open(const char *filepath, ReportList *reports)
{
FileDataReadFn *read_fn = NULL;
FileDataSeekFn *seek_fn = NULL; /* Optional. */
int file = -1;
gzFile gzfile = (gzFile)Z_NULL;
char header[7];
/* Regular file. */
errno = 0;
gzFile gzfile = BLI_gzopen(filepath, "rb");
if (gzfile == (gzFile)Z_NULL) {
file = BLI_open(filepath, O_BINARY | O_RDONLY, 0);
if (file == -1) {
BKE_reportf(reports, RPT_WARNING, "Unable to open '%s': %s",
filepath, errno ? strerror(errno) : TIP_("unknown error reading file"));
return NULL;
}
else if (read(file, header, sizeof(header)) != sizeof(header)) {
BKE_reportf(reports, RPT_WARNING, "Unable to read '%s': %s",
filepath, errno ? strerror(errno) : TIP_("insufficient content"));
close(file);
return NULL;
}
else {
lseek(file, 0, SEEK_SET);
}
/* Regular file. */
if (memcmp(header, "BLENDER", sizeof(header)) == 0) {
read_fn = fd_read_data_from_file;
seek_fn = fd_seek_data_from_file;
}
else {
close(file);
file = -1;
}
/* Gzip file. */
errno = 0;
if ((read_fn == NULL) &&
/* Check header magic. */
(header[0] == 0x1f && header[1] == 0x8b))
{
gzfile = BLI_gzopen(filepath, "rb");
if (gzfile == (gzFile)Z_NULL) {
BKE_reportf(reports, RPT_WARNING, "Unable to open '%s': %s",
filepath, errno ? strerror(errno) : TIP_("unknown error reading file"));
return NULL;
}
else {
read_fn = fd_read_gzip_from_file;
seek_fn = fd_seek_gzip_from_file;
}
}
if (read_fn == NULL) {
BKE_reportf(reports, RPT_WARNING, "Unrecognized file format '%s'", filepath);
return NULL;
}
FileData *fd = filedata_new();
fd->filedes = file;
fd->gzfiledes = gzfile;
fd->read = fd_read_gzip_from_file;
fd->seek = fd_seek_gzip_from_file;
fd->read = read_fn;
fd->seek = seek_fn;
return fd;
}
@@ -1387,6 +1470,10 @@ FileData *blo_filedata_from_memfile(MemFile *memfile, ReportList *reports)
void blo_filedata_free(FileData *fd)
{
if (fd) {
if (fd->filedes != -1) {
close(fd->filedes);
}
if (fd->gzfiledes != NULL) {
gzclose(fd->gzfiledes);
}

View File

@@ -48,6 +48,11 @@ enum eFileDataFlag {
FD_FLAGS_NOT_MY_LIBMAP = 1 << 5,
};
typedef int (FileDataReadFn)(struct FileData *filedata, void *buffer, unsigned int size);
typedef off_t (FileDataSeekFn)(struct FileData *filedata, off_t offset, int whence);
typedef struct FileData {
/** Linked list of BHeadN's. */
ListBase listbase;
@@ -55,8 +60,12 @@ typedef struct FileData {
bool is_eof;
int buffersize;
off_t file_offset;
int (*read)(struct FileData *filedata, void *buffer, unsigned int size);
off_t (*seek)(struct FileData *filedata, off_t offset, int whence);
FileDataReadFn *read;
FileDataSeekFn *seek;
/** Regular file reading. */
int filedes;
/** Variables needed for reading from memory / stream. */
const char *buffer;
@@ -65,12 +74,12 @@ typedef struct FileData {
/** Variables needed for reading from file. */
gzFile gzfiledes;
/** Gzip stream for memory decompression. */
z_stream strm;
/** Now only in use for library appending. */
char relabase[FILE_MAX];
/** Gzip stream for memory decompression. */
z_stream strm;
/** General reading variables. */
struct SDNA *filesdna;