[project @ 2005-03-14 15:57:57 by simonmar]
[ghc-base.git] / cbits / lockFile.c
1 /*
2  * (c) The GRASP/AQUA Project, Glasgow University, 1994-2004
3  *
4  * $Id: lockFile.c,v 1.5 2005/01/28 13:36:32 simonmar Exp $
5  *
6  * stdin/stout/stderr Runtime Support
7  */
8
9 #ifndef mingw32_HOST_OS
10
11 #include "HsBase.h"
12 #include "Rts.h"
13 #include "../../ghc/rts/RtsUtils.h" // for barf()
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     if (fd > FD_SETSIZE) {
34         barf("lockFile: fd out of range");
35     }
36
37     while (fstat(fd, &sb) < 0) {
38         if (errno != EINTR)
39             return -1;
40     }
41
42     if (for_writing) {
43       /* opening a file for writing, check to see whether
44          we don't have any read locks on it already.. */
45       for (i = 0; i < readLocks; i++) {
46          if (readLock[i].inode == sb.st_ino && readLock[i].device == sb.st_dev)
47             return -1;
48       }
49       /* If we're determined that there is only a single
50          writer to the file, check to see whether the file
51          hasn't already been opened for writing..
52       */
53       if (exclusive) {
54         for (i = 0; i < writeLocks; i++) {
55           if (writeLock[i].inode == sb.st_ino && writeLock[i].device == sb.st_dev) {
56              return -1;
57           }
58         }
59       }
60       /* OK, everything is cool lock-wise, record it and leave. */
61       i = writeLocks++;
62       writeLock[i].device = sb.st_dev;
63       writeLock[i].inode = sb.st_ino;
64       writeLock[i].fd = fd;
65       return 0;
66     } else {
67       /* For reading, it's simpler - just check to see
68          that there's no-one writing to the underlying file. */
69       for (i = 0; i < writeLocks; i++) {
70         if (writeLock[i].inode == sb.st_ino && writeLock[i].device == sb.st_dev)
71              return -1;
72       }
73       /* Fit in new entry, reusing an existing table entry, if possible. */
74       for (i = 0; i < readLocks; i++) {
75          if (readLock[i].inode == sb.st_ino && readLock[i].device == sb.st_dev) {
76            return 0;
77          }
78       }
79       i = readLocks++;
80       readLock[i].device = sb.st_dev;
81       readLock[i].inode = sb.st_ino;
82       readLock[i].fd = fd;
83       return 0;
84     }
85
86 }
87
88 int
89 unlockFile(int fd)
90 {
91     int i;
92
93     for (i = 0; i < readLocks; i++)
94         if (readLock[i].fd == fd) {
95             while (++i < readLocks)
96                 readLock[i - 1] = readLock[i];
97             readLocks--;
98             return 0;
99         }
100
101     for (i = 0; i < writeLocks; i++)
102         if (writeLock[i].fd == fd) {
103             while (++i < writeLocks)
104                 writeLock[i - 1] = writeLock[i];
105             writeLocks--;
106             return 0;
107         }
108      /* Signal that we did not find an entry */
109     return 1;
110 }
111
112 #endif