diff options
Diffstat (limited to 'usr.bin/mg')
-rw-r--r-- | usr.bin/mg/buffer.c | 34 | ||||
-rw-r--r-- | usr.bin/mg/def.h | 9 | ||||
-rw-r--r-- | usr.bin/mg/file.c | 13 | ||||
-rw-r--r-- | usr.bin/mg/fileio.c | 66 | ||||
-rw-r--r-- | usr.bin/mg/line.c | 24 | ||||
-rw-r--r-- | usr.bin/mg/region.c | 8 | ||||
-rw-r--r-- | usr.bin/mg/sysdef.h | 3 | ||||
-rw-r--r-- | usr.bin/mg/tty.c | 7 | ||||
-rw-r--r-- | usr.bin/mg/word.c | 20 |
9 files changed, 160 insertions, 24 deletions
diff --git a/usr.bin/mg/buffer.c b/usr.bin/mg/buffer.c index 9d7b89e3af0..64761e58106 100644 --- a/usr.bin/mg/buffer.c +++ b/usr.bin/mg/buffer.c @@ -1,4 +1,4 @@ -/* $OpenBSD: buffer.c,v 1.67 2007/05/28 17:52:17 kjell Exp $ */ +/* $OpenBSD: buffer.c,v 1.68 2008/09/15 16:11:35 kjell Exp $ */ /* This file is in the public domain. */ @@ -22,10 +22,14 @@ extern int globalwd; int togglereadonly(int f, int n) { + int s; + + if ((s = checkdirty(curbp)) != TRUE) + return (s); if (!(curbp->b_flag & BFREADONLY)) curbp->b_flag |= BFREADONLY; else { - curbp->b_flag &=~ BFREADONLY; + curbp->b_flag &= ~BFREADONLY; if (curbp->b_flag & BFCHG) ewprintf("Warning: Buffer was modified"); } @@ -572,7 +576,7 @@ bclear(struct buffer *bp) /* * Display the given buffer in the given window. Flags indicated - * action on redisplay. + * action on redisplay. Update modified flag so insert loop can check it. */ int showbuffer(struct buffer *bp, struct mgwin *wp, int flags) @@ -580,6 +584,10 @@ showbuffer(struct buffer *bp, struct mgwin *wp, int flags) struct buffer *obp; struct mgwin *owp; + /* Ensure file has not been modified elsewhere */ + if (fchecktime(bp) != TRUE) + bp->b_flag |= BFDIRTY; + if (wp->w_bufp == bp) { /* Easy case! */ wp->w_flag |= flags; wp->w_dotp = bp->b_dotp; @@ -798,3 +806,23 @@ error: return (FALSE); } +/* + * Ensures a buffer has not been modified elsewhere. + * Returns TRUE if it has NOT. FALSE or ABORT otherwise + */ +int +checkdirty(struct buffer *bp) +{ + int s; + + if ((bp->b_flag & (BFDIRTY | BFIGNDIRTY)) == BFDIRTY) { + if ((s = eyorn("File changed on disk; really edit the buffer")) + != TRUE) + return (s); + bp->b_flag &= ~BFDIRTY; + bp->b_flag |= BFIGNDIRTY; + } + + return (TRUE); +} + diff --git a/usr.bin/mg/def.h b/usr.bin/mg/def.h index f26d46a2505..542a07c084e 100644 --- a/usr.bin/mg/def.h +++ b/usr.bin/mg/def.h @@ -1,4 +1,4 @@ -/* $OpenBSD: def.h,v 1.106 2008/06/14 08:39:30 kjell Exp $ */ +/* $OpenBSD: def.h,v 1.107 2008/09/15 16:11:35 kjell Exp $ */ /* This file is in the public domain. */ @@ -272,7 +272,8 @@ struct buffer { #endif #define BFOVERWRITE 0x08 /* overwrite mode */ #define BFREADONLY 0x10 /* read only mode */ - +#define BFDIRTY 0x20 /* Buffer was modified elsewhere */ +#define BFIGNDIRTY 0x40 /* Ignore modifications */ /* * This structure holds information about recent actions for the Undo command. */ @@ -404,6 +405,7 @@ int usebuffer(int, int); int notmodified(int, int); int popbuftop(struct buffer *); int getbufcwd(char *, size_t); +int checkdirty(struct buffer *); /* display.c */ int vtresize(int, int, int); @@ -424,6 +426,7 @@ void free_file_list(struct list *); /* fileio.c */ int ffropen(const char *, struct buffer *); +void ffstat(struct buffer *); int ffwopen(const char *, struct buffer *); int ffclose(struct buffer *); int ffputbuf(struct buffer *); @@ -434,6 +437,8 @@ char *startupfile(char *); int copy(char *, char *); struct list *make_file_list(char *); int fisdir(const char *); +int fchecktime(struct buffer *); +int fupdstat(struct buffer *); /* kbd.c X */ int do_meta(int, int); diff --git a/usr.bin/mg/file.c b/usr.bin/mg/file.c index cf4b744de35..6f3f87f7d78 100644 --- a/usr.bin/mg/file.c +++ b/usr.bin/mg/file.c @@ -1,4 +1,4 @@ -/* $OpenBSD: file.c,v 1.67 2008/06/18 17:13:53 kjell Exp $ */ +/* $OpenBSD: file.c,v 1.68 2008/09/15 16:11:35 kjell Exp $ */ /* This file is in the public domain. */ @@ -212,7 +212,7 @@ readin(char *fname) if (bclear(curbp) != TRUE) return (TRUE); /* Clear readonly. May be set by autoexec path */ - curbp->b_flag &=~ BFREADONLY; + curbp->b_flag &= ~BFREADONLY; if ((status = insertfile(fname, fname, TRUE)) != TRUE) { ewprintf("File is not readable: %s", fname); return (FALSE); @@ -566,6 +566,14 @@ buffsave(struct buffer *bp) return (FALSE); } + /* Ensure file has not been modified elsewhere */ + /* We don't use the ignore flag here */ + if (fchecktime(bp) != TRUE) { + if ((s = eyesno("File has changed on disk since last save. " + "Save anyway")) != TRUE) + return (s); + } + if (makebackup && (bp->b_flag & BFBAK)) { s = fbackupfile(bp->b_fname); /* hard error */ @@ -632,6 +640,7 @@ writeout(struct buffer *bp, char *fn) } else /* ignore close error if it is a write error */ (void)ffclose(bp); + (void)fupdstat(bp); return (s == FIOSUC); } diff --git a/usr.bin/mg/fileio.c b/usr.bin/mg/fileio.c index 2f6e8f56856..1f4c40c8fdb 100644 --- a/usr.bin/mg/fileio.c +++ b/usr.bin/mg/fileio.c @@ -1,4 +1,4 @@ -/* $OpenBSD: fileio.c,v 1.81 2007/11/27 16:22:14 martynas Exp $ */ +/* $OpenBSD: fileio.c,v 1.82 2008/09/15 16:11:35 kjell Exp $ */ /* This file is in the public domain. */ @@ -8,8 +8,8 @@ #include "def.h" -#include <sys/stat.h> #include <sys/types.h> +#include <sys/stat.h> #include <sys/time.h> #include <sys/resource.h> #include <sys/wait.h> @@ -31,8 +31,6 @@ static FILE *ffp; int ffropen(const char *fn, struct buffer *bp) { - struct stat statbuf; - if ((ffp = fopen(fn, "r")) == NULL) { if (errno == ENOENT) return (FIOFNF); @@ -43,13 +41,44 @@ ffropen(const char *fn, struct buffer *bp) if (fisdir(fn) == TRUE) return (FIODIR); - if (bp && fstat(fileno(ffp), &statbuf) == 0) { + ffstat(bp); + + return (FIOSUC); +} + +/* + * Update stat/dirty info + */ +void +ffstat(struct buffer *bp) +{ + struct stat sb; + + if (bp && fstat(fileno(ffp), &sb) == 0) { /* set highorder bit to make sure this isn't all zero */ - bp->b_fi.fi_mode = statbuf.st_mode | 0x8000; - bp->b_fi.fi_uid = statbuf.st_uid; - bp->b_fi.fi_gid = statbuf.st_gid; + bp->b_fi.fi_mode = sb.st_mode | 0x8000; + bp->b_fi.fi_uid = sb.st_uid; + bp->b_fi.fi_gid = sb.st_gid; + bp->b_fi.fi_mtime = sb.st_mtimespec; + /* Clear the ignore flag */ + bp->b_flag &= ~(BFIGNDIRTY | BFDIRTY); } +} +/* + * Update the status/dirty info. If there is an error, + * there's not a lot we can do. + */ +int +fupdstat(struct buffer *bp) +{ + if ((ffp = fopen(bp->b_fname, "r")) == NULL) { + if (errno == ENOENT) + return (FIOFNF); + return (FIOERR); + } + ffstat(bp); + ffclose(bp); return (FIOSUC); } @@ -559,3 +588,24 @@ fisdir(const char *fname) return (FALSE); } + +/* + * Check the mtime of the supplied filename. + * Return TRUE if last mtime matches, FALSE if not, + * If the stat fails, return TRUE and try the save anyway + */ +int +fchecktime(struct buffer *bp) +{ + struct stat sb; + + if (stat(bp->b_fname, &sb) == -1) + return (TRUE); + + if (bp->b_fi.fi_mtime.tv_sec != sb.st_mtimespec.tv_sec || + bp->b_fi.fi_mtime.tv_nsec != sb.st_mtimespec.tv_nsec) + return (FALSE); + + return (TRUE); + +} diff --git a/usr.bin/mg/line.c b/usr.bin/mg/line.c index ac600887381..4d0565e0afe 100644 --- a/usr.bin/mg/line.c +++ b/usr.bin/mg/line.c @@ -1,4 +1,4 @@ -/* $OpenBSD: line.c,v 1.44 2006/12/24 01:20:53 kjell Exp $ */ +/* $OpenBSD: line.c,v 1.45 2008/09/15 16:11:35 kjell Exp $ */ /* This file is in the public domain. */ @@ -142,7 +142,10 @@ linsert_str(const char *s, int n) struct line *lp1; struct mgwin *wp; RSIZE i; - int doto; + int doto, k; + + if ((k = checkdirty(curbp)) != TRUE) + return (k); if (curbp->b_flag & BFREADONLY) { ewprintf("Buffer is read only"); @@ -233,10 +236,14 @@ linsert(int n, int c) struct mgwin *wp; RSIZE i; int doto; + int s; if (!n) return (TRUE); + if ((s = checkdirty(curbp)) != TRUE) + return (s); + if (curbp->b_flag & BFREADONLY) { ewprintf("Buffer is read only"); return (FALSE); @@ -388,6 +395,10 @@ lnewline_at(struct line *lp1, int doto) int lnewline(void) { + int s; + + if ((s = checkdirty(curbp)) != TRUE) + return (s); if (curbp->b_flag & BFREADONLY) { ewprintf("Buffer is read only"); return (FALSE); @@ -414,7 +425,10 @@ ldelete(RSIZE n, int kflag) size_t len; char *sv; int end; + int s; + if ((s = checkdirty(curbp)) != TRUE) + return (s); if (curbp->b_flag & BFREADONLY) { ewprintf("Buffer is read only"); return (FALSE); @@ -497,7 +511,10 @@ ldelnewline(void) { struct line *lp1, *lp2, *lp3; struct mgwin *wp; + int s; + if ((s = checkdirty(curbp)) != TRUE) + return (s); if (curbp->b_flag & BFREADONLY) { ewprintf("Buffer is read only"); return (FALSE); @@ -571,7 +588,10 @@ int lreplace(RSIZE plen, char *st) { RSIZE rlen; /* replacement length */ + int s; + if ((s = checkdirty(curbp)) != TRUE) + return (s); if (curbp->b_flag & BFREADONLY) { ewprintf("Buffer is read only"); return (FALSE); diff --git a/usr.bin/mg/region.c b/usr.bin/mg/region.c index 751f63fea7f..78555084453 100644 --- a/usr.bin/mg/region.c +++ b/usr.bin/mg/region.c @@ -1,4 +1,4 @@ -/* $OpenBSD: region.c,v 1.26 2008/06/10 23:23:53 kjell Exp $ */ +/* $OpenBSD: region.c,v 1.27 2008/09/15 16:11:35 kjell Exp $ */ /* This file is in the public domain. */ @@ -98,6 +98,8 @@ lowerregion(int f, int n) struct region region; int loffs, c, s; + if ((s = checkdirty(curbp)) != TRUE) + return (s); if (curbp->b_flag & BFREADONLY) { ewprintf("Buffer is read-only"); return (FALSE); @@ -139,6 +141,8 @@ upperregion(int f, int n) struct region region; int loffs, c, s; + if ((s = checkdirty(curbp)) != TRUE) + return (s); if (curbp->b_flag & BFREADONLY) { ewprintf("Buffer is read-only"); return (FALSE); @@ -261,6 +265,8 @@ prefixregion(int f, int n) int nline; int s; + if ((s = checkdirty(curbp)) != TRUE) + return (s); if (curbp->b_flag & BFREADONLY) { ewprintf("Buffer is read-only"); return (FALSE); diff --git a/usr.bin/mg/sysdef.h b/usr.bin/mg/sysdef.h index 4df4e805a8c..6b7561442b3 100644 --- a/usr.bin/mg/sysdef.h +++ b/usr.bin/mg/sysdef.h @@ -1,4 +1,4 @@ -/* $OpenBSD: sysdef.h,v 1.15 2006/08/01 22:16:03 jason Exp $ */ +/* $OpenBSD: sysdef.h,v 1.16 2008/09/15 16:11:35 kjell Exp $ */ /* This file is in the public domain. */ @@ -26,4 +26,5 @@ struct fileinfo { uid_t fi_uid; gid_t fi_gid; mode_t fi_mode; + struct timespec fi_mtime; /* Last modified time */ }; diff --git a/usr.bin/mg/tty.c b/usr.bin/mg/tty.c index 49169052153..f803cc7a7ed 100644 --- a/usr.bin/mg/tty.c +++ b/usr.bin/mg/tty.c @@ -1,4 +1,4 @@ -/* $OpenBSD: tty.c,v 1.29 2008/06/11 00:03:49 tobias Exp $ */ +/* $OpenBSD: tty.c,v 1.30 2008/09/15 16:11:35 kjell Exp $ */ /* This file is in the public domain. */ @@ -127,6 +127,11 @@ ttinit(void) void ttreinit(void) { + /* check if file was modified while we were gone */ + if (fchecktime(curbp) != TRUE) { + curbp->b_flag |= BFDIRTY; + } + if (enter_ca_mode) /* enter application mode */ putpad(enter_ca_mode, 1); diff --git a/usr.bin/mg/word.c b/usr.bin/mg/word.c index 9489120f10a..c18b620e672 100644 --- a/usr.bin/mg/word.c +++ b/usr.bin/mg/word.c @@ -1,4 +1,4 @@ -/* $OpenBSD: word.c,v 1.14 2006/05/28 23:30:16 kjell Exp $ */ +/* $OpenBSD: word.c,v 1.15 2008/09/15 16:11:35 kjell Exp $ */ /* This file is in the public domain. */ @@ -68,9 +68,11 @@ forwword(int f, int n) int upperword(int f, int n) { - int c; + int c, s; RSIZE size; + if ((s = checkdirty(curbp)) != TRUE) + return (s); if (curbp->b_flag & BFREADONLY) { ewprintf("Buffer is read-only"); return (FALSE); @@ -108,9 +110,11 @@ upperword(int f, int n) int lowerword(int f, int n) { - int c; + int c, s; RSIZE size; + if ((s = checkdirty(curbp)) != TRUE) + return (s); if (curbp->b_flag & BFREADONLY) { ewprintf("Buffer is read-only"); return (FALSE); @@ -149,9 +153,11 @@ lowerword(int f, int n) int capword(int f, int n) { - int c; + int c, s; RSIZE size; + if ((s = checkdirty(curbp)) != TRUE) + return (s); if (curbp->b_flag & BFREADONLY) { ewprintf("Buffer is read-only"); return (FALSE); @@ -228,7 +234,10 @@ delfword(int f, int n) RSIZE size; struct line *dotp; int doto; + int s; + if ((s = checkdirty(curbp)) != TRUE) + return (s); if (curbp->b_flag & BFREADONLY) { ewprintf("Buffer is read-only"); return (FALSE); @@ -279,7 +288,10 @@ int delbword(int f, int n) { RSIZE size; + int s; + if ((s = checkdirty(curbp)) != TRUE) + return (s); if (curbp->b_flag & BFREADONLY) { ewprintf("Buffer is read-only"); return (FALSE); |