diff options
Diffstat (limited to 'source/blender/blenloader')
-rw-r--r-- | source/blender/blenloader/BLO_readfile.h | 2 | ||||
-rw-r--r-- | source/blender/blenloader/BLO_undofile.h | 14 | ||||
-rw-r--r-- | source/blender/blenloader/intern/readfile.c | 3 | ||||
-rw-r--r-- | source/blender/blenloader/intern/undofile.c | 78 |
4 files changed, 95 insertions, 2 deletions
diff --git a/source/blender/blenloader/BLO_readfile.h b/source/blender/blenloader/BLO_readfile.h index 4fd2e227bc5..0b4ff13c7bd 100644 --- a/source/blender/blenloader/BLO_readfile.h +++ b/source/blender/blenloader/BLO_readfile.h @@ -147,6 +147,8 @@ void BLO_update_defaults_startup_blend(struct Main *mainvar); struct BlendThumbnail *BLO_thumbnail_from_file(const char *filepath); +struct Main *BLO_main_from_memfile(struct MemFile *memfile, struct Main *bmain, struct Scene **r_scene); + #ifdef __cplusplus } #endif diff --git a/source/blender/blenloader/BLO_undofile.h b/source/blender/blenloader/BLO_undofile.h index d3c0130a63b..b713b963056 100644 --- a/source/blender/blenloader/BLO_undofile.h +++ b/source/blender/blenloader/BLO_undofile.h @@ -33,6 +33,8 @@ * \ingroup blenloader */ +struct Scene; + typedef struct { void *next, *prev; const char *buf; @@ -47,6 +49,12 @@ typedef struct MemFile { size_t size; } MemFile; +typedef struct MemFileUndoData { + char filename[1024]; /* FILE_MAX */ + MemFile memfile; + size_t undo_size; +} MemFileUndoData; + /* actually only used writefile.c */ extern void memfile_chunk_add(MemFile *compare, MemFile *current, const char *buf, unsigned int size); @@ -54,5 +62,9 @@ extern void memfile_chunk_add(MemFile *compare, MemFile *current, const char *bu extern void BLO_memfile_free(MemFile *memfile); extern void BLO_memfile_merge(MemFile *first, MemFile *second); -#endif +/* utilities */ +extern struct Main *BLO_memfile_main_get(struct MemFile *memfile, struct Main *bmain, struct Scene **r_scene); +extern bool BLO_memfile_write_file(struct MemFile *memfile, const char *filename); + +#endif /* __BLO_UNDOFILE_H__ */ diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index e85af67b105..7b51ddcce92 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -6300,7 +6300,8 @@ static void direct_link_windowmanager(FileData *fd, wmWindowManager *wm) wm->defaultconf = NULL; wm->addonconf = NULL; wm->userconf = NULL; - + wm->undo_stack = NULL; + BLI_listbase_clear(&wm->jobs); BLI_listbase_clear(&wm->drags); diff --git a/source/blender/blenloader/intern/undofile.c b/source/blender/blenloader/intern/undofile.c index ffc7d7c83f5..287936e276e 100644 --- a/source/blender/blenloader/intern/undofile.c +++ b/source/blender/blenloader/intern/undofile.c @@ -34,6 +34,15 @@ #include <string.h> #include <stdio.h> #include <math.h> +#include <fcntl.h> +#include <errno.h> + +/* open/close */ +#ifndef _WIN32 +# include <unistd.h> +#else +# include <io.h> +#endif #include "MEM_guardedalloc.h" @@ -42,6 +51,9 @@ #include "BLI_blenlib.h" #include "BLO_undofile.h" +#include "BLO_readfile.h" + +#include "BKE_main.h" /* keep last */ #include "BLI_strict_flags.h" @@ -124,3 +136,69 @@ void memfile_chunk_add(MemFile *compare, MemFile *current, const char *buf, unsi current->size += size; } } + +struct Main *BLO_memfile_main_get(struct MemFile *memfile, struct Main *oldmain, struct Scene **r_scene) +{ + struct Main *bmain_undo = NULL; + BlendFileData *bfd = BLO_read_from_memfile(oldmain, oldmain->name, memfile, NULL, BLO_READ_SKIP_NONE); + + if (bfd) { + bmain_undo = bfd->main; + if (r_scene) { + *r_scene = bfd->curscene; + } + + MEM_freeN(bfd); + } + + return bmain_undo; +} + + +/** + * Saves .blend using undo buffer. + * + * \return success. + */ +bool BLO_memfile_write_file(struct MemFile *memfile, const char *filename) +{ + MemFileChunk *chunk; + int file, oflags; + + /* note: This is currently used for autosave and 'quit.blend', where _not_ following symlinks is OK, + * however if this is ever executed explicitly by the user, we may want to allow writing to symlinks. + */ + + oflags = O_BINARY | O_WRONLY | O_CREAT | O_TRUNC; +#ifdef O_NOFOLLOW + /* use O_NOFOLLOW to avoid writing to a symlink - use 'O_EXCL' (CVE-2008-1103) */ + oflags |= O_NOFOLLOW; +#else + /* TODO(sergey): How to deal with symlinks on windows? */ +# ifndef _MSC_VER +# warning "Symbolic links will be followed on undo save, possibly causing CVE-2008-1103" +# endif +#endif + file = BLI_open(filename, oflags, 0666); + + if (file == -1) { + fprintf(stderr, "Unable to save '%s': %s\n", + filename, errno ? strerror(errno) : "Unknown error opening file"); + return false; + } + + for (chunk = memfile->chunks.first; chunk; chunk = chunk->next) { + if (write(file, chunk->buf, chunk->size) != chunk->size) { + break; + } + } + + close(file); + + if (chunk) { + fprintf(stderr, "Unable to save '%s': %s\n", + filename, errno ? strerror(errno) : "Unknown error writing file"); + return false; + } + return true; +} |