summaryrefslogtreecommitdiff
path: root/usr.bin/mg
diff options
context:
space:
mode:
Diffstat (limited to 'usr.bin/mg')
-rw-r--r--usr.bin/mg/buffer.c34
-rw-r--r--usr.bin/mg/def.h9
-rw-r--r--usr.bin/mg/file.c13
-rw-r--r--usr.bin/mg/fileio.c66
-rw-r--r--usr.bin/mg/line.c24
-rw-r--r--usr.bin/mg/region.c8
-rw-r--r--usr.bin/mg/sysdef.h3
-rw-r--r--usr.bin/mg/tty.c7
-rw-r--r--usr.bin/mg/word.c20
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);