1/*********************************************************************** 2* * 3* This software is part of the ast package * 4* Copyright (c) 1990-2012 AT&T Intellectual Property * 5* and is licensed under the * 6* Eclipse Public License, Version 1.0 * 7* by AT&T Intellectual Property * 8* * 9* A copy of the License is available at * 10* http://www.eclipse.org/org/documents/epl-v10.html * 11* (with md5 checksum b35adb5213ca9657e911e9befb180842) * 12* * 13* Information and Software Systems Research * 14* AT&T Research * 15* Florham Park NJ * 16* * 17* Glenn Fowler <gsf@research.att.com> * 18* * 19***********************************************************************/ 20#pragma prototyped 21/* 22 * Glenn Fowler 23 * AT&T Research 24 * 25 * sync all outstanding file operations for file opened on fd 26 * if file==0 then fd used 27 * if fd<0 then file used 28 * if mode<0 then fd not created 29 * 30 * NOTE: this is an unfortunate NFS workaround that should be done by fsync() 31 */ 32 33#include "colib.h" 34 35#include <ls.h> 36 37#include "FEATURE/nfsd" 38 39int 40cosync(Coshell_t* co, const char* file, int fd, int mode) 41{ 42#if defined(_cmd_nfsd) 43 if (!co || (co->flags & CO_SERVER)) 44 { 45 char tmp[PATH_MAX]; 46 47 if (file && *file) 48 { 49 register const char* s; 50 register char* t; 51 register char* b; 52 int td; 53 54 /* 55 * writing to a dir apparently flushes the 56 * attribute cache for all entries in the dir 57 */ 58 59 s = file; 60 b = t = tmp; 61 while (t < &tmp[sizeof(tmp) - 1]) 62 { 63 if (!(*t = *s++)) break; 64 if (*t++ == '/') b = t; 65 } 66 s = "..nfs..botch.."; 67 t = b; 68 while (t < &tmp[sizeof(tmp) - 1] && (*t++ = *s++)); 69 *t = 0; 70 if ((td = open(tmp, O_WRONLY|O_CREAT|O_TRUNC|O_cloexec, 0)) >= 0) 71 close(td); 72 unlink(tmp); 73 if (fd >= 0 && mode >= 0) 74 { 75 if ((td = open(file, mode|O_cloexec)) < 0) 76 return(-1); 77 close(fd); 78 dup2(td, fd); 79 close(td); 80 } 81 } 82#if defined(F_SETLK) 83 else 84 { 85 int clean = 0; 86 struct flock lock; 87 88 if (fd < 0) 89 { 90 if (!file || mode < 0 || (fd = open(file, O_RDONLY|O_cloexec)) < 0) return(-1); 91 clean = 1; 92 } 93 94 /* 95 * this sets the VNOCACHE flag across NFS 96 */ 97 98 lock.l_type = F_RDLCK; 99 lock.l_whence = 0; 100 lock.l_start = 0; 101 lock.l_len = 1; 102 if (!fcntl(fd, F_SETLK, &lock)) 103 { 104 lock.l_type = F_UNLCK; 105 fcntl(fd, F_SETLK, &lock); 106 } 107 if (clean) close(fd); 108 109 /* 110 * 4.1 has a bug that lets VNOCACHE linger after unlock 111 * VNOCACHE inhibits mapping which kills exec 112 * the double rename flushes the incore vnode (and VNOCACHE) 113 * 114 * this kind of stuff doesn't happen with *real* file systems 115 */ 116 117 if (file && *file) 118 { 119 strcpy(tmp, file); 120 fd = strlen(tmp) - 1; 121 tmp[fd] = (tmp[fd] == '*') ? '?' : '*'; 122 if (!rename(file, tmp)) rename(tmp, file); 123 } 124 } 125#endif 126 } 127#endif 128 return(0); 129} 130