Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
att
GitHub Repository: att/ast
Path: blob/master/src/lib/libast/aso/aso-fcntl.c
1811 views
1
/***********************************************************************
2
* *
3
* This software is part of the ast package *
4
* Copyright (c) 1985-2012 AT&T Intellectual Property *
5
* and is licensed under the *
6
* Eclipse Public License, Version 1.0 *
7
* by AT&T Intellectual Property *
8
* *
9
* A copy of the License is available at *
10
* http://www.eclipse.org/org/documents/epl-v10.html *
11
* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
12
* *
13
* Information and Software Systems Research *
14
* AT&T Research *
15
* Florham Park NJ *
16
* *
17
* Glenn Fowler <[email protected]> *
18
* David Korn <[email protected]> *
19
* Phong Vo <[email protected]> *
20
* *
21
***********************************************************************/
22
#pragma prototyped
23
24
#include "asohdr.h"
25
26
#if defined(_UWIN) && defined(_BLD_ast) || !_aso_fcntl
27
28
NoN(aso_meth_fcntl)
29
30
#else
31
32
#include <sys/stat.h>
33
#include <fcntl.h>
34
#include <unistd.h>
35
36
typedef struct APL_s
37
{
38
int fd;
39
size_t size;
40
char path[1];
41
} APL_t;
42
43
static void*
44
aso_init_fcntl(void* data, const char* details)
45
{
46
APL_t* apl = (APL_t*)data;
47
char* path;
48
char* opt;
49
size_t size;
50
size_t references;
51
int n;
52
int fd;
53
int drop;
54
int perm;
55
struct flock lock;
56
char buf[PATH_MAX];
57
char tmp[64];
58
59
if (apl)
60
{
61
lock.l_type = F_WRLCK;
62
lock.l_whence = SEEK_SET;
63
lock.l_start = apl->size;
64
lock.l_len = sizeof(references);
65
if (fcntl(apl->fd, F_SETLKW, &lock) >= 0)
66
{
67
if (lseek(apl->fd, apl->size, SEEK_SET) != apl->size)
68
references = 0;
69
else if (read(apl->fd, &references, sizeof(references)) != sizeof(references))
70
references = 0;
71
else if (references > 0)
72
{
73
references--;
74
if (lseek(apl->fd, apl->size, SEEK_SET) != apl->size)
75
references = 0;
76
else if (write(apl->fd, &references, sizeof(references)) != sizeof(references))
77
references = 0;
78
}
79
lock.l_type = F_UNLCK;
80
fcntl(apl->fd, F_SETLK, &lock);
81
if (!references)
82
remove(apl->path);
83
}
84
close(apl->fd);
85
free(apl);
86
return 0;
87
}
88
fd = -1;
89
perm = S_IRUSR|S_IWUSR;
90
drop = 0;
91
size = 32 * 1024 - sizeof(references);
92
if (path = (char*)details)
93
while (opt = strchr(path, ','))
94
{
95
if (strneq(path, "perm=", 5))
96
{
97
if ((n = opt - (path + 5)) >= sizeof(tmp))
98
n = sizeof(tmp) - 1;
99
memcpy(tmp, path + 5, n);
100
tmp[n] = 0;
101
perm = strperm(tmp, NiL, perm);
102
}
103
else if (strneq(path, "size=", 5))
104
{
105
size = strtoul(path + 5, NiL, 0);
106
if (size <= sizeof(references))
107
goto bad;
108
size -= sizeof(references);
109
}
110
path = opt + 1;
111
}
112
if (!path || !*path)
113
{
114
if (!(path = pathtemp(buf, sizeof(buf), NiL, "aso", &fd)))
115
return 0;
116
drop = 1;
117
}
118
if (!(apl = newof(0, APL_t, 1, strlen(path))))
119
goto bad;
120
if (fd >= 0 || (fd = open(path, O_RDWR|O_cloexec)) < 0 && (fd = open(path, O_CREAT|O_RDWR|O_cloexec, perm)) >= 0)
121
{
122
if (lseek(fd, size, SEEK_SET) != size)
123
goto bad;
124
references = 1;
125
if (write(fd, &references, sizeof(references)) != sizeof(references))
126
goto bad;
127
}
128
else
129
{
130
if ((size = lseek(fd, 0, SEEK_END)) <= sizeof(references))
131
goto bad;
132
size -= sizeof(references);
133
lock.l_type = F_WRLCK;
134
lock.l_whence = SEEK_SET;
135
lock.l_start = 0;
136
lock.l_len = sizeof(references);
137
if (fcntl(fd, F_SETLKW, &lock) < 0)
138
goto bad;
139
if (lseek(fd, size, SEEK_SET) != size)
140
goto bad;
141
if (read(fd, &references, sizeof(references)) != sizeof(references))
142
goto bad;
143
references++;
144
if (lseek(fd, size, SEEK_SET) != size)
145
goto bad;
146
if (write(fd, &references, sizeof(references)) != sizeof(references))
147
goto bad;
148
lock.l_type = F_UNLCK;
149
fcntl(fd, F_SETLK, &lock);
150
}
151
apl->fd = fd;
152
apl->size = size;
153
strcpy(apl->path, path);
154
return apl;
155
bad:
156
if (apl)
157
free(apl);
158
if (fd >= 0)
159
close(fd);
160
if (drop)
161
remove(path);
162
return 0;
163
}
164
165
static ssize_t
166
aso_lock_fcntl(void* data, ssize_t k, void volatile* p)
167
{
168
APL_t* apl = (APL_t*)data;
169
struct flock lock;
170
171
if (!apl)
172
return -1;
173
if (k > 0)
174
lock.l_type = F_UNLCK;
175
else
176
{
177
lock.l_type = F_WRLCK;
178
k = HASH(p, apl->size) + 1;
179
}
180
lock.l_whence = SEEK_SET;
181
lock.l_start = k - 1;
182
lock.l_len = 1;
183
return fcntl(apl->fd, F_SETLKW, &lock) < 0 ? -1 : k;
184
}
185
186
Asometh_t _aso_meth_fcntl = { "fcntl", ASO_PROCESS, aso_init_fcntl, aso_lock_fcntl };
187
188
#endif
189
190