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