/*
* (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
*/
static int writeLocks = 0;
int
-lockFile(fd, exclusive)
+lockFile(fd, for_writing, exclusive)
int fd;
+int for_writing;
int exclusive;
{
int i;
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
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 {
/*
* (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
*/
#include <fcntl.h>
#endif
+#ifdef mingw32_TARGET_OS
+#define O_NOCTTY 0
+#endif
+
IOFileObject*
openStdFile(fd,flags,rd)
StgInt fd;
FILE *fp;
int fd;
int oflags;
- int exclusive;
+ int for_writing;
int created = 0;
struct stat sb;
IOFileObject* fo;
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);
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) {
}
/* 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:
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:
/*
* (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.
*/
StgAddr getDirectoryContents (StgByteArray);
/* getLock.c */
-int lockFile (int, int);
+int lockFile (int, int, int);
int unlockFile (int);
StgInt getLock (StgInt, StgInt);