[project @ 2002-04-24 16:01:51 by simonmar]
[packages/random.git] / cbits / lockFile.c
1 /*
2 * (c) The GRASP/AQUA Project, Glasgow University, 1994-1998
3 *
4 * $Id: lockFile.c,v 1.2 2002/02/07 11:13:30 simonmar Exp $
5 *
6 * stdin/stout/stderr Runtime Support
7 */
8
9 #include "HsBase.h"
10
11 #ifndef FD_SETSIZE
12 #define FD_SETSIZE 256
13 #endif
14
15 typedef struct {
16 dev_t device;
17 ino_t inode;
18 int fd;
19 } Lock;
20
21 static Lock readLock[FD_SETSIZE];
22 static Lock writeLock[FD_SETSIZE];
23
24 static int readLocks = 0;
25 static int writeLocks = 0;
26
27 int
28 lockFile(int fd, int for_writing, int exclusive)
29 {
30 struct stat sb;
31 int i;
32
33 while (fstat(fd, &sb) < 0) {
34 if (errno != EINTR) {
35 #ifndef _WIN32
36 return -1;
37 #else
38 /* fstat()ing socket fd's seems to fail with CRT's fstat(),
39 so let's just silently return and hope for the best..
40 */
41 return 0;
42 #endif
43 }
44 }
45
46 if (for_writing) {
47 /* opening a file for writing, check to see whether
48 we don't have any read locks on it already.. */
49 for (i = 0; i < readLocks; i++) {
50 if (readLock[i].inode == sb.st_ino && readLock[i].device == sb.st_dev) {
51 #ifndef __MINGW32__
52 return -1;
53 #else
54 break;
55 #endif
56 }
57 }
58 /* If we're determined that there is only a single
59 writer to the file, check to see whether the file
60 hasn't already been opened for writing..
61 */
62 if (exclusive) {
63 for (i = 0; i < writeLocks; i++) {
64 if (writeLock[i].inode == sb.st_ino && writeLock[i].device == sb.st_dev) {
65 #ifndef __MINGW32__
66 return -1;
67 #else
68 break;
69 #endif
70 }
71 }
72 }
73 /* OK, everything is cool lock-wise, record it and leave. */
74 i = writeLocks++;
75 writeLock[i].device = sb.st_dev;
76 writeLock[i].inode = sb.st_ino;
77 writeLock[i].fd = fd;
78 return 0;
79 } else {
80 /* For reading, it's simpler - just check to see
81 that there's no-one writing to the underlying file. */
82 for (i = 0; i < writeLocks; i++) {
83 if (writeLock[i].inode == sb.st_ino && writeLock[i].device == sb.st_dev) {
84 #ifndef __MINGW32__
85 return -1;
86 #else
87 break;
88 #endif
89 }
90 }
91 /* Fit in new entry, reusing an existing table entry, if possible. */
92 for (i = 0; i < readLocks; i++) {
93 if (readLock[i].inode == sb.st_ino && readLock[i].device == sb.st_dev) {
94 return 0;
95 }
96 }
97 i = readLocks++;
98 readLock[i].device = sb.st_dev;
99 readLock[i].inode = sb.st_ino;
100 readLock[i].fd = fd;
101 return 0;
102 }
103
104 }
105
106 int
107 unlockFile(int fd)
108 {
109 int i;
110
111 for (i = 0; i < readLocks; i++)
112 if (readLock[i].fd == fd) {
113 while (++i < readLocks)
114 readLock[i - 1] = readLock[i];
115 readLocks--;
116 return 0;
117 }
118
119 for (i = 0; i < writeLocks; i++)
120 if (writeLock[i].fd == fd) {
121 while (++i < writeLocks)
122 writeLock[i - 1] = writeLock[i];
123 writeLocks--;
124 return 0;
125 }
126 /* Signal that we did not find an entry */
127 return 1;
128 }