nano-devel
[Top][All Lists]
Advanced

[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;




reply via email to

[Prev in Thread] Current Thread [Next in Thread]