Commit c8f077d4 authored by sof's avatar sof

[project @ 1999-02-04 12:13:15 by sof]

- relax the restriction that just the one open writeable handle on
  *the same file* may exist when dealing with the standard handles,
  stdout and stderr.

  Reason: the following invocation of a Haskell program,

      foo >log 2>&1

  should be acceptable.
parent 6037e956
/*
* (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 {
......
/*
* (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:
......
/*
* (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);
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment