[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Nano-devel] File Backup Patch
From: |
Carl Drinkwater |
Subject: |
[Nano-devel] File Backup Patch |
Date: |
Fri, 17 May 2002 19:44:27 +0100 |
Hi,
Find attached a patch which enables backing up of files a la emacs
(filename.txt => filename.txt~ )
The patch adds -
o A command line option -u and --backup.
o M-u for toggling backup on and off (Option listed in writeout menu,
but works everywhere).
o If the original file has remained unchanged since the file was
loaded, it is copied to filename~
o If the original file has changed, or has been deleted since the file
was loaded, no backup is made.
o File permissions and owner/group of the original file are preserved.
o Backup at the moment is disabled by default.
o Backup isn't present if ./configured with --enable-tiny.
The patch is made against 1.1.9-cvs checked out this afternoon GMT.
I've not altered any of the documentation as some behaviour may change
according to any comments it gets.
I've also added '\n' to the end of the 'filename is ...' messages
fprintf(stderr, _("filename is %s\n"), open_files->filename);
... lines in files.c for tidier debug messages (Sorry if it was intended
to be without).
Actually, is it correct to ./configure with --enable-debug but still
have to add '#define DEBUG 1' somewhere to get debug messages?
Anyway, let me know of any comments/problems you have with this.
Regards,
Carl.
diff -urN nano-1.1.9-cvs/files.c nano-1.1.9-cvs-fixed/files.c
--- nano-1.1.9-cvs/files.c Sun May 12 20:52:15 2002
+++ nano-1.1.9-cvs-fixed/files.c Fri May 17 19:32:05 2002
@@ -326,6 +326,7 @@
return -1;
}
read_file(f, filename, quiet);
+ stat( filename, &originalfilestat );
}
return 1;
@@ -387,7 +388,7 @@
if (i != -1) {
#ifdef DEBUG
- fprintf(stderr, _("filename is %s"), answer);
+ fprintf(stderr, _("filename is %s\n"), answer);
#endif
#ifndef DISABLE_TABCOMP
@@ -573,7 +574,7 @@
open_files and splice it in after the current one */
#ifdef DEBUG
- fprintf(stderr, _("filename is %s"), open_files->filename);
+ fprintf(stderr, _("filename is %s\n"), open_files->filename);
#endif
tmp = make_new_opennode(NULL);
@@ -626,7 +627,7 @@
}
#ifdef DEBUG
- fprintf(stderr, _("filename is %s"), open_files->filename);
+ fprintf(stderr, _("filename is %s\n"), open_files->filename);
#endif
return 0;
@@ -717,7 +718,7 @@
open_files = open_files->prev;
#ifdef DEBUG
- fprintf(stderr, _("filename is %s"), open_files->filename);
+ fprintf(stderr, _("filename is %s\n"), open_files->filename);
#endif
}
@@ -729,7 +730,7 @@
open_files = open_files->next;
#ifdef DEBUG
- fprintf(stderr, _("filename is %s"), open_files->filename);
+ fprintf(stderr, _("filename is %s\n"), open_files->filename);
#endif
}
@@ -781,7 +782,7 @@
open_files = open_files->next;
#ifdef DEBUG
- fprintf(stderr, _("filename is %s"), open_files->filename);
+ fprintf(stderr, _("filename is %s\n"), open_files->filename);
#endif
}
@@ -792,7 +793,7 @@
open_files = open_files->prev;
#ifdef DEBUG
- fprintf(stderr, _("filename is %s"), open_files->filename);
+ fprintf(stderr, _("filename is %s\n"), open_files->filename);
#endif
}
@@ -1220,10 +1221,13 @@
char *buf = NULL;
filestruct *fileptr;
FILE *f;
- int fd;
+ int fd, backupfd;
int mask = 0, realexists, anyexists;
struct stat st, lst;
char *realname = NULL;
+ char *backupname = NULL;
+ char backupbuf[COPYFILEBLOCKSIZE];
+ int bytesread;
if (name[0] == '\0') {
statusbar(_("Cancelled"));
@@ -1260,6 +1264,70 @@
/* Save the state of file at the end of the symlink (if there is
one) */
realexists = stat(realname, &st);
+#ifndef NANO_SMALL
+ if (ISSET(BACKUP_FILE)) {
+ /* should we backup? */
+ /* stat returns 0 on success, -1 on file doesn't exist or other
error */
+ if ( realexists == 0) {
+#ifdef DEBUG
+ fprintf(stderr, _("original file modified %ld\n"),
originalfilestat.st_mtimespec.tv_sec );
+ fprintf(stderr, _("existing file modified %ld\n"),
st.st_mtimespec.tv_sec );
+#endif
+
+ /* is the original file mtime the same as it is now? */
+ if ( originalfilestat.st_mtimespec.tv_sec ==
st.st_mtimespec.tv_sec ) {
+ backupname = charalloc(strlen(realname)+2);
+ sprintf( backupname, "%s~", realname );
+#ifdef DEBUG
+ fprintf( stderr, _("We should back up with filename %s\n"),
backupname);
+#endif
+
+ /* get a file descriptor for the source, original file */
+ fd = open(realname, O_RDONLY);
+ if ( !fd ) {
+ statusbar(_("Could not original file for reading for backup:
%s"),
+ strerror(errno));
+ return -1;
+ }
+
+ /* get a file descriptor for the destination backup file */
+ backupfd = open(backupname, O_WRONLY | O_CREAT | O_TRUNC,
(S_IRUSR|S_IWUSR));
+ if ( !backupfd ) {
+ statusbar(_("Could not original backup for writing: %s"),
+ strerror(errno));
+ return -1;
+ }
+
+#ifdef DEBUG
+ fprintf( stderr, _("Backing up %s to %s\n"), realname,
backupname);
+#endif
+ /* copy the file */
+ while ((bytesread = read(fd,backupbuf,COPYFILEBLOCKSIZE))>0)
+ if (write(backupfd, backupbuf, bytesread)<=0)
+ break;
+
+ close( backupfd );
+ close( fd );
+
+ if (chmod(backupname, originalfilestat.st_mode) == -1)
+ statusbar(_("Could not set permissions %o on backup %s:
%s"),
+ originalfilestat.st_mode, backupname,
strerror(errno));
+
+ if (chown(backupname, originalfilestat.st_uid,
originalfilestat.st_gid) == -1)
+ statusbar(_("Could not set owner %d/group %d on backup %s:
%s"),
+ originalfilestat.st_uid, originalfilestat.st_gid,
backupname, strerror(errno));
+
+ free( backupname );
+ }
+
+#ifdef DEBUG
+ } else {
+ fprintf(stderr, _("File doesn't already exist\n"));
+#endif
+ }
+ }
+#endif
+
/* Stat the link itself for the check... */
anyexists = lstat(realname, &lst);
@@ -1501,6 +1569,7 @@
{
int i = 0;
char *formatstr = NULL;
+ char *backupstr = NULL;
#ifdef NANO_EXTRA
static int did_cred = 0;
@@ -1537,29 +1606,35 @@
else
formatstr = "";
+ if (ISSET(BACKUP_FILE)) {
+ backupstr = _(" [Backup] ");
+ } else {
+ backupstr = "";
+ }
+
/* Be nice to the translation folks */
if (ISSET(MARK_ISSET) && !exiting) {
if (append == 2)
i = statusq(1, writefile_list, "",
- "%s%s", _("Prepend Selection to File"), formatstr);
+ "%s%s%s", _("Prepend Selection to File"), formatstr,
backupstr);
else if (append)
i = statusq(1, writefile_list, "",
- "%s%s", _("Append Selection to File"), formatstr);
+ "%s%s%s", _("Append Selection to File"), formatstr,
backupstr);
else
i = statusq(1, writefile_list, "",
- "%s%s", _("Write Selection to File"), formatstr);
+ "%s%s%s", _("Write Selection to File"), formatstr,
backupstr);
} else
#endif
{
if (append == 2)
i = statusq(1, writefile_list, answer,
- "%s%s", _("File Name to Prepend"), formatstr);
+ "%s%s%s", _("File Name to Prepend"), formatstr,
backupstr);
else if (append)
i = statusq(1, writefile_list, answer,
- "%s%s", _("File Name to Append"), formatstr);
+ "%s%s%s", _("File Name to Append"), formatstr,
backupstr);
else
i = statusq(1, writefile_list, answer,
- "%s%s", _("File Name to Write"), formatstr);
+ "%s%s%s", _("File Name to Write"), formatstr,
backupstr);
}
@@ -1588,13 +1663,16 @@
UNSET(DOS_FILE);
TOGGLE(MAC_FILE);
return(do_writeout(answer, exiting, append));
+ } else if (i == TOGGLE_BACKUP_KEY) {
+ TOGGLE(BACKUP_FILE);
+ return(do_writeout(answer, exiting, append));
} else if (i == NANO_PREPEND_KEY)
return(do_writeout(answer, exiting, append==2 ? 0 : 2));
else if (i == NANO_APPEND_KEY)
return(do_writeout(answer, exiting, append==1 ? 0 : 1));
#ifdef DEBUG
- fprintf(stderr, _("filename is %s"), answer);
+ fprintf(stderr, _("filename is %s\n"), answer);
#endif
#ifdef NANO_EXTRA
diff -urN nano-1.1.9-cvs/global.c nano-1.1.9-cvs-fixed/global.c
--- nano-1.1.9-cvs/global.c Fri May 17 00:30:14 2002
+++ nano-1.1.9-cvs-fixed/global.c Fri May 17 13:41:05 2002
@@ -42,6 +42,7 @@
WINDOW *topwin; /* Top line of screen */
WINDOW *bottomwin; /* Bottom buffer */
char *filename = NULL; /* Name of the file */
+struct stat originalfilestat; /* stat for the file as we loaded it */
int editwinrows = 0; /* How many rows long is the edit
window? */
filestruct *current; /* Current buffer pointer */
@@ -224,7 +225,7 @@
*toggle_nohelp_msg, *toggle_picomode_msg, *toggle_mouse_msg,
*toggle_cuttoend_msg, *toggle_wrap_msg, *toggle_case_msg,
*toggle_backwards_msg, *toggle_noconvert_msg, *toggle_dos_msg,
- *toggle_mac_msg, *toggle_smooth_msg;
+ *toggle_mac_msg, *toggle_backup_msg, *toggle_smooth_msg;
#ifdef HAVE_REGEX_H
char *toggle_regexp_msg;
@@ -251,6 +252,7 @@
toggle_noconvert_msg = _("No conversion from DOS/Mac format");
toggle_dos_msg = _("Writing file in DOS format");
toggle_mac_msg = _("Writing file in Mac format");
+ toggle_backup_msg = _("Backing up file");
toggle_smooth_msg = _("Smooth scrolling");
toggle_wrap_msg = _("Auto wrap");
@@ -279,6 +281,7 @@
toggle_init_one(TOGGLE_NOCONVERT_KEY, toggle_noconvert_msg,
NO_CONVERT);
toggle_init_one(TOGGLE_DOS_KEY, toggle_dos_msg, DOS_FILE);
toggle_init_one(TOGGLE_MAC_KEY, toggle_mac_msg, MAC_FILE);
+ toggle_init_one(TOGGLE_BACKUP_KEY, toggle_backup_msg, BACKUP_FILE);
toggle_init_one(TOGGLE_SMOOTH_KEY, toggle_smooth_msg, SMOOTHSCROLL);
}
#endif /* !NANO_SMALL */
@@ -324,6 +327,7 @@
char *nano_tofiles_msg = "", *nano_gotodir_msg = "",
*nano_case_msg =
"", *nano_reverse_msg = "", *nano_execute_msg = "";
char *nano_dos_msg = "", *nano_mac_msg = "";
+ char *nano_backup_msg = "";
#ifdef HAVE_REGEX_H
char *nano_regexp_msg = "", *nano_bracket_msg = "";
@@ -376,6 +380,7 @@
nano_reverse_msg = _("Search backwards");
nano_dos_msg = _("Write file out in DOS format");
nano_mac_msg = _("Write file out in Mac format");
+ nano_backup_msg = _("Back up original file when saving");
#ifdef HAVE_REGEX_H
nano_regexp_msg = _("Use Regular expressions");
nano_bracket_msg = _("Find other bracket");
@@ -694,6 +699,7 @@
sc_init_one(&writefile_list, TOGGLE_MAC_KEY, _("Mac Format"),
IFHELP(nano_mac_msg, 0), 0, 0, NOVIEW, 0);
+
#endif
sc_init_one(&writefile_list, NANO_APPEND_KEY, _("Append"),
@@ -701,6 +707,11 @@
sc_init_one(&writefile_list, NANO_PREPEND_KEY, _("Prepend"),
IFHELP(nano_prepend_msg, 0), 0, 0, NOVIEW, 0);
+
+#ifndef NANO_SMALL
+ sc_init_one(&writefile_list, TOGGLE_BACKUP_KEY, _("Backup File"),
+ IFHELP(nano_backup_msg, 0), 0, 0, NOVIEW, 0);
+#endif
sc_init_one(&writefile_list, NANO_CANCEL_KEY, _("Cancel"),
IFHELP(nano_cancel_msg, 0), 0, 0, VIEW, 0);
diff -urN nano-1.1.9-cvs/nano.c nano-1.1.9-cvs-fixed/nano.c
--- nano-1.1.9-cvs/nano.c Sun May 12 20:52:15 2002
+++ nano-1.1.9-cvs-fixed/nano.c Fri May 17 10:34:19 2002
@@ -550,6 +550,9 @@
print1opt(_("-s [prog]"), _("--speller=[prog]"), _("Enable
alternate speller"));
#endif
print1opt("-t", "--tempfile", _("Auto save on exit, don't prompt"));
+#ifndef NANO_SMALL
+ print1opt("-u", "--backup", _("Backup existing files on save"));
+#endif
print1opt("-v", "--view", _("View (read only) mode"));
#ifndef DISABLE_WRAPPING
print1opt("-w", "--nowrap", _("Don't wrap long lines"));
@@ -2820,6 +2823,7 @@
{"mac", 0, 0, 'M'},
{"noconvert", 0, 0, 'N'},
{"autoindent", 0, 0, 'i'},
+ {"backup", 0, 0, 'u'},
#endif
{"tempfile", 0, 0, 't'},
#ifndef DISABLE_SPELLER
@@ -2867,11 +2871,11 @@
#endif /* ENABLE_NANORC */
#ifdef HAVE_GETOPT_LONG
- while ((optchr = getopt_long(argc, argv,
"h?DFKMNQ:RST:VY:abcefgijklmo:pr:s:tvwxz",
+ while ((optchr = getopt_long(argc, argv,
"h?DFKMNQ:RST:VY:abcefgijklmo:pr:s:tuvwxz",
long_options, &option_index)) != EOF) {
#else
while ((optchr =
- getopt(argc, argv,
"h?DFKMNQ:RST:VY:abcefgijklmo:pr:s:tvwxz")) != EOF) {
+ getopt(argc, argv,
"h?DFKMNQ:RST:VY:abcefgijklmo:pr:s:tuvwxz")) != EOF) {
#endif
switch (optchr) {
@@ -2998,6 +3002,9 @@
case 't':
SET(TEMP_OPT);
break;
+ case 'u':
+ SET(BACKUP_FILE);
+ break;
case 'v':
SET(VIEW_MODE);
break;
diff -urN nano-1.1.9-cvs/nano.h nano-1.1.9-cvs-fixed/nano.h
--- nano-1.1.9-cvs/nano.h Sun May 12 20:52:15 2002
+++ nano-1.1.9-cvs-fixed/nano.h Fri May 17 19:16:51 2002
@@ -36,6 +36,8 @@
#define ISSET(bit) (flags & bit)
#define TOGGLE(bit) flags ^= bit
+/* For the backup file copy ... */
+#define COPYFILEBLOCKSIZE 1024
#ifdef USE_SLANG /* Slang support enabled */
#include <slcurses.h>
@@ -190,7 +192,7 @@
#define DISABLE_CURPOS (1<<24) /* Damn, we still need it */
#define ALT_KEYPAD (1<<25)
#define NO_CONVERT (1<<26)
-
+#define BACKUP_FILE (1<<27)
/* Control key sequences, changing these would be very very bad */
#ifndef NANO_SMALL
@@ -346,6 +348,7 @@
#define TOGGLE_MAC_KEY NANO_ALT_O
#define TOGGLE_SMOOTH_KEY NANO_ALT_S
#define TOGGLE_NOCONVERT_KEY NANO_ALT_N
+#define TOGGLE_BACKUP_KEY NANO_ALT_U
#define MAIN_VISIBLE 12
diff -urN nano-1.1.9-cvs/proto.h nano-1.1.9-cvs-fixed/proto.h
--- nano-1.1.9-cvs/proto.h Sun May 12 20:52:15 2002
+++ nano-1.1.9-cvs-fixed/proto.h Fri May 17 13:39:08 2002
@@ -45,6 +45,7 @@
extern WINDOW *edit, *topwin, *bottomwin;
extern char *filename;
+extern struct stat originalfilestat;
extern char *answer;
extern char *hblank, *help_text;
extern char *last_search;
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [Nano-devel] File Backup Patch,
Carl Drinkwater <=