[project @ 1998-12-02 13:17:09 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.3 1998/12/02 13:27:41 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(fd, exclusive)
46 int fd;
47 int exclusive;
48 {
49     int i;
50     struct stat sb;
51
52     while (fstat(fd, &sb) < 0) {
53         if (errno != EINTR) {
54             return -1;
55         }
56     }
57
58     /* Only lock regular files */
59     if (!S_ISREG(sb.st_mode))
60         return 0;
61     
62     for (i = 0; i < writeLocks; i++)
63         if (writeLock[i].inode == sb.st_ino && writeLock[i].device == sb.st_dev) {
64             errno = EAGAIN;
65             return -1;
66         }
67
68     if (!exclusive) {
69         i = readLocks++;
70         readLock[i].device = sb.st_dev;
71         readLock[i].inode = sb.st_ino;
72         readLock[i].fd = fd;
73         return 0;
74     }
75
76     for (i = 0; i < readLocks; i++)
77         if (readLock[i].inode == sb.st_ino && readLock[i].device == sb.st_dev) {
78             errno = EAGAIN;
79             return -1;
80         }           
81
82     i = writeLocks++;
83     writeLock[i].device = sb.st_dev;
84     writeLock[i].inode = sb.st_ino;
85     writeLock[i].fd = fd;
86     return 0;
87 }
88
89 int
90 unlockFile(fd)
91 int fd;
92 {
93     int i, rc;
94
95     for (i = 0; i < readLocks; i++)
96         if (readLock[i].fd == fd) {
97             while (++i < readLocks)
98                 readLock[i - 1] = readLock[i];
99             readLocks--;
100             return 0;
101         }
102
103     for (i = 0; i < writeLocks; i++)
104         if (writeLock[i].fd == fd) {
105             while (++i < writeLocks)
106                 writeLock[i - 1] = writeLock[i];
107             writeLocks--;
108             return 0;
109         }
110      /* Signal that we did not find an entry */
111     return 1;
112 }
113
114 StgInt
115 getLock(fd, exclusive)
116 StgInt fd;
117 StgInt exclusive;
118 {
119     if (lockFile(fd, exclusive) < 0) {
120         if (errno == EBADF)
121             return 0;
122         else {
123             cvtErrno();
124             switch (ghc_errno) {
125             default:
126                 stdErrno();
127                 break;
128             case GHC_EACCES:
129             case GHC_EAGAIN:
130                 ghc_errtype = ERR_RESOURCEBUSY;
131                 ghc_errstr = "file is locked";
132                 break;
133             }
134             /* Not so sure we want to do this, since getLock() 
135             is only called on the standard file descriptors.. */
136             /*(void) close(fd); */
137             return -1;
138         }
139     }
140     return 1;
141 }