/*
* (c) The GRASP/AQUA Project, Glasgow University, 1994-1998
*
- * $Id: getLock.c,v 1.1 1998/04/10 10:54:39 simonm Exp $
+ * $Id: getLock.c,v 1.8 2001/03/01 12:25:33 rrt Exp $
*
* stdin/stout/stderr Runtime Support
*/
static int writeLocks = 0;
int
-lockFile(int fd, int exclusive)
+lockFile(fd, for_writing, exclusive)
+int fd;
+int for_writing;
+int exclusive;
{
int i;
- struct stat sb;
+ struct Stat sb;
- while (fstat(fd, &sb) < 0) {
+ while (Fstat(fd, &sb) < 0) {
if (errno != EINTR) {
+#ifndef _WIN32
return -1;
+#else
+ /* fstat()ing socket fd's seems to fail with CRT's fstat(),
+ so let's just silently return and hope for the best..
+ */
+ return 0;
+#endif
}
}
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) {
+#ifndef __MINGW32__
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;
+#else
+ break;
+#endif
+ }
+ }
+ /* 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) {
+#ifndef __MINGW32__
+ errno = EAGAIN;
+ return -1;
+#else
+ break;
+#endif
+ }
+ }
+ }
+ /* 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) {
+#ifndef __MINGW32__
+ errno = EAGAIN;
+ return -1;
+#else
+ break;
+#endif
+ }
+ }
+ /* 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;
}
- for (i = 0; i < readLocks; i++)
- if (readLock[i].inode == sb.st_ino && readLock[i].device == sb.st_dev) {
- errno = EAGAIN;
- return -1;
- }
-
- i = writeLocks++;
- writeLock[i].device = sb.st_dev;
- writeLock[i].inode = sb.st_ino;
- writeLock[i].fd = fd;
- return 0;
}
int
-unlockFile(int fd)
+unlockFile(fd)
+int fd;
{
- int i, rc;
+ int i;
for (i = 0; i < readLocks; i++)
if (readLock[i].fd == fd) {
return 1;
}
+/* getLock() is used when opening the standard file descriptors */
StgInt
-getLock(StgAddr fp, StgInt exclusive)
+getLock(fd, for_writing)
+StgInt fd;
+StgInt for_writing;
{
- if (lockFile(fileno((FILE *) fp), exclusive) < 0) {
+ if (lockFile(fd, for_writing, 0) < 0) {
if (errno == EBADF)
return 0;
else {
ghc_errstr = "file is locked";
break;
}
- (void) fclose((FILE *) fp);
+ /* Not so sure we want to do this, since getLock()
+ is only called on the standard file descriptors.. */
+ /*(void) close(fd); */
return -1;
}
}
return 1;
}
-