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-d3aeb78583b8master
parent
df2a82509b
commit
b9b572236a
|
@ -35,6 +35,10 @@ CVS code -
|
||||||
specified, which doesn't appear to be used anywhere. Changes
|
specified, which doesn't appear to be used anywhere. Changes
|
||||||
to input_tab(), do_browser(), do_enter(), replace_regexp(),
|
to input_tab(), do_browser(), do_enter(), replace_regexp(),
|
||||||
replace_line(), and mallocstrncpy(). (DLR)
|
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.c:
|
||||||
cut_line()
|
cut_line()
|
||||||
- Set placewewant properly after cutting a line, to avoid a
|
- Set placewewant properly after cutting a line, to avoid a
|
||||||
|
|
61
src/files.c
61
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
|
/* 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
|
* etc.). Memory is allocated for the return value. If no writable
|
||||||
* extension exists, we return "". */
|
* 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;
|
unsigned long i = 0;
|
||||||
char *buf;
|
char *buf;
|
||||||
size_t namelen = strlen(name);
|
size_t namelen, suffixlen;
|
||||||
|
|
||||||
buf = charalloc(namelen + digits(ULONG_MAX) + 7);
|
assert(name != NULL && suffix != NULL);
|
||||||
strcpy(buf, name);
|
|
||||||
strcpy(buf + namelen, ".save");
|
namelen = strlen(name);
|
||||||
namelen += 5;
|
suffixlen = strlen(suffix);
|
||||||
|
|
||||||
|
buf = charalloc(namelen + suffixlen + digits(ULONG_MAX) + 2);
|
||||||
|
sprintf(buf, "%s%s", name, suffix);
|
||||||
|
|
||||||
while (TRUE) {
|
while (TRUE) {
|
||||||
struct stat fs;
|
struct stat fs;
|
||||||
|
@ -396,7 +399,7 @@ char *get_next_filename(const char *name)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
i++;
|
i++;
|
||||||
sprintf(buf + namelen, ".%lu", i);
|
sprintf(buf + namelen + suffixlen, ".%lu", i);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* We get here only if there is no possible save file. */
|
/* 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
|
/* If backup_dir is set, we set backupname to
|
||||||
* backup_dir/backupname~, where backupname is the canonicalized
|
* backup_dir/backupname~[.number], where backupname is the
|
||||||
* absolute pathname of realname with every '/' replaced with a
|
* canonicalized absolute pathname of realname with every '/'
|
||||||
* '!'. This means that /home/foo/file is backed up in
|
* replaced with a '!'. This means that /home/foo/file is
|
||||||
* backup_dir/!home!foo!file~. */
|
* backed up in backup_dir/!home!foo!file~[.number]. */
|
||||||
if (backup_dir != NULL) {
|
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
|
/* If get_full_path() failed, we don't have a
|
||||||
* canonicalized absolute pathname, so just use the
|
* canonicalized absolute pathname, so just use the
|
||||||
* filename portion of the pathname. We use tail() so
|
* filename portion of the pathname. We use tail() so
|
||||||
* that e.g. ../backupname will be backed up in
|
* that e.g. ../backupname will be backed up in
|
||||||
* backupdir/backupname~ instead of
|
* backupdir/backupname~ instead of
|
||||||
* backupdir/../backupname~. */
|
* backupdir/../backupname~. */
|
||||||
canon_realname = mallocstrcpy(NULL, tail(realname));
|
backuptemp = mallocstrcpy(NULL, tail(realname));
|
||||||
else {
|
else {
|
||||||
size_t i = 0;
|
size_t i = 0;
|
||||||
|
|
||||||
for (; canon_realname[i] != '\0'; i++) {
|
for (; backuptemp[i] != '\0'; i++) {
|
||||||
if (canon_realname[i] == '/')
|
if (backuptemp[i] == '/')
|
||||||
canon_realname[i] = '!';
|
backuptemp[i] = '!';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
backupname = charalloc(strlen(backup_dir) +
|
backupname = charalloc(strlen(backup_dir) +
|
||||||
strlen(canon_realname) + 2);
|
strlen(backuptemp) + 1);
|
||||||
sprintf(backupname, "%s%s~", backup_dir, canon_realname);
|
sprintf(backupname, "%s%s", backup_dir, backuptemp);
|
||||||
free(canon_realname);
|
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 {
|
} else {
|
||||||
backupname = charalloc(strlen(realname) + 2);
|
backupname = charalloc(strlen(realname) + 2);
|
||||||
sprintf(backupname, "%s~", realname);
|
sprintf(backupname, "%s~", realname);
|
||||||
|
@ -1482,6 +1497,7 @@ int write_file(const char *name, bool tmp, int append, bool
|
||||||
strerror(errno));
|
strerror(errno));
|
||||||
goto cleanup_and_exit;
|
goto cleanup_and_exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
free(backupname);
|
free(backupname);
|
||||||
}
|
}
|
||||||
#endif /* !NANO_SMALL */
|
#endif /* !NANO_SMALL */
|
||||||
|
@ -1632,11 +1648,13 @@ int write_file(const char *name, bool tmp, int append, bool
|
||||||
FILE *f_source = NULL;
|
FILE *f_source = NULL;
|
||||||
|
|
||||||
fd_source = open(tempname, O_RDONLY | O_CREAT);
|
fd_source = open(tempname, O_RDONLY | O_CREAT);
|
||||||
|
|
||||||
if (fd_source != -1) {
|
if (fd_source != -1) {
|
||||||
f_source = fdopen(fd_source, "rb");
|
f_source = fdopen(fd_source, "rb");
|
||||||
if (f_source == NULL)
|
if (f_source == NULL)
|
||||||
close(fd_source);
|
close(fd_source);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (f_source == NULL) {
|
if (f_source == NULL) {
|
||||||
statusbar(_("Error reading %s: %s"), tempname,
|
statusbar(_("Error reading %s: %s"), tempname,
|
||||||
strerror(errno));
|
strerror(errno));
|
||||||
|
@ -1680,6 +1698,7 @@ int write_file(const char *name, bool tmp, int append, bool
|
||||||
cleanup_and_exit:
|
cleanup_and_exit:
|
||||||
free(realname);
|
free(realname);
|
||||||
free(tempname);
|
free(tempname);
|
||||||
|
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -169,7 +169,7 @@ void die_save_file(const char *die_filename)
|
||||||
if (die_filename[0] == '\0')
|
if (die_filename[0] == '\0')
|
||||||
die_filename = "nano";
|
die_filename = "nano";
|
||||||
|
|
||||||
retval = get_next_filename(die_filename);
|
retval = get_next_filename(die_filename, ".save");
|
||||||
if (retval[0] != '\0')
|
if (retval[0] != '\0')
|
||||||
failed = (write_file(retval, TRUE, FALSE, TRUE) == -1);
|
failed = (write_file(retval, TRUE, FALSE, TRUE) == -1);
|
||||||
|
|
||||||
|
|
|
@ -246,7 +246,7 @@ filestruct *read_line(char *buf, filestruct *prevnode, bool
|
||||||
void load_file(void);
|
void load_file(void);
|
||||||
void read_file(FILE *f, const char *filename);
|
void read_file(FILE *f, const char *filename);
|
||||||
int open_file(const char *filename, bool newfie, FILE **f);
|
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
|
#ifndef NANO_SMALL
|
||||||
void execute_command(const char *command);
|
void execute_command(const char *command);
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in New Issue