Changeset View
Changeset View
Standalone View
Standalone View
source/blender/blenloader/intern/readfile.c
- This file is larger than 256 KB, so syntax highlighting is disabled by default.
| Show First 20 Lines • Show All 803 Lines • ▼ Show 20 Lines | if (bhead8->code != ENDB) { | ||||
| bhead8->SDNAnr = bhead4->SDNAnr; | bhead8->SDNAnr = bhead4->SDNAnr; | ||||
| bhead8->nr = bhead4->nr; | bhead8->nr = bhead4->nr; | ||||
| } | } | ||||
| } | } | ||||
| static BHeadN *get_bhead(FileData *fd) | static BHeadN *get_bhead(FileData *fd) | ||||
| { | { | ||||
| BHeadN *new_bhead = NULL; | BHeadN *new_bhead = NULL; | ||||
| int readsize; | ssize_t readsize; | ||||
| if (fd) { | if (fd) { | ||||
| if (!fd->is_eof) { | if (!fd->is_eof) { | ||||
| /* initializing to zero isn't strictly needed but shuts valgrind up | /* initializing to zero isn't strictly needed but shuts valgrind up | ||||
| * since uninitialized memory gets compared */ | * since uninitialized memory gets compared */ | ||||
| BHead8 bhead8 = {0}; | BHead8 bhead8 = {0}; | ||||
| BHead4 bhead4 = {0}; | BHead4 bhead4 = {0}; | ||||
| BHead bhead = {0}; | BHead bhead = {0}; | ||||
| ▲ Show 20 Lines • Show All 82 Lines • ▼ Show 20 Lines | #ifdef USE_BHEAD_READ_ON_DEMAND | ||||
| BLI_assert(fd->file_offset == seek_new); | BLI_assert(fd->file_offset == seek_new); | ||||
| } | } | ||||
| else { | else { | ||||
| fd->is_eof = true; | fd->is_eof = true; | ||||
| } | } | ||||
| } | } | ||||
| #endif | #endif | ||||
| else { | else { | ||||
| new_bhead = MEM_mallocN(sizeof(BHeadN) + bhead.len, "new_bhead"); | new_bhead = MEM_mallocN(sizeof(BHeadN) + (size_t)bhead.len, "new_bhead"); | ||||
| if (new_bhead) { | if (new_bhead) { | ||||
| new_bhead->next = new_bhead->prev = NULL; | new_bhead->next = new_bhead->prev = NULL; | ||||
| #ifdef USE_BHEAD_READ_ON_DEMAND | #ifdef USE_BHEAD_READ_ON_DEMAND | ||||
| new_bhead->file_offset = 0; /* don't seek. */ | new_bhead->file_offset = 0; /* don't seek. */ | ||||
| new_bhead->has_data = true; | new_bhead->has_data = true; | ||||
| #endif | #endif | ||||
| new_bhead->is_memchunk_identical = false; | new_bhead->is_memchunk_identical = false; | ||||
| new_bhead->bhead = bhead; | new_bhead->bhead = bhead; | ||||
| readsize = fd->read(fd, new_bhead + 1, bhead.len, &new_bhead->is_memchunk_identical); | readsize = fd->read( | ||||
| fd, new_bhead + 1, (size_t)bhead.len, &new_bhead->is_memchunk_identical); | |||||
| if (readsize != bhead.len) { | if (readsize != (ssize_t)bhead.len) { | ||||
| fd->is_eof = true; | fd->is_eof = true; | ||||
| MEM_freeN(new_bhead); | MEM_freeN(new_bhead); | ||||
| new_bhead = NULL; | new_bhead = NULL; | ||||
| } | } | ||||
| } | } | ||||
| else { | else { | ||||
| fd->is_eof = true; | fd->is_eof = true; | ||||
| } | } | ||||
| ▲ Show 20 Lines • Show All 71 Lines • ▼ Show 20 Lines | static bool blo_bhead_read_data(FileData *fd, BHead *thisblock, void *buf) | ||||
| bool success = true; | bool success = true; | ||||
| BHeadN *new_bhead = BHEADN_FROM_BHEAD(thisblock); | BHeadN *new_bhead = BHEADN_FROM_BHEAD(thisblock); | ||||
| BLI_assert(new_bhead->has_data == false && new_bhead->file_offset != 0); | BLI_assert(new_bhead->has_data == false && new_bhead->file_offset != 0); | ||||
| off64_t offset_backup = fd->file_offset; | off64_t offset_backup = fd->file_offset; | ||||
| if (UNLIKELY(fd->seek(fd, new_bhead->file_offset, SEEK_SET) == -1)) { | if (UNLIKELY(fd->seek(fd, new_bhead->file_offset, SEEK_SET) == -1)) { | ||||
| success = false; | success = false; | ||||
| } | } | ||||
| else { | else { | ||||
| if (fd->read(fd, buf, new_bhead->bhead.len, &new_bhead->is_memchunk_identical) != | if (fd->read(fd, buf, (size_t)new_bhead->bhead.len, &new_bhead->is_memchunk_identical) != | ||||
| new_bhead->bhead.len) { | (ssize_t)new_bhead->bhead.len) { | ||||
| success = false; | success = false; | ||||
| } | } | ||||
| } | } | ||||
| if (fd->seek(fd, offset_backup, SEEK_SET) == -1) { | if (fd->seek(fd, offset_backup, SEEK_SET) == -1) { | ||||
| success = false; | success = false; | ||||
| } | } | ||||
| return success; | return success; | ||||
| } | } | ||||
| Show All 18 Lines | |||||
| const char *blo_bhead_id_name(const FileData *fd, const BHead *bhead) | const char *blo_bhead_id_name(const FileData *fd, const BHead *bhead) | ||||
| { | { | ||||
| return (const char *)POINTER_OFFSET(bhead, sizeof(*bhead) + fd->id_name_offs); | return (const char *)POINTER_OFFSET(bhead, sizeof(*bhead) + fd->id_name_offs); | ||||
| } | } | ||||
| static void decode_blender_header(FileData *fd) | static void decode_blender_header(FileData *fd) | ||||
| { | { | ||||
| char header[SIZEOFBLENDERHEADER], num[4]; | char header[SIZEOFBLENDERHEADER], num[4]; | ||||
| int readsize; | ssize_t readsize; | ||||
| /* read in the header data */ | /* read in the header data */ | ||||
| readsize = fd->read(fd, header, sizeof(header), NULL); | readsize = fd->read(fd, header, sizeof(header), NULL); | ||||
| if (readsize == sizeof(header) && STREQLEN(header, "BLENDER", 7) && ELEM(header[7], '_', '-') && | if (readsize == sizeof(header) && STREQLEN(header, "BLENDER", 7) && ELEM(header[7], '_', '-') && | ||||
| ELEM(header[8], 'v', 'V') && | ELEM(header[8], 'v', 'V') && | ||||
| (isdigit(header[9]) && isdigit(header[10]) && isdigit(header[11]))) { | (isdigit(header[9]) && isdigit(header[10]) && isdigit(header[11]))) { | ||||
| fd->flags |= FD_FLAGS_FILE_OK; | fd->flags |= FD_FLAGS_FILE_OK; | ||||
| ▲ Show 20 Lines • Show All 117 Lines • ▼ Show 20 Lines | |||||
| /** \} */ | /** \} */ | ||||
| /* -------------------------------------------------------------------- */ | /* -------------------------------------------------------------------- */ | ||||
| /** \name File Data API | /** \name File Data API | ||||
| * \{ */ | * \{ */ | ||||
| /* Regular file reading. */ | /* Regular file reading. */ | ||||
| static int fd_read_data_from_file(FileData *filedata, | static ssize_t fd_read_data_from_file(FileData *filedata, | ||||
| void *buffer, | void *buffer, | ||||
| uint size, | size_t size, | ||||
| bool *UNUSED(r_is_memchunck_identical)) | bool *UNUSED(r_is_memchunck_identical)) | ||||
| { | { | ||||
| int readsize = read(filedata->filedes, buffer, size); | ssize_t readsize = read(filedata->filedes, buffer, size); | ||||
| if (readsize < 0) { | if (readsize < 0) { | ||||
| readsize = EOF; | readsize = EOF; | ||||
| } | } | ||||
| else { | else { | ||||
| filedata->file_offset += readsize; | filedata->file_offset += readsize; | ||||
| } | } | ||||
| return readsize; | return readsize; | ||||
| } | } | ||||
| static off64_t fd_seek_data_from_file(FileData *filedata, off64_t offset, int whence) | static off64_t fd_seek_data_from_file(FileData *filedata, off64_t offset, int whence) | ||||
| { | { | ||||
| filedata->file_offset = BLI_lseek(filedata->filedes, offset, whence); | filedata->file_offset = BLI_lseek(filedata->filedes, offset, whence); | ||||
| return filedata->file_offset; | return filedata->file_offset; | ||||
| } | } | ||||
| /* GZip file reading. */ | /* GZip file reading. */ | ||||
campbellbarton: Shouldn't an assert be added here for `size > UINT_MAX`? | |||||
Done Inline ActionsIndeed. mont29: Indeed. | |||||
| static int fd_read_gzip_from_file(FileData *filedata, | static ssize_t fd_read_gzip_from_file(FileData *filedata, | ||||
| void *buffer, | void *buffer, | ||||
| uint size, | size_t size, | ||||
| bool *UNUSED(r_is_memchunck_identical)) | bool *UNUSED(r_is_memchunck_identical)) | ||||
| { | { | ||||
| int readsize = gzread(filedata->gzfiledes, buffer, size); | BLI_assert(size <= INT_MAX); | ||||
| ssize_t readsize = gzread(filedata->gzfiledes, buffer, (uint)size); | |||||
| if (readsize < 0) { | if (readsize < 0) { | ||||
| readsize = EOF; | readsize = EOF; | ||||
| } | } | ||||
| else { | else { | ||||
| filedata->file_offset += readsize; | filedata->file_offset += readsize; | ||||
| } | } | ||||
| return readsize; | return readsize; | ||||
| } | } | ||||
| /* Memory reading. */ | /* Memory reading. */ | ||||
| static int fd_read_from_memory(FileData *filedata, | static ssize_t fd_read_from_memory(FileData *filedata, | ||||
| void *buffer, | void *buffer, | ||||
| uint size, | size_t size, | ||||
| bool *UNUSED(r_is_memchunck_identical)) | bool *UNUSED(r_is_memchunck_identical)) | ||||
| { | { | ||||
| /* don't read more bytes then there are available in the buffer */ | /* don't read more bytes then there are available in the buffer */ | ||||
| int readsize = (int)MIN2(size, (uint)(filedata->buffersize - filedata->file_offset)); | ssize_t readsize = (ssize_t)MIN2(size, filedata->buffersize - (size_t)filedata->file_offset); | ||||
| memcpy(buffer, filedata->buffer + filedata->file_offset, readsize); | memcpy(buffer, filedata->buffer + filedata->file_offset, (size_t)readsize); | ||||
| filedata->file_offset += readsize; | filedata->file_offset += readsize; | ||||
| return readsize; | return readsize; | ||||
| } | } | ||||
| /* MemFile reading. */ | /* MemFile reading. */ | ||||
| static int fd_read_from_memfile(FileData *filedata, | static ssize_t fd_read_from_memfile(FileData *filedata, | ||||
| void *buffer, | void *buffer, | ||||
| uint size, | size_t size, | ||||
| bool *r_is_memchunck_identical) | bool *r_is_memchunck_identical) | ||||
| { | { | ||||
| static size_t seek = SIZE_MAX; /* the current position */ | static size_t seek = SIZE_MAX; /* the current position */ | ||||
| static size_t offset = 0; /* size of previous chunks */ | static size_t offset = 0; /* size of previous chunks */ | ||||
| static MemFileChunk *chunk = NULL; | static MemFileChunk *chunk = NULL; | ||||
| size_t chunkoffset, readsize, totread; | size_t chunkoffset, readsize, totread; | ||||
| if (r_is_memchunck_identical != NULL) { | if (r_is_memchunck_identical != NULL) { | ||||
| *r_is_memchunck_identical = true; | *r_is_memchunck_identical = true; | ||||
| Show All 10 Lines | if (seek != (size_t)filedata->file_offset) { | ||||
| while (chunk) { | while (chunk) { | ||||
| if (seek + chunk->size > (size_t)filedata->file_offset) { | if (seek + chunk->size > (size_t)filedata->file_offset) { | ||||
| break; | break; | ||||
| } | } | ||||
| seek += chunk->size; | seek += chunk->size; | ||||
| chunk = chunk->next; | chunk = chunk->next; | ||||
| } | } | ||||
| offset = seek; | offset = seek; | ||||
| seek = filedata->file_offset; | seek = (size_t)filedata->file_offset; | ||||
| } | } | ||||
| if (chunk) { | if (chunk) { | ||||
| totread = 0; | totread = 0; | ||||
| do { | do { | ||||
| /* first check if it's on the end if current chunk */ | /* first check if it's on the end if current chunk */ | ||||
| if (seek - offset == chunk->size) { | if (seek - offset == chunk->size) { | ||||
| Show All 27 Lines | do { | ||||
| * where we need an extra flag defined when saving the next (future) step after the one we | * where we need an extra flag defined when saving the next (future) step after the one we | ||||
| * want to restore, as we are supposed to 'come from' that future undo step, and not the | * want to restore, as we are supposed to 'come from' that future undo step, and not the | ||||
| * one before current one. */ | * one before current one. */ | ||||
| *r_is_memchunck_identical &= filedata->undo_direction > 0 ? chunk->is_identical : | *r_is_memchunck_identical &= filedata->undo_direction > 0 ? chunk->is_identical : | ||||
| chunk->is_identical_future; | chunk->is_identical_future; | ||||
| } | } | ||||
| } while (totread < size); | } while (totread < size); | ||||
| return totread; | return (ssize_t)totread; | ||||
| } | } | ||||
| return 0; | return 0; | ||||
| } | } | ||||
| static FileData *filedata_new(void) | static FileData *filedata_new(void) | ||||
| { | { | ||||
| FileData *fd = MEM_callocN(sizeof(FileData), "FileData"); | FileData *fd = MEM_callocN(sizeof(FileData), "FileData"); | ||||
| ▲ Show 20 Lines • Show All 145 Lines • ▼ Show 20 Lines | if (fd != NULL) { | ||||
| if (fd->flags & FD_FLAGS_FILE_OK) { | if (fd->flags & FD_FLAGS_FILE_OK) { | ||||
| return fd; | return fd; | ||||
| } | } | ||||
| blo_filedata_free(fd); | blo_filedata_free(fd); | ||||
| } | } | ||||
| return NULL; | return NULL; | ||||
| } | } | ||||
| static int fd_read_gzip_from_memory(FileData *filedata, | static ssize_t fd_read_gzip_from_memory(FileData *filedata, | ||||
| void *buffer, | void *buffer, | ||||
| uint size, | size_t size, | ||||
| bool *UNUSED(r_is_memchunck_identical)) | bool *UNUSED(r_is_memchunck_identical)) | ||||
| { | { | ||||
| int err; | int err; | ||||
| filedata->strm.next_out = (Bytef *)buffer; | filedata->strm.next_out = (Bytef *)buffer; | ||||
| filedata->strm.avail_out = size; | filedata->strm.avail_out = (uint)size; | ||||
| // Inflate another chunk. | // Inflate another chunk. | ||||
| err = inflate(&filedata->strm, Z_SYNC_FLUSH); | err = inflate(&filedata->strm, Z_SYNC_FLUSH); | ||||
| if (err == Z_STREAM_END) { | if (err == Z_STREAM_END) { | ||||
| return 0; | return 0; | ||||
| } | } | ||||
| if (err != Z_OK) { | if (err != Z_OK) { | ||||
| printf("fd_read_gzip_from_memory: zlib error\n"); | printf("fd_read_gzip_from_memory: zlib error\n"); | ||||
| return 0; | return 0; | ||||
| } | } | ||||
| filedata->file_offset += size; | filedata->file_offset += size; | ||||
| return size; | return (ssize_t)size; | ||||
| } | } | ||||
| static int fd_read_gzip_from_memory_init(FileData *fd) | static int fd_read_gzip_from_memory_init(FileData *fd) | ||||
| { | { | ||||
| fd->strm.next_in = (Bytef *)fd->buffer; | fd->strm.next_in = (Bytef *)fd->buffer; | ||||
| fd->strm.avail_in = fd->buffersize; | fd->strm.avail_in = fd->buffersize; | ||||
| fd->strm.total_out = 0; | fd->strm.total_out = 0; | ||||
| ▲ Show 20 Lines • Show All 7,682 Lines • Show Last 20 Lines | |||||
Shouldn't an assert be added here for size > UINT_MAX?