0ffad7d5ea5ecb10efdce44047f823b06d5bb60d
[haskell-directory.git] / cbits / lockFile.c
1 /* 
2  * (c) The GRASP/AQUA Project, Glasgow University, 1994-1998
3  *
4  * $Id: lockFile.c,v 1.1 2001/06/28 14:15:04 simonmar Exp $
5  *
6  * stdin/stout/stderr Runtime Support
7  */
8
9 #include "HsCore.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 }