|
|
1 | /* |
|
|
2 | * Copyright (c) 2012 Marc Alexander Lehmann <schmorp@schmorp.de> |
|
|
3 | * |
|
|
4 | * Redistribution and use in source and binary forms, with or without modifica- |
|
|
5 | * tion, are permitted provided that the following conditions are met: |
|
|
6 | * |
|
|
7 | * 1. Redistributions of source code must retain the above copyright notice, |
|
|
8 | * this list of conditions and the following disclaimer. |
|
|
9 | * |
|
|
10 | * 2. Redistributions in binary form must reproduce the above copyright |
|
|
11 | * notice, this list of conditions and the following disclaimer in the |
|
|
12 | * documentation and/or other materials provided with the distribution. |
|
|
13 | * |
|
|
14 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED |
|
|
15 | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MER- |
|
|
16 | * CHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO |
|
|
17 | * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPE- |
|
|
18 | * CIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
|
|
19 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; |
|
|
20 | * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, |
|
|
21 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTH- |
|
|
22 | * ERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED |
|
|
23 | * OF THE POSSIBILITY OF SUCH DAMAGE. |
|
|
24 | * |
|
|
25 | * Alternatively, the contents of this file may be used under the terms of |
|
|
26 | * the GNU General Public License ("GPL") version 2 or any later version, |
|
|
27 | * in which case the provisions of the GPL are applicable instead of |
|
|
28 | * the above. If you wish to allow the use of your version of this file |
|
|
29 | * only under the terms of the GPL and not to allow others to use your |
|
|
30 | * version of this file under the BSD license, indicate your decision |
|
|
31 | * by deleting the provisions above and replace them with the notice |
|
|
32 | * and other provisions required by the GPL. If you do not delete the |
|
|
33 | * provisions above, a recipient may use your version of this file under |
|
|
34 | * either the BSD or the GPL. |
|
|
35 | */ |
|
|
36 | |
1 | #include "urlib.h" |
37 | #include "urlib.h" |
2 | |
38 | |
3 | #include <fcntl.h> |
39 | #include <fcntl.h> |
|
|
40 | #include <stdio.h> |
|
|
41 | #include <string.h> |
|
|
42 | #include <stdlib.h> |
4 | |
43 | |
5 | #ifdef _WIN32 |
44 | #ifdef _WIN32 |
6 | |
45 | |
7 | #include <windows.h> |
46 | #include <windows.h> |
8 | //#include <winbase.h> |
47 | //#include <winbase.h> |
… | |
… | |
18 | |
57 | |
19 | #define u_setenv(name,value) SetEnvironmentVariable (name, value) |
58 | #define u_setenv(name,value) SetEnvironmentVariable (name, value) |
20 | #define u_mkdir(path) !CreateDirectory (path, NULL) |
59 | #define u_mkdir(path) !CreateDirectory (path, NULL) |
21 | #define u_chdir(path) !SetCurrentDirectory (path) |
60 | #define u_chdir(path) !SetCurrentDirectory (path) |
22 | #define u_rename(fr,to) !MoveFile (fr, to) |
61 | #define u_rename(fr,to) !MoveFile (fr, to) |
23 | #define u_open(path) CreateFile (path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL) |
62 | #define u_open(path) CreateFile (path, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL) |
24 | #define u_creat(path,exec) CreateFile (path, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL) |
63 | #define u_creat(path,exec) CreateFile (path, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL) |
25 | #define u_creat(path,exec) CreateFile (path, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL) |
64 | #define u_creat(path,exec) CreateFile (path, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL) |
26 | #define u_close(handle) CloseHandle (handle) |
65 | #define u_close(handle) CloseHandle (handle) |
27 | #define u_append(path,add) PathAppend (path, add) |
66 | #define u_append(path,add) PathAppend (path, add) |
28 | #define u_write(handle,data,len) (WriteFile (handle, data, len, &dword, 0) ? dword : -1) |
67 | #define u_write(handle,data,len) (WriteFile (handle, data, len, &dword, 0) ? dword : -1) |
29 | |
68 | |
30 | #define u_fsync(handle) FlushFileBuffers (handle) |
69 | #define u_fsync(handle) FlushFileBuffers (handle) |
31 | #define u_sync() |
70 | #define u_sync() |
32 | |
71 | |
33 | #define u_lockfile(path) CreateFile (path, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL) |
72 | #define u_lockfile(path) CreateFile (path, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL) |
34 | #define u_cloexec(handle) |
73 | #define u_cloexec(handle) |
35 | |
74 | |
36 | #else |
75 | #else |
37 | |
76 | |
38 | #define _GNU_SOURCE 1 |
77 | #define _GNU_SOURCE 1 |
… | |
… | |
79 | #endif |
118 | #endif |
80 | |
119 | |
81 | #define u_16(ptr) (((ptr)[0] << 8) | (ptr)[1]) |
120 | #define u_16(ptr) (((ptr)[0] << 8) | (ptr)[1]) |
82 | #define u_32(ptr) (((ptr)[0] << 24) | ((ptr)[1] << 16) | ((ptr)[2] << 8) | (ptr)[3]) |
121 | #define u_32(ptr) (((ptr)[0] << 24) | ((ptr)[1] << 16) | ((ptr)[2] << 8) | (ptr)[3]) |
83 | |
122 | |
|
|
123 | static char currdir[MAX_PATH]; |
|
|
124 | static char datadir[MAX_PATH]; // %AppData%/urlader |
|
|
125 | static char exe_dir[MAX_PATH]; // %AppData%/urlader/EXE_ID |
|
|
126 | static char execdir[MAX_PATH]; // %AppData%/urlader/EXE_ID/EXE_VER |
|
|
127 | static char exe_id[MAX_PATH]; |
|
|
128 | static char exe_ver[MAX_PATH]; |
|
|
129 | |
|
|
130 | ///////////////////////////////////////////////////////////////////////////// |
|
|
131 | |
|
|
132 | static void |
|
|
133 | u_fatal (const char *msg) |
|
|
134 | { |
|
|
135 | #ifdef _WIN32 |
|
|
136 | MessageBox (0, msg, URLADER, 0); |
|
|
137 | #else |
|
|
138 | write (2, URLADER ": ", sizeof (URLADER ": ") - 1); |
|
|
139 | write (2, msg, strlen (msg)); |
|
|
140 | write (2, "\n", 1); |
|
|
141 | #endif |
|
|
142 | |
|
|
143 | _exit (1); |
|
|
144 | } |
|
|
145 | |
84 | static void * |
146 | static void * |
85 | u_malloc (unsigned int size) |
147 | u_malloc (unsigned int size) |
86 | { |
148 | { |
87 | void *addr; |
149 | void *addr; |
88 | |
150 | |
89 | #ifdef _WIN32 |
151 | if (!size) |
90 | HANDLE handle = CreateFileMapping (0, 0, PAGE_READWRITE, 0, size, NULL); |
|
|
91 | |
|
|
92 | if (!handle) |
|
|
93 | return 0; |
152 | return 0; |
94 | |
153 | |
|
|
154 | #ifdef _WIN32 |
|
|
155 | { |
|
|
156 | HANDLE handle = CreateFileMapping (0, 0, PAGE_READWRITE, 0, size, NULL); |
|
|
157 | |
|
|
158 | addr = 0; |
|
|
159 | if (handle) |
|
|
160 | { |
95 | addr = MapViewOfFile (handle, FILE_MAP_WRITE, 0, 0, size); |
161 | addr = MapViewOfFile (handle, FILE_MAP_WRITE, 0, 0, size); |
96 | |
|
|
97 | CloseHandle (handle); |
162 | CloseHandle (handle); |
|
|
163 | } |
|
|
164 | } |
98 | #elif defined (MAP_ANONYMOUS) |
165 | #elif defined (MAP_ANONYMOUS) |
99 | addr = mmap (0, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0); |
166 | addr = mmap (0, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0); |
100 | |
167 | |
101 | if (addr == (void *)-1) |
168 | if (addr == (void *)-1) |
102 | addr = 0; |
169 | addr = 0; |
103 | #else |
170 | #else |
104 | addr = malloc (size); |
171 | addr = malloc (size); |
105 | #endif |
172 | #endif |
106 | |
173 | |
|
|
174 | if (!addr) |
|
|
175 | u_fatal ("memory allocation failure, aborting."); |
|
|
176 | |
107 | return addr; |
177 | return addr; |
108 | } |
178 | } |
109 | |
179 | |
110 | static void |
180 | static void |
111 | u_free (void *addr, unsigned int size) |
181 | u_free (void *addr, unsigned int size) |
112 | { |
182 | { |
|
|
183 | if (!addr) |
|
|
184 | return; |
|
|
185 | |
113 | #ifdef _WIN32 |
186 | #ifdef _WIN32 |
114 | UnmapViewOfFile (addr); |
187 | UnmapViewOfFile (addr); |
115 | #elif defined (MAP_ANONYMOUS) |
188 | #elif defined (MAP_ANONYMOUS) |
116 | munmap (addr, size); |
189 | munmap (addr, size); |
117 | #else |
190 | #else |
118 | free (addr); |
191 | free (addr); |
119 | #endif |
192 | #endif |
120 | } |
193 | } |
121 | |
194 | |
122 | static void * |
195 | static void * |
|
|
196 | u_realloc (void *addr, unsigned int old_size, unsigned int new_size) |
|
|
197 | { |
|
|
198 | void *addr2 = u_malloc (new_size); |
|
|
199 | memcpy (addr2, addr, (new_size < old_size ? new_size : old_size)); |
|
|
200 | u_free (addr, old_size); |
|
|
201 | |
|
|
202 | return addr2; |
|
|
203 | } |
|
|
204 | |
|
|
205 | static void * |
123 | u_mmap (u_handle h, unsigned int size) |
206 | u_mmap (u_handle h, unsigned int size) |
124 | { |
207 | { |
125 | void *addr; |
208 | void *addr; |
126 | |
209 | |
127 | #ifdef _WIN32 |
210 | #ifdef _WIN32 |
… | |
… | |
150 | UnmapViewOfFile (addr); |
233 | UnmapViewOfFile (addr); |
151 | #else |
234 | #else |
152 | munmap (addr, len); |
235 | munmap (addr, len); |
153 | #endif |
236 | #endif |
154 | } |
237 | } |
|
|
238 | |
|
|
239 | ///////////////////////////////////////////////////////////////////////////// |
|
|
240 | |
|
|
241 | typedef struct |
|
|
242 | { |
|
|
243 | char *addr; |
|
|
244 | unsigned int used; |
|
|
245 | unsigned int size; |
|
|
246 | } u_dynbuf; |
|
|
247 | |
|
|
248 | static void * |
|
|
249 | u_dynbuf_append (u_dynbuf *dynbuf, void *data, unsigned int len) |
|
|
250 | { |
|
|
251 | char *dest; |
|
|
252 | |
|
|
253 | if ((dynbuf->used += len) > dynbuf->size) |
|
|
254 | { |
|
|
255 | unsigned int new_size = dynbuf->size ? dynbuf->size * 2 : 4096; |
|
|
256 | dynbuf->addr = u_realloc (dynbuf->addr, dynbuf->size, new_size); |
|
|
257 | dynbuf->size = new_size; |
|
|
258 | } |
|
|
259 | |
|
|
260 | dest = dynbuf->addr + dynbuf->used - len; |
|
|
261 | |
|
|
262 | if (data) |
|
|
263 | memcpy (dest, data, len); |
|
|
264 | |
|
|
265 | return dest; |
|
|
266 | } |
|
|
267 | |
|
|
268 | ///////////////////////////////////////////////////////////////////////////// |
|
|
269 | |
|
|
270 | static void |
|
|
271 | u_set_datadir (void) |
|
|
272 | { |
|
|
273 | #ifdef _WIN32 |
|
|
274 | if (SHGetFolderPath (0, CSIDL_APPDATA | CSIDL_FLAG_CREATE, NULL, SHGFP_TYPE_CURRENT, datadir) != S_OK) |
|
|
275 | u_fatal ("unable to find application data directory"); |
|
|
276 | |
|
|
277 | u_mkdir (datadir); |
|
|
278 | u_append (datadir, URLADER); |
|
|
279 | |
|
|
280 | #else |
|
|
281 | char *home = getenv ("HOME"); |
|
|
282 | |
|
|
283 | if (!home) |
|
|
284 | { |
|
|
285 | struct passwd *pw; |
|
|
286 | |
|
|
287 | if ((pw = getpwuid (getuid ()))) |
|
|
288 | home = pw->pw_dir; |
|
|
289 | else |
|
|
290 | home = "/tmp"; |
|
|
291 | } |
|
|
292 | |
|
|
293 | u_mkdir (home); |
|
|
294 | //strcat (strcat (strcpy (datadir, home), "/."), URLADER); |
|
|
295 | sprintf (datadir, "%s/.%s", home, URLADER); |
|
|
296 | #endif |
|
|
297 | |
|
|
298 | u_setenv ("URLADER_DATADIR", datadir); |
|
|
299 | } |
|
|
300 | |
|
|
301 | static void |
|
|
302 | u_set_exe_info (void) |
|
|
303 | { |
|
|
304 | strcpy (exe_dir, datadir); |
|
|
305 | u_append (exe_dir, exe_id); |
|
|
306 | u_mkdir (exe_dir); |
|
|
307 | |
|
|
308 | strcpy (execdir, exe_dir); |
|
|
309 | u_append (execdir, "i-"); |
|
|
310 | strcat (execdir, exe_ver); |
|
|
311 | |
|
|
312 | u_setenv ("URLADER_EXECDIR", execdir); |
|
|
313 | u_setenv ("URLADER_EXE_ID" , exe_id); |
|
|
314 | u_setenv ("URLADER_EXE_DIR", exe_dir); |
|
|
315 | u_setenv ("URLADER_EXE_VER", exe_ver); |
|
|
316 | } |
|
|
317 | |
|
|
318 | ///////////////////////////////////////////////////////////////////////////// |
|
|
319 | |
155 | static u_handle |
320 | static u_handle |
156 | u_lock (const char *path, int excl, int dowait) |
321 | u_lock (const char *path, int excl, int dowait) |
157 | { |
322 | { |
158 | u_handle h; |
323 | u_handle h; |
159 | |
324 | |
… | |
… | |
192 | |
357 | |
193 | // we have the lock, now verify that the lockfile still exists |
358 | // we have the lock, now verify that the lockfile still exists |
194 | |
359 | |
195 | #ifdef _WIN32 |
360 | #ifdef _WIN32 |
196 | // apparently, we have to open the file to get its info :( |
361 | // apparently, we have to open the file to get its info :( |
|
|
362 | { |
197 | BY_HANDLE_FILE_INFORMATION s1, s2; |
363 | BY_HANDLE_FILE_INFORMATION s1, s2; |
198 | u_handle h2 = u_lockfile (path); |
364 | u_handle h2 = u_lockfile (path); |
199 | if (!u_valid (h)) |
365 | if (!u_valid (h)) |
200 | break; |
366 | break; |
201 | |
367 | |
202 | success = GetFileInformationByHandle (h, &s1) |
368 | success = GetFileInformationByHandle (h, &s1) |
203 | && GetFileInformationByHandle (h2, &s2); |
369 | && GetFileInformationByHandle (h2, &s2); |
204 | |
370 | |
205 | u_close (h2); |
371 | u_close (h2); |
206 | |
372 | |
207 | if (!success) |
373 | if (!success) |
208 | break; |
374 | break; |
209 | |
375 | |
210 | success = s1.dwVolumeSerialNumber == s2.dwVolumeSerialNumber |
376 | success = s1.dwVolumeSerialNumber == s2.dwVolumeSerialNumber |
211 | && s1.nFileIndexHigh == s2.nFileIndexHigh |
377 | && s1.nFileIndexHigh == s2.nFileIndexHigh |
212 | && s1.nFileIndexLow == s2.nFileIndexLow; |
378 | && s1.nFileIndexLow == s2.nFileIndexLow; |
|
|
379 | } |
213 | #else |
380 | #else |
214 | struct stat s1, s2; |
381 | struct stat s1, s2; |
215 | |
382 | |
216 | if (fstat (h, &s1) || stat (path, &s2)) |
383 | if (fstat (h, &s1) || stat (path, &s2)) |
217 | break; |
384 | break; |