--- Makefile.am | 4 - Makefile.in | 6 +- lib.c | 7 ++- mbox.c | 2 mh.c | 9 +++- mutt.h | 1 opennfs.c | 122 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ sendlib.c | 2 8 files changed, 144 insertions(+), 9 deletions(-) --- a/Makefile.am +++ b/Makefile.am @@ -23,7 +23,7 @@ mutt_SOURCES = $(BUILT_SOURCES) \ edit.c enter.c flags.c init.c filter.c from.c \ getdomain.c group.c \ handler.c hash.c hdrline.c headers.c help.c hook.c keymap.c \ - main.c mbox.c menu.c mh.c mx.c pager.c parse.c pattern.c \ + main.c mbox.c menu.c mh.c mx.c opennfs.c pager.c parse.c pattern.c \ postpone.c query.c recvattach.c recvcmd.c \ rfc822.c rfc1524.c rfc2047.c rfc2231.c rfc3676.c \ score.c send.c sendlib.c signal.c sort.c \ @@ -87,7 +87,7 @@ mutt_dotlock_SOURCES = mutt_dotlock.c mutt_dotlock_LDADD = @LIBOBJS@ mutt_dotlock_DEPENDENCIES = @LIBOBJS@ -pgpring_SOURCES = pgppubring.c pgplib.c lib.c extlib.c sha1.c md5.c pgppacket.c ascii.c +pgpring_SOURCES = pgppubring.c pgplib.c lib.c extlib.c sha1.c opennfs.c md5.c pgppacket.c ascii.c pgpring_LDADD = @LIBOBJS@ $(INTLLIBS) pgpring_DEPENDENCIES = @LIBOBJS@ $(INTLDEPS) --- a/Makefile.in +++ b/Makefile.in @@ -81,7 +81,7 @@ am_mutt_OBJECTS = $(am__objects_1) addrb group.$(OBJEXT) handler.$(OBJEXT) hash.$(OBJEXT) \ hdrline.$(OBJEXT) headers.$(OBJEXT) help.$(OBJEXT) \ hook.$(OBJEXT) keymap.$(OBJEXT) main.$(OBJEXT) mbox.$(OBJEXT) \ - menu.$(OBJEXT) mh.$(OBJEXT) mx.$(OBJEXT) pager.$(OBJEXT) \ + menu.$(OBJEXT) mh.$(OBJEXT) mx.$(OBJEXT) opennfs.$(OBJEXT) pager.$(OBJEXT) \ parse.$(OBJEXT) pattern.$(OBJEXT) postpone.$(OBJEXT) \ query.$(OBJEXT) recvattach.$(OBJEXT) recvcmd.$(OBJEXT) \ rfc822.$(OBJEXT) rfc1524.$(OBJEXT) rfc2047.$(OBJEXT) \ @@ -103,7 +103,7 @@ pgpewrap_LDADD = $(LDADD) pgpewrap_DEPENDENCIES = @LIBOBJS@ am_pgpring_OBJECTS = pgppubring.$(OBJEXT) pgplib.$(OBJEXT) \ lib.$(OBJEXT) extlib.$(OBJEXT) sha1.$(OBJEXT) md5.$(OBJEXT) \ - pgppacket.$(OBJEXT) ascii.$(OBJEXT) + pgppacket.$(OBJEXT) ascii.$(OBJEXT) opennfs.$(OBJEXT) pgpring_OBJECTS = $(am_pgpring_OBJECTS) binSCRIPT_INSTALL = $(INSTALL_SCRIPT) SCRIPTS = $(bin_SCRIPTS) @@ -308,7 +308,7 @@ mutt_SOURCES = $(BUILT_SOURCES) \ edit.c enter.c flags.c init.c filter.c from.c \ getdomain.c group.c \ handler.c hash.c hdrline.c headers.c help.c hook.c keymap.c \ - main.c mbox.c menu.c mh.c mx.c pager.c parse.c pattern.c \ + main.c mbox.c menu.c mh.c mx.c opennfs.c pager.c parse.c pattern.c \ postpone.c query.c recvattach.c recvcmd.c \ rfc822.c rfc1524.c rfc2047.c rfc2231.c rfc3676.c \ score.c send.c sendlib.c signal.c sort.c \ --- a/lib.c +++ b/lib.c @@ -48,6 +48,7 @@ #define EX_OK 0 #endif +#include "mutt.h" #include "lib.h" @@ -566,6 +567,10 @@ int safe_open (const char *path, int fla struct stat osb, nsb; int fd; +#if defined(__linux__) + if ((fd = opennfs (path, flags, 0600)) < 0) + return fd; +#else if (flags & O_EXCL) { char safe_file[_POSIX_PATH_MAX]; @@ -589,7 +594,7 @@ int safe_open (const char *path, int fla if ((fd = open (path, flags & ~O_EXCL, 0600)) < 0) return fd; - +#endif /* make sure the file is not symlink */ if (lstat (path, &osb) < 0 || fstat (fd, &nsb) < 0 || compare_stat(&osb, &nsb) == -1) --- a/mbox.c +++ b/mbox.c @@ -741,7 +741,7 @@ int mbox_sync_mailbox (CONTEXT *ctx, int /* Create a temporary file to write the new version of the mailbox in. */ mutt_mktemp (tempfile); - if ((i = open (tempfile, O_WRONLY | O_EXCL | O_CREAT, 0600)) == -1 || + if ((i = opennfs (tempfile, O_WRONLY | O_EXCL | O_CREAT, 0600)) == -1 || (fp = fdopen (i, "w")) == NULL) { if (-1 != i) --- a/mh.c +++ b/mh.c @@ -238,7 +238,11 @@ static int mh_mkstemp (CONTEXT * dest, F { snprintf (path, _POSIX_PATH_MAX, "%s/.mutt-%s-%d-%d", dest->path, NONULL (Hostname), (int) getpid (), Counter++); +#if defined(__linux__) + if ((fd = opennfs (path, O_WRONLY | O_EXCL | O_CREAT, 0600)) == -1) +#else if ((fd = open (path, O_WRONLY | O_EXCL | O_CREAT, 0666)) == -1) +#endif { if (errno != EEXIST) { @@ -1215,8 +1219,11 @@ int maildir_open_new_message (MESSAGE * dprint (2, (debugfile, "maildir_open_new_message (): Trying %s.\n", path)); - +#if defined(__linux__) + if ((fd = opennfs (path, O_WRONLY | O_EXCL | O_CREAT, 0600)) == -1) +#else if ((fd = open (path, O_WRONLY | O_EXCL | O_CREAT, 0666)) == -1) +#endif { if (errno != EEXIST) { --- a/mutt.h +++ b/mutt.h @@ -974,4 +974,5 @@ typedef struct #include "lib.h" #include "globals.h" +extern int opennfs(const char *, int, int); #endif /*MUTT_H*/ --- /dev/null +++ b/opennfs.c @@ -0,0 +1,122 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifndef NFS_SUPER_MAGIC +# define NFS_SUPER_MAGIC 0x6969 +#endif + +int opennfs(const char *path, int flags, int mode) +{ + char tmplock[NFS_MAXPATHLEN+1], sysname[256]; + char *slash, *ptr, *dir, *base, *clear = (char*)0; + struct stat ps, ts; + struct statfs fs; + ssize_t len; + int ret; + + if ((flags & (O_WRONLY|O_RDWR)) == 0) + goto safe; + + if ((flags & (O_EXCL|O_CREAT)) != (O_EXCL|O_CREAT)) + goto safe; + +#if defined(O_NOFOLLOW) + flags |= O_NOFOLLOW; +#endif + + ret = -1; + if ((clear = strdup(path)) == (char*)0) + goto err; + dir = dirname(clear); + + if ((ret = (statfs(dir, &fs))) < 0) + goto err; + + if (fs.f_type != NFS_SUPER_MAGIC) + goto safe; + + if ((ret = gethostname(sysname, sizeof(sysname))) < 0) + goto err; + + ret = -1; + ptr = &tmplock[0]; + if (((len = snprintf(ptr, NFS_MAXPATHLEN, "%s/.%s-XXXXXX", dir, sysname)) < 0) || (len >= NFS_MAXPATHLEN)) + goto err; + ptr += len; + slash = ptr; + + free(clear); + clear = (char*)0; + + if (mkdtemp(tmplock) == (char*)0) + goto err; + + ret = -1; + if ((clear = strdup(path)) == (char*)0) + goto rmd; + base = basename(clear); + + ret = -1; + if (((len = snprintf(ptr, NFS_MAXPATHLEN - len, "/%s", base)) < 0) || (len >= (NFS_MAXPATHLEN - len))) + goto rmd; + + free(clear); + clear = (char*)0; + + if ((ret = open(tmplock, flags, mode)) < 0) + goto rmd; + + errno = 0; + do { + len = write(ret, "0", 2); + } while ((len < 0) && (errno == EINTR)); + close(ret); + + ret = -1; + errno = EBADF; + if (len != 2) + goto unl; + + errno = 0; + if ((ret = lstat(tmplock, &ts)) < 0) + goto unl; + + if (((ret = link(tmplock, path)) < 0) && (errno == EEXIST)) + goto unl; + + if ((ret = lstat(path, &ps)) < 0) + goto unl; + + ret = -1; + errno = EEXIST; + if (ps.st_nlink != 2) + goto unl; + if ((ps.st_rdev != ts.st_rdev) || (ps.st_ino != ts.st_ino)) + goto unl; + + errno = 0; + flags |= O_TRUNC; + flags &= ~(O_EXCL|O_CREAT); + ret = open(path, flags, mode); +unl: + unlink(tmplock); +rmd: + *slash = '\0'; + rmdir(tmplock); +err: + if (clear) free(clear); + return ret; +safe: + if (clear) free(clear); + return open(path, flags, mode); +} --- a/sendlib.c +++ b/sendlib.c @@ -2030,7 +2030,7 @@ send_msg (const char *path, char **args, if (SendmailWait >= 0 && tempfile) { /* *tempfile will be opened as stdout */ - if (open (*tempfile, O_WRONLY | O_APPEND | O_CREAT | O_EXCL, 0600) < 0) + if (opennfs (*tempfile, O_WRONLY | O_CREAT | O_EXCL, 0600) < 0) _exit (S_ERR); /* redirect stderr to *tempfile too */ if (dup (1) < 0)