From b9b572236a4d76487723faf82072d5a2585fead9 Mon Sep 17 00:00:00 2001 From: David Lawrence Ramsey Date: Sun, 29 May 2005 02:22:55 +0000 Subject: [PATCH] when using a backup directory, make sure all the filenames written are unique by using get_next_filename() when necessary git-svn-id: svn://svn.savannah.gnu.org/nano/trunk/nano@2565 35c25a1d-7b9e-4130-9fde-d3aeb78583b8 --- ChangeLog | 4 ++++ src/files.c | 61 +++++++++++++++++++++++++++++++++++------------------ src/nano.c | 2 +- src/proto.h | 2 +- 4 files changed, 46 insertions(+), 23 deletions(-) diff --git a/ChangeLog b/ChangeLog index 49ead8d5..f4173e63 100644 --- a/ChangeLog +++ b/ChangeLog @@ -35,6 +35,10 @@ CVS code - specified, which doesn't appear to be used anywhere. Changes to input_tab(), do_browser(), do_enter(), replace_regexp(), replace_line(), and mallocstrncpy(). (DLR) + - When using a backup directory, make sure all the filenames + written are unique by using get_next_filename() when + necessary. Changes to get_next_filename(), write_file(), and + die(). (DLR, suggested by James Collings) - cut.c: cut_line() - Set placewewant properly after cutting a line, to avoid a diff --git a/src/files.c b/src/files.c index 08828a6c..a07dac9f 100644 --- a/src/files.c +++ b/src/files.c @@ -373,19 +373,22 @@ int open_file(const char *filename, bool newfie, FILE **f) } /* This function will return the name of the first available extension - * of a filename (starting with filename.save, then filename.save.1, + * of a filename (starting with [name][suffix], then [name][suffix].1, * etc.). Memory is allocated for the return value. If no writable * extension exists, we return "". */ -char *get_next_filename(const char *name) +char *get_next_filename(const char *name, const char *suffix) { unsigned long i = 0; char *buf; - size_t namelen = strlen(name); + size_t namelen, suffixlen; - buf = charalloc(namelen + digits(ULONG_MAX) + 7); - strcpy(buf, name); - strcpy(buf + namelen, ".save"); - namelen += 5; + assert(name != NULL && suffix != NULL); + + namelen = strlen(name); + suffixlen = strlen(suffix); + + buf = charalloc(namelen + suffixlen + digits(ULONG_MAX) + 2); + sprintf(buf, "%s%s", name, suffix); while (TRUE) { struct stat fs; @@ -396,7 +399,7 @@ char *get_next_filename(const char *name) break; i++; - sprintf(buf + namelen, ".%lu", i); + sprintf(buf + namelen + suffixlen, ".%lu", i); } /* We get here only if there is no possible save file. */ @@ -1412,34 +1415,46 @@ int write_file(const char *name, bool tmp, int append, bool } /* If backup_dir is set, we set backupname to - * backup_dir/backupname~, where backupname is the canonicalized - * absolute pathname of realname with every '/' replaced with a - * '!'. This means that /home/foo/file is backed up in - * backup_dir/!home!foo!file~. */ + * backup_dir/backupname~[.number], where backupname is the + * canonicalized absolute pathname of realname with every '/' + * replaced with a '!'. This means that /home/foo/file is + * backed up in backup_dir/!home!foo!file~[.number]. */ if (backup_dir != NULL) { - char *canon_realname = get_full_path(realname); + char *backuptemp = get_full_path(realname); - if (canon_realname == NULL) + if (backuptemp == NULL) /* If get_full_path() failed, we don't have a * canonicalized absolute pathname, so just use the * filename portion of the pathname. We use tail() so * that e.g. ../backupname will be backed up in * backupdir/backupname~ instead of * backupdir/../backupname~. */ - canon_realname = mallocstrcpy(NULL, tail(realname)); + backuptemp = mallocstrcpy(NULL, tail(realname)); else { size_t i = 0; - for (; canon_realname[i] != '\0'; i++) { - if (canon_realname[i] == '/') - canon_realname[i] = '!'; + for (; backuptemp[i] != '\0'; i++) { + if (backuptemp[i] == '/') + backuptemp[i] = '!'; } } backupname = charalloc(strlen(backup_dir) + - strlen(canon_realname) + 2); - sprintf(backupname, "%s%s~", backup_dir, canon_realname); - free(canon_realname); + strlen(backuptemp) + 1); + sprintf(backupname, "%s%s", backup_dir, backuptemp); + free(backuptemp); + backuptemp = get_next_filename(backupname, "~"); + if (backuptemp[0] == '\0') { + statusbar(_("Error writing %s: %s"), backupname, + _("Too many backup files?")); + free(backuptemp); + free(backupname); + fclose(f); + goto cleanup_and_exit; + } else { + free(backupname); + backupname = backuptemp; + } } else { backupname = charalloc(strlen(realname) + 2); sprintf(backupname, "%s~", realname); @@ -1482,6 +1497,7 @@ int write_file(const char *name, bool tmp, int append, bool strerror(errno)); goto cleanup_and_exit; } + free(backupname); } #endif /* !NANO_SMALL */ @@ -1632,11 +1648,13 @@ int write_file(const char *name, bool tmp, int append, bool FILE *f_source = NULL; fd_source = open(tempname, O_RDONLY | O_CREAT); + if (fd_source != -1) { f_source = fdopen(fd_source, "rb"); if (f_source == NULL) close(fd_source); } + if (f_source == NULL) { statusbar(_("Error reading %s: %s"), tempname, strerror(errno)); @@ -1680,6 +1698,7 @@ int write_file(const char *name, bool tmp, int append, bool cleanup_and_exit: free(realname); free(tempname); + return retval; } diff --git a/src/nano.c b/src/nano.c index d3ed6b2d..a63ff34f 100644 --- a/src/nano.c +++ b/src/nano.c @@ -169,7 +169,7 @@ void die_save_file(const char *die_filename) if (die_filename[0] == '\0') die_filename = "nano"; - retval = get_next_filename(die_filename); + retval = get_next_filename(die_filename, ".save"); if (retval[0] != '\0') failed = (write_file(retval, TRUE, FALSE, TRUE) == -1); diff --git a/src/proto.h b/src/proto.h index 170a9a98..b6f42e12 100644 --- a/src/proto.h +++ b/src/proto.h @@ -246,7 +246,7 @@ filestruct *read_line(char *buf, filestruct *prevnode, bool void load_file(void); void read_file(FILE *f, const char *filename); int open_file(const char *filename, bool newfie, FILE **f); -char *get_next_filename(const char *name); +char *get_next_filename(const char *name, const char *suffix); #ifndef NANO_SMALL void execute_command(const char *command); #endif -- 2.39.5