1
2 /*-
3 *
4 * New BSD License 2006
5 *
6 * Copyright (c) 2006, Jorgen Lundman
7 * All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions are
11 * met:
12 *
13 * 1 Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2 Redistributions in binary form must reproduce the above
16 * copyright notice, this list of conditions and the following
17 * disclaimer in the documentation and/or other materials provided
18 * with the distribution.
19 * 3 Neither the name of the stuff nor the names of its contributors
20 * may be used to endorse or promote products derived from this
21 * software without specific prior written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
26 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
27 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
28 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
29 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
30 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
31 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
33 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34 *
35 */
36
37 // $Id: file.c,v 1.13 2006/06/30 01:22:58 lundman Exp $
38 // File IO functions for the lion library
39 // Jorgen Lundman January 8th, 2003.
40
41
42 // Universal system headers
43
44 #ifndef WIN32
45
46 #include <stdio.h>
47 #include <stdlib.h>
48 #include <sys/types.h>
49 #include <errno.h>
50 #include <signal.h>
51
52 #include <unistd.h>
53
54 #include <fcntl.h> // for locking
55
56
57
58 #ifdef __sun__
59 extern const char *const sys_errlist[];
60 #endif
61
62
63
64 // Implementation specific headers
65
66 #include "connections.h"
67 #include "io.h"
68 #include "sockets.h"
69
70 #include "lion.h"
71
72
73
74
75 __RCSID("$LiON: lundman/lion/file.c,v 1.13 2006/06/30 01:22:58 lundman Exp $");
76
77
78
lion_open(char * file,int flags,mode_t modes,int lion_flags,void * user_data)79 connection_t *lion_open(char *file, int flags, mode_t modes,
80 int lion_flags, void *user_data)
81 {
82 connection_t *newd;
83
84 // This breaks FULLFILL, but then, passing NULL breaks lion API.
85 if (!file)
86 return NULL;
87
88 newd = connections_new();
89
90 newd->type = LION_TYPE_FILE;
91 newd->user_data = user_data;
92
93 if (lion_flags & LION_FLAG_TRACE)
94 lion_enable_trace(newd);
95
96 if (newd->trace)
97 fprintf(trace_file, "%p: lion_open (%s)\n",newd, file);
98
99 // Open the file, if issues, send event.
100
101 if (lion_flags & LION_FLAG_EXCLUSIVE) {
102
103
104
105 // They want exclusive, so lets step through the various ways this
106 // can be done, in descending order of preference.
107 // FYI, NetBSD has all of these, which made it easier to test.
108
109 #ifdef O_EXLOCK
110
111 newd->socket = open( file, flags | O_EXLOCK | O_NONBLOCK, modes );
112
113 #elif defined LOCK_EX
114
115 newd->socket = open( file, flags, modes );
116
117 if (newd->socket >= 0) {
118 if (flock(newd->socket, LOCK_EX|LOCK_NB)) {
119 close(newd->socket);
120 newd->socket = -1;
121 }
122 }
123
124 #elif defined F_SETLK
125
126 {
127 struct flock locker;
128
129 locker.l_start = 0; // offset from whence
130 locker.l_len = 0; // whole file
131 locker.l_pid = getpid(); // don't actually care
132 locker.l_type = F_WRLCK;
133 locker.l_whence= 0; // start of file.
134
135 newd->socket = open( file, flags, modes );
136
137 if (newd->socket >= 0) {
138
139 if (fcntl( newd->socket, F_SETLK, &locker) == -1) {
140
141 close(newd->socket);
142 newd->socket = -1;
143
144 }
145 }
146 }
147
148 #elif defined F_TLOCK // advisory only, but atleast we can stop within lion.
149
150 newd->socket = open( file, flags, modes );
151
152 if (newd->socket >= 0) {
153
154 if ( lockf( newd->socket, F_TLOCK, 0) == -1) {
155
156 close(newd->socket);
157 newd->socket = -1;
158
159 }
160 }
161
162
163 #endif // which locking type
164
165
166 // Phew no exclusive, just open.
167
168 } else {
169
170 newd->socket = open( file, flags, modes );
171
172 }
173
174 #ifdef DEBUG
175 if (newd->socket < 0)
176 perror("open");
177 printf("net_open(%s): %d\n", file, newd->socket);
178 #endif
179
180 if (newd->socket < 0) {
181
182 if (lion_flags & LION_FLAG_FULFILL) {
183
184 // Signal above layer of failure
185 newd->status = ST_PENDING;
186
187 io_force_loop = 1;
188 return newd;
189 }
190
191 newd->status = ST_DISCONNECT;
192
193 return NULL;
194 }
195
196
197 // File was opened ok, set nonblocking.
198 // Technically not needed if the first locking method exist.
199
200 // In Unix, we can just use the same method as sockets
201 //fcntl(newd->socket,F_SETFL,(fcntl(newd->socket,F_GETFL)|O_NONBLOCK));
202 newd->socket = sockets_setnonblocking(newd->socket);
203
204
205 // printf("[file] file %d is nonblocking %d\n", newd->socket,
206 // fcntl(newd->socket, F_GETFL) & O_NONBLOCK);
207
208
209 // We're done, tell application its ready.
210 // Race condition here, we can signal app that it is CONNECTED but
211 // since we've not returned the handle, the client will get rather
212 // confused.
213
214 newd->status = ST_PENDING;
215
216 return newd;
217
218 }
219
220
221
222
223 #endif
224