From 651b8fb14eb6ee5cbfa98bffe80a966a0753b14e Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 19 Mar 2018 14:17:59 +0100 Subject: Undo: unified undo system w/ linear history - Use a single undo history for all operations. - UndoType's are registered and poll the context to check if they should be used when performing an undo push. - Mode switching is used to ensure the state is correct before undo data is restored. - Some undo types accumulate changes (image & text editing) others store the state multiple times (with de-duplication). This is supported by checking UndoStack.mode `ACCUMULATE` / `STORE`. - Each undo step stores ID datablocks they use with utilities to help manage restoring correct ID's. Needed since global undo is now mixed with other modes undo. - Currently performs each undo step when going up/down history Previously this wasn't done, making history fail in some cases. This can be optimized to skip some combinations of undo steps. grease-pencil is an exception which has not been updated since it integrates undo into the draw-session. See D3113 --- source/blender/blenloader/intern/undofile.c | 78 +++++++++++++++++++++++++++++ 1 file changed, 78 insertions(+) (limited to 'source/blender/blenloader/intern/undofile.c') 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 #include #include +#include +#include + +/* open/close */ +#ifndef _WIN32 +# include +#else +# include +#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; +} -- cgit v1.2.3