> So perhaps it is better for mg to behave more like emacs when it comes
> to saving backup files in a single directory. Especially if a user has
> two files open with the same name and are working on them
> simultaneously. In this diff I've added the path to the backup file
> name. Like emacs, it changes any '/' to '!'.
>
Here is a slightly modified diff; add NUL termination to backup path.
Are there objections to this going in?
-lum
Index: def.h
===================================================================
RCS file: /cvs/src/usr.bin/mg/def.h,v
retrieving revision 1.123
diff -u -p -r1.123 def.h
--- def.h 7 Jun 2012 15:15:04 -0000 1.123
+++ def.h 9 Jun 2012 20:22:10 -0000
@@ -446,6 +446,7 @@ struct list *make_file_list(char *);
int fisdir(const char *);
int fchecktime(struct buffer *);
int fupdstat(struct buffer *);
+int backuptohomedir(int, int);
/* kbd.c X */
int do_meta(int, int);
Index: fileio.c
===================================================================
RCS file: /cvs/src/usr.bin/mg/fileio.c,v
retrieving revision 1.89
diff -u -p -r1.89 fileio.c
--- fileio.c 25 May 2012 04:56:58 -0000 1.89
+++ fileio.c 9 Jun 2012 20:22:10 -0000
@@ -22,6 +22,10 @@
#include "kbd.h"
+static char *bkuplocation(const char *);
+
+static char *bkupdir;
+
/*
* Open a file for reading.
*/
@@ -189,6 +193,51 @@ ffgetline(FILE *ffp, char *buf, int nbuf
}
/*
+ * Location of backup file. This function creates the correct path.
+ */
+static char *
+bkuplocation(const char *fn)
+{
+ struct stat sb;
+ char *ret;
+
+ if (bkupdir != NULL && (stat(bkupdir, &sb) == 0) &&
+ S_ISDIR(sb.st_mode)) {
+ char fname[NFILEN];
+ const char *c;
+ int i = 0, len;
+
+ c = fn;
+ len = strlen(bkupdir);
+
+ while (*c != '\0') {
+ /* Make sure we don't go over combined:
+ * strlen(bkupdir + '/' + fname + '\0')
+ */
+ if (i >= NFILEN - len - 1)
+ return (NULL);
+ if (*c == '/') {
+ fname[i] = '!';
+ } else if (*c == '!') {
+ if (i >= NFILEN - len - 2)
+ return (NULL);
+ fname[i++] = '!';
+ fname[i] = '!';
+ } else
+ fname[i] = *c;
+ i++;
+ c++;
+ }
+ fname[i] = '\0';
+ if (asprintf(&ret, "%s/%s", bkupdir, fname) == -1)
+ return (NULL);
+ } else if ((ret = strndup(fn, NFILEN)) == NULL)
+ return (NULL);
+
+ return (ret);
+}
+
+/*
* Make a backup copy of "fname". On Unix the backup has the same
* name as the original file, with a "~" on the end; this seems to
* be newest of the new-speak. The error handling is all in "file.c".
@@ -203,23 +252,29 @@ fbackupfile(const char *fn)
int from, to, serrno;
ssize_t nread;
char buf[BUFSIZ];
- char *nname, *tname;
+ char *nname, *tname, *bkpth;
if (stat(fn, &sb) == -1) {
ewprintf("Can't stat %s : %s", fn, strerror(errno));
return (FALSE);
}
- if (asprintf(&nname, "%s~", fn) == -1) {
+ if ((bkpth = bkuplocation(fn)) == NULL)
+ return (FALSE);
+
+ if (asprintf(&nname, "%s~", bkpth) == -1) {
ewprintf("Can't allocate temp file name : %s", strerror(errno));
+ free(bkpth);
return (ABORT);
}
- if (asprintf(&tname, "%s.XXXXXXXXXX", fn) == -1) {
+ if (asprintf(&tname, "%s.XXXXXXXXXX", bkpth) == -1) {
ewprintf("Can't allocate temp file name : %s", strerror(errno));
+ free(bkpth);
free(nname);
return (ABORT);
}
+ free(bkpth);
if ((from = open(fn, O_RDONLY)) == -1) {
free(nname);
@@ -610,4 +665,28 @@ fchecktime(struct buffer *bp)
return (TRUE);
+}
+
+int
+backuptohomedir(int f, int n)
+{
+ const char *c = "~/.mg.d";
+ char *p;
+
+ if (bkupdir == NULL) {
+ p = adjustname(c, TRUE);
+ bkupdir = strndup(p, NFILEN);
+ if (bkupdir == NULL)
+ return(FALSE);
+
+ if (mkdir(bkupdir, 0700) == -1 && errno != EEXIST) {
+ free(bkupdir);
+ bkupdir = NULL;
+ }
+ } else {
+ free(bkupdir);
+ bkupdir = NULL;
+ }
+
+ return (TRUE);
}
Index: funmap.c
===================================================================
RCS file: /cvs/src/usr.bin/mg/funmap.c,v
retrieving revision 1.39
diff -u -p -r1.39 funmap.c
--- funmap.c 7 Jun 2012 15:15:04 -0000 1.39
+++ funmap.c 9 Jun 2012 20:22:10 -0000
@@ -25,6 +25,7 @@ static struct funmap functnames[] = {
{fillmode, "auto-fill-mode",},
{indentmode, "auto-indent-mode",},
{backtoindent, "back-to-indentation",},
+ {backuptohomedir, "backup-to-home-directory",},
{backchar, "backward-char",},
{delbword, "backward-kill-word",},
{gotobop, "backward-paragraph",},
Index: mg.1
===================================================================
RCS file: /cvs/src/usr.bin/mg/mg.1,v
retrieving revision 1.61
diff -u -p -r1.61 mg.1
--- mg.1 7 Jun 2012 15:15:04 -0000 1.61
+++ mg.1 9 Jun 2012 20:22:10 -0000
@@ -350,6 +350,9 @@ to a new line.
Toggle indent mode, where indentation is preserved after a newline.
.It back-to-indentation
Move the dot to the first non-whitespace character on the current line.
+.It backup-to-home-directory
+Save backup copies to a ~/.mg.d directory instead of working directory.
+Requires make-backup-files to be on.
.It backward-char
Move cursor backwards one character.
.It backward-kill-word