diff --git a/dive.h b/dive.h index 2e0039f80..ae2645ac0 100644 --- a/dive.h +++ b/dive.h @@ -656,6 +656,7 @@ extern void save_dives_logic(const char *filename, bool select_only); extern void save_dive(FILE *f, struct dive *dive); extern void export_dives_uddf(const char *filename, const bool selected); +extern int subsurface_rename(const char *path, const char *newpath); extern int subsurface_open(const char *path, int oflags, mode_t mode); extern FILE *subsurface_fopen(const char *path, const char *mode); extern void *subsurface_opendir(const char *path); diff --git a/linux.c b/linux.c index 1feefd6f1..ac1174a5c 100644 --- a/linux.c +++ b/linux.c @@ -101,6 +101,11 @@ int enumerate_devices (device_callback_t callback, void *userdata) } /* NOP wrappers to comform with windows.c */ +int subsurface_rename(const char *path, const char *newpath) +{ + return rename(path, newpath); +} + int subsurface_open(const char *path, int oflags, mode_t mode) { return open(path, oflags, mode); diff --git a/macos.c b/macos.c index ba461ee4f..aa5036ea2 100644 --- a/macos.c +++ b/macos.c @@ -82,6 +82,11 @@ int enumerate_devices (device_callback_t callback, void *userdata) } /* NOP wrappers to comform with windows.c */ +int subsurface_rename(const char *path, const char *newpath) +{ + return rename(path, newpath); +} + int subsurface_open(const char *path, int oflags, mode_t mode) { return open(path, oflags, mode); diff --git a/save-xml.c b/save-xml.c index 7bb2642bd..a95487313 100644 --- a/save-xml.c +++ b/save-xml.c @@ -577,12 +577,46 @@ void save_dives_buffer(struct membuffer *b, const bool select_only) put_format(b, "\n\n"); } +static void save_backup(const char *name, const char *ext, const char *new_ext) +{ + int len = strlen(name); + int a = strlen(ext), b = strlen(new_ext); + char *newname; + + /* len up to and including the final '.' */ + len -= a; + if (len <= 1) + return; + if (name[len-1] != '.') + return; + /* msvc doesn't have strncasecmp, has _strnicmp instead - crazy */ + if (strncasecmp(name+len, ext, a)) + return; + + newname = malloc(len + b + 1); + if (!newname) + return; + + memcpy(newname, name, len); + memcpy(newname+len, new_ext, b+1); + + /* + * Ignore errors. Maybe we can't create the backup file, + * maybe no old file existed. Regardless, we'll write the + * new file. + */ + subsurface_rename(name, newname); + free(newname); +} + void save_dives_logic(const char *filename, const bool select_only) { struct membuffer buf = {0}; FILE *f; save_dives_buffer(&buf, select_only); + /* Maybe we might want to make this configurable? */ + save_backup(filename, "xml", "bak"); f = subsurface_fopen(filename, "w"); if (f) { flush_buffer(&buf, f); diff --git a/windows.c b/windows.c index 7c537f6e5..042e1c619 100644 --- a/windows.c +++ b/windows.c @@ -111,6 +111,22 @@ static wchar_t *utf8_to_utf16_fl(const char *utf8, char *file, int line) /* bellow we provide a set of wrappers for some I/O functions to use wchar_t. * on win32 this solves the issue that we need paths to be utf-16 encoded. */ +int subsurface_rename(const char *path, const char *newpath) +{ + int ret = -1; + if (!path || !newpath) + return -1; + + wchar_t *wpath = utf8_to_utf16(path); + wchar_t *wnewpath = utf8_to_utf16(newpath); + + if (wpath && wnewpath) + ret = _wrename(wpath, wnewpath); + free((void *)wpath); + free((void *)wnewpath); + return ret; +} + int subsurface_open(const char *path, int oflags, mode_t mode) { int ret = -1;