summaryrefslogtreecommitdiff
path: root/src/lib/libcoshell/cosync.c
diff options
context:
space:
mode:
authorIgor Pashev <pashev.igor@gmail.com>2012-06-24 22:28:35 +0000
committerIgor Pashev <pashev.igor@gmail.com>2012-06-24 22:28:35 +0000
commit3950ffe2a485479f6561c27364d3d7df5a21d124 (patch)
tree468c6e14449d1b1e279222ec32f676b0311917d2 /src/lib/libcoshell/cosync.c
downloadksh-3950ffe2a485479f6561c27364d3d7df5a21d124.tar.gz
Imported Upstream version 93u+upstream
Diffstat (limited to 'src/lib/libcoshell/cosync.c')
-rw-r--r--src/lib/libcoshell/cosync.c127
1 files changed, 127 insertions, 0 deletions
diff --git a/src/lib/libcoshell/cosync.c b/src/lib/libcoshell/cosync.c
new file mode 100644
index 0000000..4439efa
--- /dev/null
+++ b/src/lib/libcoshell/cosync.c
@@ -0,0 +1,127 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1990-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Research
+ *
+ * sync all outstanding file operations for file opened on fd
+ * if file==0 then fd used
+ * if fd<0 then file used
+ * if mode<0 then fd not created
+ *
+ * NOTE: this is an unfortunate NFS workaround that should be done by fsync()
+ */
+
+#include "colib.h"
+
+#include <ls.h>
+
+#include "FEATURE/nfsd"
+
+int
+cosync(Coshell_t* co, const char* file, int fd, int mode)
+{
+#if defined(_cmd_nfsd)
+ if (!co || (co->flags & CO_SERVER))
+ {
+ char tmp[PATH_MAX];
+
+ if (file && *file)
+ {
+ register const char* s;
+ register char* t;
+ register char* b;
+ int td;
+
+ /*
+ * writing to a dir apparently flushes the
+ * attribute cache for all entries in the dir
+ */
+
+ s = file;
+ b = t = tmp;
+ while (t < &tmp[sizeof(tmp) - 1])
+ {
+ if (!(*t = *s++)) break;
+ if (*t++ == '/') b = t;
+ }
+ s = "..nfs..botch..";
+ t = b;
+ while (t < &tmp[sizeof(tmp) - 1] && (*t++ = *s++));
+ *t = 0;
+ if ((td = open(tmp, O_WRONLY|O_CREAT|O_TRUNC, 0)) >= 0) close(td);
+ unlink(tmp);
+ if (fd >= 0 && mode >= 0)
+ {
+ if ((td = open(file, mode)) < 0) return(-1);
+ close(fd);
+ dup2(td, fd);
+ close(td);
+ }
+ }
+#if defined(F_SETLK)
+ else
+ {
+ int clean = 0;
+ struct flock lock;
+
+ if (fd < 0)
+ {
+ if (!file || mode < 0 || (fd = open(file, O_RDONLY)) < 0) return(-1);
+ clean = 1;
+ }
+
+ /*
+ * this sets the VNOCACHE flag across NFS
+ */
+
+ lock.l_type = F_RDLCK;
+ lock.l_whence = 0;
+ lock.l_start = 0;
+ lock.l_len = 1;
+ if (!fcntl(fd, F_SETLK, &lock))
+ {
+ lock.l_type = F_UNLCK;
+ fcntl(fd, F_SETLK, &lock);
+ }
+ if (clean) close(fd);
+
+ /*
+ * 4.1 has a bug that lets VNOCACHE linger after unlock
+ * VNOCACHE inhibits mapping which kills exec
+ * the double rename flushes the incore vnode (and VNOCACHE)
+ *
+ * this kind of stuff doesn't happen with *real* file systems
+ */
+
+ if (file && *file)
+ {
+ strcpy(tmp, file);
+ fd = strlen(tmp) - 1;
+ tmp[fd] = (tmp[fd] == '*') ? '?' : '*';
+ if (!rename(file, tmp)) rename(tmp, file);
+ }
+ }
+#endif
+ }
+#endif
+ return(0);
+}