Re: mg - save backup files to homedir (diff v2)
> 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 - 1.123 +++ def.h 9 Jun 2012 20:22:10 - @@ -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.c25 May 2012 04:56:58 - 1.89 +++ fileio.c9 Jun 2012 20:22:10 - @@ -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.XX", fn) == -1) { + if (asprintf(&tname, "%s.XX", 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:
Re: mg - save backup files to homedir (diff v2)
> [note: I've modifed this diff from the first version with comments > from eric@ and Sunil Nimmagadda.] > > I find the backup files mg creates scattered around a pain but then > again I don't want to switch backups off since they can be useful. > Also, I don't feel the need to implement something in mg as fancy as > emacs's backup functionality ie. moving backup files, versioning, > deleting old backup versions etc > > With this diff I've only added the emacs functionality of moving the > backup files to a single directory instead of having them scattered > around everywhere. > > There are some drawbacks to having the backups in one directory of > course, only one backup version is maintained for files of the same > name but which originate in different directories (But that is > enough for me) > > Since the functionality isn't trying to mimic emacs exactly, the > command name I've chosen isn't trying to reuse one of emacs'. > > backup-to-home-directory > > This is open to suggestions of course. > > The backup directory name ~/.mg.d stems from emacs's ~/.emacs.d. > 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 '!'. mark 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 - 1.123 +++ def.h 8 Jun 2012 09:59:16 - @@ -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.c25 May 2012 04:56:58 - 1.89 +++ fileio.c8 Jun 2012 09:59:17 - @@ -22,6 +22,10 @@ #include "kbd.h" +static char *bkuplocation(const char *); + +static char *bkupdir; + /* * Open a file for reading. */ @@ -189,6 +193,50 @@ 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++; + } + 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 +251,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.XX", fn) == -1) { + if (asprintf(&tname, "%s.XX", bkpth) == -1) { ewprintf("Can't
mg - save backup files to homedir (diff v2)
[note: I've modifed this diff from the first version with comments from eric@ and Sunil Nimmagadda.] I find the backup files mg creates scattered around a pain but then again I don't want to switch backups off since they can be useful. Also, I don't feel the need to implement something in mg as fancy as emacs's backup functionality ie. moving backup files, versioning, deleting old backup versions etc With this diff I've only added the emacs functionality of moving the backup files to a single directory instead of having them scattered around everywhere. There are some drawbacks to having the backups in one directory of course, only one backup version is maintained for files of the same name but which originate in different directories (But that is enough for me) Since the functionality isn't trying to mimic emacs exactly, the command name I've chosen isn't trying to reuse one of emacs'. backup-to-home-directory This is open to suggestions of course. The backup directory name ~/.mg.d stems from emacs's ~/.emacs.d. Any comments? -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 - 1.123 +++ def.h 7 Jun 2012 17:38:26 - @@ -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.c25 May 2012 04:56:58 - 1.89 +++ fileio.c7 Jun 2012 17:38:26 - @@ -22,6 +22,10 @@ #include "kbd.h" +static char *bkuplocation(const char *); + +static char *bkupdir; + /* * Open a file for reading. */ @@ -189,6 +193,26 @@ 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 *fname, *c; + + if (bkupdir != NULL && (stat(bkupdir, &sb) == 0) && + S_ISDIR(sb.st_mode)) { + c = strrchr(fn, '/'); + if (asprintf(&fname, "%s%s", bkupdir, c) == -1) + return (NULL); + } else if ((fname = strndup(fn, NFILEN)) == NULL) + return (NULL); + + return (fname); +} + +/* * 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 +227,27 @@ 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)); return (ABORT); } - if (asprintf(&tname, "%s.XX", fn) == -1) { + if (asprintf(&tname, "%s.XX", bkpth) == -1) { ewprintf("Can't allocate temp file name : %s", strerror(errno)); free(nname); return (ABORT); } + free(bkpth); if ((from = open(fn, O_RDONLY)) == -1) { free(nname); @@ -610,4 +638,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.c7 Jun 2012 15:15:04 - 1.39 +++ funmap.c7 Jun 2012 17:38:26 - @@ -25,6 +25,7 @@ static struct funmap functnames[] = { {fillmode, "auto-fill-mode",}, {indentmode, "au