1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143
|
/*
* (c) The GRASP/AQUA Project, Glasgow University, 1994-2004
*
* $Id: lockFile.c,v 1.3 2004/06/02 12:35:11 simonmar Exp $
*
* stdin/stout/stderr Runtime Support
*/
#include "HsBase.h"
#include "Rts.h"
#include "../../ghc/rts/RtsUtils.h" // for barf()
#ifdef mingw32_TARGET_OS
// The Win32 C runtime has a max of 2048 file descriptors (see
// _NHANDLE_ in the crt sources), but mingw defines FD_SETSIZE to
// 64.
# define NUM_FDS 2048
#else
# ifndef FD_SETSIZE
# error No FD_SETSIZE defined!
# else
# define NUM_FDS FD_SETSIZE
# endif
#endif
typedef struct {
dev_t device;
ino_t inode;
int fd;
} Lock;
static Lock readLock[NUM_FDS];
static Lock writeLock[NUM_FDS];
static int readLocks = 0;
static int writeLocks = 0;
int
lockFile(int fd, int for_writing, int exclusive)
{
struct stat sb;
int i;
if (fd > NUM_FDS) {
barf("lockFile: fd out of range");
}
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 (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__
return -1;
#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__
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__
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;
}
}
int
unlockFile(int fd)
{
int i;
for (i = 0; i < readLocks; i++)
if (readLock[i].fd == fd) {
while (++i < readLocks)
readLock[i - 1] = readLock[i];
readLocks--;
return 0;
}
for (i = 0; i < writeLocks; i++)
if (writeLock[i].fd == fd) {
while (++i < writeLocks)
writeLock[i - 1] = writeLock[i];
writeLocks--;
return 0;
}
/* Signal that we did not find an entry */
return 1;
}
|