[project @ 1998-04-10 10:54:14 by simonm]
[ghc-hetmet.git] / ghc / lib / std / cbits / getLock.c
1 /* 
2  * (c) The GRASP/AQUA Project, Glasgow University, 1994-1998
3  *
4  * $Id: getLock.c,v 1.1 1998/04/10 10:54:39 simonm Exp $
5  *
6  * stdin/stout/stderr Runtime Support
7  */
8
9 #include "Rts.h"
10 #include "stgio.h"
11
12 #ifdef HAVE_SYS_TYPES_H
13 #include <sys/types.h>
14 #endif
15
16 #ifdef HAVE_SYS_STAT_H
17 #include <sys/stat.h>
18 #endif
19
20 #ifdef HAVE_UNISTD_H
21 #include <unistd.h>
22 #endif
23
24 #ifdef HAVE_FCNTL_H
25 #include <fcntl.h>
26 #endif
27
28 #ifndef FD_SETSIZE
29 #define FD_SETSIZE 256
30 #endif
31
32 typedef struct {
33     dev_t device;
34     ino_t inode;
35     int fd;
36 } Lock;
37
38 static Lock readLock[FD_SETSIZE];
39 static Lock writeLock[FD_SETSIZE];
40
41 static int readLocks = 0;
42 static int writeLocks = 0;
43
44 int
45 lockFile(int fd, int exclusive)
46 {
47     int i;
48     struct stat sb;
49
50     while (fstat(fd, &sb) < 0) {
51         if (errno != EINTR) {
52             return -1;
53         }
54     }
55
56     /* Only lock regular files */
57     if (!S_ISREG(sb.st_mode))
58         return 0;
59     
60     for (i = 0; i < writeLocks; i++)
61         if (writeLock[i].inode == sb.st_ino && writeLock[i].device == sb.st_dev) {
62             errno = EAGAIN;
63             return -1;
64         }
65
66     if (!exclusive) {
67         i = readLocks++;
68         readLock[i].device = sb.st_dev;
69         readLock[i].inode = sb.st_ino;
70         readLock[i].fd = fd;
71         return 0;
72     }
73
74     for (i = 0; i < readLocks; i++)
75         if (readLock[i].inode == sb.st_ino && readLock[i].device == sb.st_dev) {
76             errno = EAGAIN;
77             return -1;
78         }           
79
80     i = writeLocks++;
81     writeLock[i].device = sb.st_dev;
82     writeLock[i].inode = sb.st_ino;
83     writeLock[i].fd = fd;
84     return 0;
85 }
86
87 int
88 unlockFile(int fd)
89 {
90     int i, rc;
91
92     for (i = 0; i < readLocks; i++)
93         if (readLock[i].fd == fd) {
94             while (++i < readLocks)
95                 readLock[i - 1] = readLock[i];
96             readLocks--;
97             return 0;
98         }
99
100     for (i = 0; i < writeLocks; i++)
101         if (writeLock[i].fd == fd) {
102             while (++i < writeLocks)
103                 writeLock[i - 1] = writeLock[i];
104             writeLocks--;
105             return 0;
106         }
107      /* Signal that we did not find an entry */
108     return 1;
109 }
110
111 StgInt
112 getLock(StgAddr fp, StgInt exclusive)
113 {
114     if (lockFile(fileno((FILE *) fp), exclusive) < 0) {
115         if (errno == EBADF)
116             return 0;
117         else {
118             cvtErrno();
119             switch (ghc_errno) {
120             default:
121                 stdErrno();
122                 break;
123             case GHC_EACCES:
124             case GHC_EAGAIN:
125                 ghc_errtype = ERR_RESOURCEBUSY;
126                 ghc_errstr = "file is locked";
127                 break;
128             }
129             (void) fclose((FILE *) fp);
130             return -1;
131         }
132     }
133     return 1;
134 }
135