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