diff --git a/ghc/lib/std/cbits/getLock.c b/ghc/lib/std/cbits/getLock.c index a0d93adf7f3a82c18bd1466f3df1336b1b2c911c..be6acb46f1593eb44e5d5e934765bae9dc742738 100644 --- a/ghc/lib/std/cbits/getLock.c +++ b/ghc/lib/std/cbits/getLock.c @@ -1,7 +1,7 @@ /* * (c) The GRASP/AQUA Project, Glasgow University, 1994-1998 * - * $Id: getLock.c,v 1.3 1998/12/02 13:27:41 simonm Exp $ + * $Id: getLock.c,v 1.4 1999/02/04 12:13:15 sof Exp $ * * stdin/stout/stderr Runtime Support */ @@ -42,8 +42,9 @@ static int readLocks = 0; static int writeLocks = 0; int -lockFile(fd, exclusive) +lockFile(fd, for_writing, exclusive) int fd; +int for_writing; int exclusive; { int i; @@ -59,31 +60,55 @@ int exclusive; if (!S_ISREG(sb.st_mode)) return 0; - for (i = 0; i < writeLocks; i++) - if (writeLock[i].inode == sb.st_ino && writeLock[i].device == sb.st_dev) { + if (for_writing) { + /* opening a file for writing, check to see whether + we don't have any read locks on it already.. */ + for (i = 0; i < readLocks; i++) { + if (readLock[i].inode == sb.st_ino && readLock[i].device == sb.st_dev) { errno = EAGAIN; return -1; - } - - if (!exclusive) { - i = readLocks++; - readLock[i].device = sb.st_dev; - readLock[i].inode = sb.st_ino; - readLock[i].fd = fd; - return 0; - } - - for (i = 0; i < readLocks; i++) - if (readLock[i].inode == sb.st_ino && readLock[i].device == sb.st_dev) { + } + } + /* If we're determined that there is only a single + writer to the file, check to see whether the file + hasn't already been opened for writing.. + */ + if (exclusive) { + for (i = 0; i < writeLocks; i++) { + if (writeLock[i].inode == sb.st_ino && writeLock[i].device == sb.st_dev) { + errno = EAGAIN; + return -1; + } + } + } + /* OK, everything is cool lock-wise, record it and leave. */ + i = writeLocks++; + writeLock[i].device = sb.st_dev; + writeLock[i].inode = sb.st_ino; + writeLock[i].fd = fd; + return 0; + } else { + /* For reading, it's simpler - just check to see + that there's no-one writing to the underlying file. */ + for (i = 0; i < writeLocks; i++) { + if (writeLock[i].inode == sb.st_ino && writeLock[i].device == sb.st_dev) { errno = EAGAIN; return -1; - } + } + } + /* Fit in new entry, reusing an existing table entry, if possible. */ + for (i = 0; i < readLocks; i++) { + if (readLock[i].inode == sb.st_ino && readLock[i].device == sb.st_dev) { + return 0; + } + } + i = readLocks++; + readLock[i].device = sb.st_dev; + readLock[i].inode = sb.st_ino; + readLock[i].fd = fd; + return 0; + } - i = writeLocks++; - writeLock[i].device = sb.st_dev; - writeLock[i].inode = sb.st_ino; - writeLock[i].fd = fd; - return 0; } int @@ -111,12 +136,13 @@ int fd; return 1; } +/* getLock() is used when opening the standard file descriptors */ StgInt -getLock(fd, exclusive) +getLock(fd, for_writing) StgInt fd; -StgInt exclusive; +StgInt for_writing; { - if (lockFile(fd, exclusive) < 0) { + if (lockFile(fd, for_writing, 0) < 0) { if (errno == EBADF) return 0; else { diff --git a/ghc/lib/std/cbits/openFile.c b/ghc/lib/std/cbits/openFile.c index 2d5afe516b53ff3b59fc40977a7ea36b0592338b..7d3b217ad2f3fbc4001b42794b2ce5b577423862 100644 --- a/ghc/lib/std/cbits/openFile.c +++ b/ghc/lib/std/cbits/openFile.c @@ -1,7 +1,7 @@ /* * (c) The GRASP/AQUA Project, Glasgow University, 1994-1998 * - * $Id: openFile.c,v 1.5 1999/01/23 17:44:40 sof Exp $ + * $Id: openFile.c,v 1.6 1999/02/04 12:13:15 sof Exp $ * * openFile Runtime Support */ @@ -29,6 +29,10 @@ #include <fcntl.h> #endif +#ifdef mingw32_TARGET_OS +#define O_NOCTTY 0 +#endif + IOFileObject* openStdFile(fd,flags,rd) StgInt fd; @@ -63,7 +67,7 @@ StgInt flags; FILE *fp; int fd; int oflags; - int exclusive; + int for_writing; int created = 0; struct stat sb; IOFileObject* fo; @@ -76,19 +80,19 @@ StgInt flags; switch (how) { case OPENFILE_APPEND: oflags = O_WRONLY | O_NOCTTY | O_APPEND; - exclusive = 1; + for_writing = 1; break; case OPENFILE_WRITE: oflags = O_WRONLY | O_NOCTTY; - exclusive = 1; + for_writing = 1; break; case OPENFILE_READ_ONLY: oflags = O_RDONLY | O_NOCTTY; - exclusive = 0; + for_writing = 0; break; case OPENFILE_READ_WRITE: oflags = O_RDWR | O_NOCTTY; - exclusive = 0; + for_writing = 1; break; default: fprintf(stderr, "openFile: unknown mode `%d'\n", how); @@ -110,12 +114,14 @@ StgInt flags; return NULL; } else { /* If it is a dangling symlink, break off now, too. */ +#ifndef mingw32_TARGET_OS struct stat st; if ( lstat(file,&st) == 0) { ghc_errtype = ERR_NOSUCHTHING; ghc_errstr = "dangling symlink"; return NULL; } +#endif } /* Now try to create it */ while ((fd = open(file, oflags | O_CREAT | O_EXCL, 0666)) < 0) { @@ -186,7 +192,7 @@ StgInt flags; } /* Use our own personal locking */ - if (lockFile(fd, exclusive) < 0) { + if (lockFile(fd, for_writing, 1/*enforce single-writer, if needs be.*/) < 0) { cvtErrno(); switch (ghc_errno) { default: @@ -268,11 +274,13 @@ StgInt fd; StgInt oflags; StgInt flags; { - int exclusive; + int for_writing; FILE* fp; IOFileObject* fo; - if (lockFile(fd, exclusive) < 0) { + for_writing = ( ((oflags & O_WRONLY) || (oflags & O_RDWR)) ? 1 : 0); + + if (lockFile(fd, for_writing, 1/* enforce single-writer */ ) < 0) { cvtErrno(); switch (ghc_errno) { default: diff --git a/ghc/lib/std/cbits/stgio.h b/ghc/lib/std/cbits/stgio.h index 68a097974feee0f753acd153c289ff871815f63e..9631807e1bfe8bca8a3f6c878d1ab124807c156b 100644 --- a/ghc/lib/std/cbits/stgio.h +++ b/ghc/lib/std/cbits/stgio.h @@ -1,7 +1,7 @@ /* * (c) The GRASP/AQUA Project, Glasgow University, 1994-1998 * - * $Id: stgio.h,v 1.9 1999/01/15 17:54:23 sof Exp $ + * $Id: stgio.h,v 1.10 1999/02/04 12:13:16 sof Exp $ * * Helper code for GHC's IO subsystem. */ @@ -146,7 +146,7 @@ StgAddr getCurrentDirectory(void); StgAddr getDirectoryContents (StgByteArray); /* getLock.c */ -int lockFile (int, int); +int lockFile (int, int, int); int unlockFile (int); StgInt getLock (StgInt, StgInt);