[project @ 1996-01-08 20:28:12 by partain]
[ghc-hetmet.git] / ghc / runtime / io / 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 void
89 unlockFile(fd)
90 int fd;
91 {
92     int i;
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;
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;
108         }
109 }
110
111 StgInt
112 getLock(fp, exclusive)
113 StgAddr fp;
114 StgInt exclusive;
115 {
116     if (lockFile(fileno((FILE *) fp), exclusive) < 0) {
117         if (errno == EBADF)
118             return 0;
119         else {
120             cvtErrno();
121             switch (ghc_errno) {
122             default:
123                 stdErrno();
124                 break;
125             case GHC_EACCES:
126             case GHC_EAGAIN:
127                 ghc_errtype = ERR_RESOURCEBUSY;
128                 ghc_errstr = "file is locked";
129                 break;
130             }
131             (void) fclose((FILE *) fp);
132             return -1;
133         }
134     }
135     return 1;
136 }
137
138 \end{code}