summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--contrib/nvi/common/exf.c29
1 files changed, 29 insertions, 0 deletions
diff --git a/contrib/nvi/common/exf.c b/contrib/nvi/common/exf.c
index 57f5748..8c4dea5 100644
--- a/contrib/nvi/common/exf.c
+++ b/contrib/nvi/common/exf.c
@@ -837,10 +837,39 @@ file_write(sp, fm, tm, name, flags)
SIGBLOCK;
if ((fd = open(name, oflags,
S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH)) < 0) {
+ if (errno == EACCES && LF_ISSET(FS_FORCE)) {
+ /*
+ * If the user owns the file but does not
+ * have write permission on it, grant it
+ * automatically for the duration of the
+ * opening of the file, if possible.
+ */
+ struct stat sb;
+ mode_t fmode;
+
+ if (stat(name, &sb) != 0)
+ goto fail_open;
+ fmode = sb.st_mode;
+ if (!(sb.st_mode & S_IWUSR) && sb.st_uid == getuid())
+ fmode |= S_IWUSR;
+ else
+ goto fail_open;
+ if (chmod(name, fmode) != 0)
+ goto fail_open;
+ fd = open(name, oflags, S_IRUSR | S_IWUSR |
+ S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
+ if (fd == -1)
+ goto fail_open;
+ (void)fchmod(fd, sb.st_mode);
+ goto success_open;
+ fail_open:
+ errno = EACCES;
+ }
msgq_str(sp, M_SYSERR, name, "%s");
SIGUNBLOCK;
return (1);
}
+success_open:
SIGUNBLOCK;
/* Try and get a lock. */
OpenPOWER on IntegriCloud