1 |
root |
1.1 |
#include "urlib.h" |
2 |
|
|
|
3 |
|
|
#include <fcntl.h> |
4 |
root |
1.2 |
#include <stdio.h> |
5 |
|
|
#include <string.h> |
6 |
|
|
#include <stdlib.h> |
7 |
root |
1.1 |
|
8 |
|
|
#ifdef _WIN32 |
9 |
|
|
|
10 |
|
|
#include <windows.h> |
11 |
|
|
//#include <winbase.h> |
12 |
|
|
#include <shlobj.h> |
13 |
|
|
#include <shlwapi.h> |
14 |
|
|
#include <wininet.h> |
15 |
|
|
|
16 |
|
|
static DWORD dword; |
17 |
|
|
|
18 |
|
|
#define u_handle HANDLE |
19 |
|
|
#define u_invalid_handle 0 |
20 |
|
|
#define u_valid(handle) (!!handle) |
21 |
|
|
|
22 |
|
|
#define u_setenv(name,value) SetEnvironmentVariable (name, value) |
23 |
|
|
#define u_mkdir(path) !CreateDirectory (path, NULL) |
24 |
|
|
#define u_chdir(path) !SetCurrentDirectory (path) |
25 |
|
|
#define u_rename(fr,to) !MoveFile (fr, to) |
26 |
|
|
#define u_open(path) CreateFile (path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL) |
27 |
|
|
#define u_creat(path,exec) CreateFile (path, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL) |
28 |
|
|
#define u_creat(path,exec) CreateFile (path, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL) |
29 |
|
|
#define u_close(handle) CloseHandle (handle) |
30 |
|
|
#define u_append(path,add) PathAppend (path, add) |
31 |
|
|
#define u_write(handle,data,len) (WriteFile (handle, data, len, &dword, 0) ? dword : -1) |
32 |
|
|
|
33 |
|
|
#define u_fsync(handle) FlushFileBuffers (handle) |
34 |
|
|
#define u_sync() |
35 |
|
|
|
36 |
|
|
#define u_lockfile(path) CreateFile (path, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL) |
37 |
|
|
#define u_cloexec(handle) |
38 |
|
|
|
39 |
|
|
#else |
40 |
|
|
|
41 |
|
|
#define _GNU_SOURCE 1 |
42 |
|
|
#define _BSD_SOURCE 1 |
43 |
|
|
// the above increases our chances of getting MAP_ANONYMOUS |
44 |
|
|
|
45 |
|
|
#include <sys/mman.h> |
46 |
|
|
#include <sys/types.h> |
47 |
|
|
#include <sys/stat.h> |
48 |
|
|
#include <unistd.h> |
49 |
|
|
#include <pwd.h> |
50 |
|
|
|
51 |
|
|
#if defined (MAP_ANON) && !defined (MAP_ANONYMOUS) |
52 |
|
|
#define MAP_ANONYMOUS MAP_ANON |
53 |
|
|
#endif |
54 |
|
|
|
55 |
|
|
#ifdef PATH_MAX |
56 |
|
|
#define MAX_PATH (PATH_MAX < 4096 ? 4096 : PATH_MAX) |
57 |
|
|
#else |
58 |
|
|
#define MAX_PATH 4096 |
59 |
|
|
#endif |
60 |
|
|
|
61 |
|
|
#define u_handle int |
62 |
|
|
#define u_invalid_handle -1 |
63 |
|
|
#define u_valid(fd) ((fd) >= 0) |
64 |
|
|
|
65 |
|
|
#define u_setenv(name,value) setenv (name, value, 1) |
66 |
|
|
#define u_mkdir(path) mkdir (path, 0777) |
67 |
|
|
#define u_chdir(path) chdir (path) |
68 |
|
|
#define u_rename(fr,to) rename (fr, to) |
69 |
|
|
#define u_open(path) open (path, O_RDONLY) |
70 |
|
|
#define u_creat(path,exec) open (path, O_WRONLY | O_CREAT | O_TRUNC, (exec) ? 0777 : 0666) |
71 |
|
|
#define u_close(handle) close (handle) |
72 |
|
|
#define u_append(path,add) strcat (strcat (path, "/"), add) |
73 |
|
|
#define u_write(handle,data,len) write (handle, data, len) |
74 |
|
|
|
75 |
|
|
// on a mostly idle system, a sync at the end is certainly faster, hope for the best |
76 |
|
|
#define u_fsync(handle) |
77 |
|
|
#define u_sync() sync () |
78 |
|
|
|
79 |
|
|
#define u_lockfile(path) open (path, O_RDWR | O_CREAT, 0666) |
80 |
|
|
#define u_cloexec(handle) fcntl (handle, F_SETFD, FD_CLOEXEC) |
81 |
|
|
|
82 |
|
|
#endif |
83 |
|
|
|
84 |
|
|
#define u_16(ptr) (((ptr)[0] << 8) | (ptr)[1]) |
85 |
|
|
#define u_32(ptr) (((ptr)[0] << 24) | ((ptr)[1] << 16) | ((ptr)[2] << 8) | (ptr)[3]) |
86 |
|
|
|
87 |
root |
1.2 |
static char currdir[MAX_PATH]; |
88 |
|
|
static char datadir[MAX_PATH]; // %AppData%/urlader |
89 |
|
|
static char exe_dir[MAX_PATH]; // %AppData%/urlader/EXE_ID |
90 |
|
|
static char execdir[MAX_PATH]; // %AppData%/urlader/EXE_ID/EXE_VER |
91 |
|
|
static char exe_id[MAX_PATH]; |
92 |
|
|
static char exe_ver[MAX_PATH]; |
93 |
|
|
|
94 |
|
|
///////////////////////////////////////////////////////////////////////////// |
95 |
|
|
|
96 |
|
|
static void |
97 |
|
|
u_fatal (const char *msg) |
98 |
|
|
{ |
99 |
|
|
#ifdef _WIN32 |
100 |
|
|
MessageBox (0, msg, URLADER, 0); |
101 |
|
|
#else |
102 |
|
|
write (2, URLADER ": ", sizeof (URLADER ": ") - 1); |
103 |
|
|
write (2, msg, strlen (msg)); |
104 |
|
|
write (2, "\n", 1); |
105 |
|
|
#endif |
106 |
|
|
|
107 |
|
|
_exit (1); |
108 |
|
|
} |
109 |
|
|
|
110 |
root |
1.1 |
static void * |
111 |
|
|
u_malloc (unsigned int size) |
112 |
|
|
{ |
113 |
|
|
void *addr; |
114 |
|
|
|
115 |
root |
1.3 |
if (!size) |
116 |
|
|
return 0; |
117 |
|
|
|
118 |
root |
1.1 |
#ifdef _WIN32 |
119 |
|
|
HANDLE handle = CreateFileMapping (0, 0, PAGE_READWRITE, 0, size, NULL); |
120 |
|
|
|
121 |
root |
1.3 |
addr = 0; |
122 |
|
|
if (handle) |
123 |
|
|
{ |
124 |
|
|
addr = MapViewOfFile (handle, FILE_MAP_WRITE, 0, 0, size); |
125 |
|
|
CloseHandle (handle); |
126 |
|
|
} |
127 |
root |
1.1 |
#elif defined (MAP_ANONYMOUS) |
128 |
|
|
addr = mmap (0, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0); |
129 |
|
|
|
130 |
|
|
if (addr == (void *)-1) |
131 |
|
|
addr = 0; |
132 |
|
|
#else |
133 |
|
|
addr = malloc (size); |
134 |
|
|
#endif |
135 |
|
|
|
136 |
root |
1.3 |
if (!addr) |
137 |
|
|
u_fatal ("memory allocation failure, aborting."); |
138 |
|
|
|
139 |
root |
1.1 |
return addr; |
140 |
|
|
} |
141 |
|
|
|
142 |
|
|
static void |
143 |
|
|
u_free (void *addr, unsigned int size) |
144 |
|
|
{ |
145 |
root |
1.3 |
if (!addr) |
146 |
|
|
return; |
147 |
|
|
|
148 |
root |
1.1 |
#ifdef _WIN32 |
149 |
|
|
UnmapViewOfFile (addr); |
150 |
|
|
#elif defined (MAP_ANONYMOUS) |
151 |
|
|
munmap (addr, size); |
152 |
|
|
#else |
153 |
|
|
free (addr); |
154 |
|
|
#endif |
155 |
|
|
} |
156 |
|
|
|
157 |
|
|
static void * |
158 |
root |
1.3 |
u_realloc (void *addr, unsigned int old_size, unsigned int new_size) |
159 |
|
|
{ |
160 |
|
|
void *addr2 = u_malloc (new_size); |
161 |
|
|
memcpy (addr2, addr, (new_size < old_size ? new_size : old_size)); |
162 |
|
|
u_free (addr, old_size); |
163 |
|
|
|
164 |
|
|
return addr2; |
165 |
|
|
} |
166 |
|
|
|
167 |
|
|
static void * |
168 |
root |
1.1 |
u_mmap (u_handle h, unsigned int size) |
169 |
|
|
{ |
170 |
|
|
void *addr; |
171 |
|
|
|
172 |
|
|
#ifdef _WIN32 |
173 |
|
|
HANDLE handle = CreateFileMapping (h, 0, PAGE_READONLY, 0, size, NULL); |
174 |
|
|
|
175 |
|
|
if (!handle) |
176 |
|
|
return 0; |
177 |
|
|
|
178 |
|
|
addr = MapViewOfFile (handle, FILE_MAP_READ, 0, 0, size); |
179 |
|
|
|
180 |
|
|
CloseHandle (handle); |
181 |
|
|
#else |
182 |
|
|
addr = mmap (0, size, PROT_READ, MAP_SHARED, h, 0); |
183 |
|
|
|
184 |
|
|
if (addr == (void *)-1) |
185 |
|
|
addr = 0; |
186 |
|
|
#endif |
187 |
|
|
|
188 |
|
|
return addr; |
189 |
|
|
} |
190 |
|
|
|
191 |
|
|
static void |
192 |
|
|
u_munmap (void *addr, unsigned int len) |
193 |
|
|
{ |
194 |
|
|
#ifdef _WIN32 |
195 |
|
|
UnmapViewOfFile (addr); |
196 |
|
|
#else |
197 |
|
|
munmap (addr, len); |
198 |
|
|
#endif |
199 |
|
|
} |
200 |
root |
1.2 |
|
201 |
|
|
///////////////////////////////////////////////////////////////////////////// |
202 |
|
|
|
203 |
root |
1.3 |
typedef struct |
204 |
|
|
{ |
205 |
|
|
char *addr; |
206 |
|
|
unsigned int used; |
207 |
|
|
unsigned int size; |
208 |
|
|
} u_dynbuf; |
209 |
|
|
|
210 |
|
|
static void * |
211 |
|
|
u_dynbuf_append (u_dynbuf *dynbuf, void *data, unsigned int len) |
212 |
|
|
{ |
213 |
|
|
char *dest; |
214 |
|
|
|
215 |
|
|
if ((dynbuf->used += len) > dynbuf->size) |
216 |
|
|
{ |
217 |
|
|
unsigned int new_size = dynbuf->size ? dynbuf->size * 2 : 4096; |
218 |
|
|
dynbuf->addr = u_realloc (dynbuf->addr, dynbuf->size, new_size); |
219 |
|
|
dynbuf->size = new_size; |
220 |
|
|
} |
221 |
|
|
|
222 |
|
|
dest = dynbuf->addr + dynbuf->used - len; |
223 |
|
|
|
224 |
|
|
if (data) |
225 |
|
|
memcpy (dest, data, len); |
226 |
|
|
|
227 |
|
|
return dest; |
228 |
|
|
} |
229 |
|
|
|
230 |
|
|
///////////////////////////////////////////////////////////////////////////// |
231 |
|
|
|
232 |
root |
1.2 |
static void |
233 |
|
|
u_set_datadir (void) |
234 |
|
|
{ |
235 |
|
|
#ifdef _WIN32 |
236 |
|
|
if (SHGetFolderPath (0, CSIDL_APPDATA | CSIDL_FLAG_CREATE, NULL, SHGFP_TYPE_CURRENT, datadir) != S_OK) |
237 |
|
|
u_fatal ("unable to find application data directory"); |
238 |
|
|
|
239 |
|
|
u_mkdir (datadir); |
240 |
|
|
u_append (datadir, URLADER); |
241 |
|
|
|
242 |
|
|
#else |
243 |
|
|
char *home = getenv ("HOME"); |
244 |
|
|
|
245 |
|
|
if (!home) |
246 |
|
|
{ |
247 |
|
|
struct passwd *pw; |
248 |
|
|
|
249 |
|
|
if ((pw = getpwuid (getuid ()))) |
250 |
|
|
home = pw->pw_dir; |
251 |
|
|
else |
252 |
|
|
home = "/tmp"; |
253 |
|
|
} |
254 |
|
|
|
255 |
|
|
u_mkdir (home); |
256 |
|
|
//strcat (strcat (strcpy (datadir, home), "/."), URLADER); |
257 |
|
|
sprintf (datadir, "%s/.%s", home, URLADER); |
258 |
|
|
#endif |
259 |
|
|
|
260 |
|
|
u_setenv ("URLADER_DATADIR", datadir); |
261 |
|
|
} |
262 |
|
|
|
263 |
|
|
static void |
264 |
|
|
u_set_exe_info (void) |
265 |
|
|
{ |
266 |
|
|
strcpy (exe_dir, datadir); |
267 |
|
|
u_append (exe_dir, exe_id); |
268 |
|
|
u_mkdir (exe_dir); |
269 |
|
|
|
270 |
|
|
strcpy (execdir, exe_dir); |
271 |
|
|
u_append (execdir, "i-"); |
272 |
|
|
strcat (execdir, exe_ver); |
273 |
|
|
|
274 |
|
|
u_setenv ("URLADER_EXECDIR", execdir); |
275 |
|
|
u_setenv ("URLADER_EXE_ID" , exe_id); |
276 |
|
|
u_setenv ("URLADER_EXE_DIR", exe_dir); |
277 |
|
|
u_setenv ("URLADER_EXE_VER", exe_ver); |
278 |
|
|
} |
279 |
|
|
|
280 |
|
|
///////////////////////////////////////////////////////////////////////////// |
281 |
|
|
|
282 |
root |
1.1 |
static u_handle |
283 |
|
|
u_lock (const char *path, int excl, int dowait) |
284 |
|
|
{ |
285 |
|
|
u_handle h; |
286 |
|
|
|
287 |
|
|
h = u_lockfile (path); |
288 |
|
|
if (!u_valid (h)) |
289 |
|
|
return h; |
290 |
|
|
|
291 |
|
|
u_cloexec (h); |
292 |
|
|
|
293 |
|
|
for (;;) |
294 |
|
|
{ |
295 |
|
|
int success; |
296 |
|
|
|
297 |
|
|
// acquire the lock |
298 |
|
|
#ifdef _WIN32 |
299 |
|
|
OVERLAPPED ov = { 0 }; |
300 |
|
|
|
301 |
|
|
success = LockFileEx (h, |
302 |
|
|
(excl ? LOCKFILE_EXCLUSIVE_LOCK : 0) |
303 |
|
|
| (dowait ? 0 : LOCKFILE_FAIL_IMMEDIATELY), |
304 |
|
|
0, |
305 |
|
|
1, 0, |
306 |
|
|
&ov); |
307 |
|
|
#else |
308 |
|
|
struct flock lck = { 0 }; |
309 |
|
|
|
310 |
|
|
lck.l_type = excl ? F_WRLCK : F_RDLCK; |
311 |
|
|
lck.l_whence = SEEK_SET; |
312 |
|
|
lck.l_len = 1; |
313 |
|
|
|
314 |
|
|
success = !fcntl (h, dowait ? F_SETLKW : F_SETLK, &lck); |
315 |
|
|
#endif |
316 |
|
|
|
317 |
|
|
if (!success) |
318 |
|
|
break; |
319 |
|
|
|
320 |
|
|
// we have the lock, now verify that the lockfile still exists |
321 |
|
|
|
322 |
|
|
#ifdef _WIN32 |
323 |
|
|
// apparently, we have to open the file to get its info :( |
324 |
root |
1.2 |
{ |
325 |
|
|
BY_HANDLE_FILE_INFORMATION s1, s2; |
326 |
|
|
u_handle h2 = u_lockfile (path); |
327 |
|
|
if (!u_valid (h)) |
328 |
|
|
break; |
329 |
|
|
|
330 |
|
|
success = GetFileInformationByHandle (h, &s1) |
331 |
|
|
&& GetFileInformationByHandle (h2, &s2); |
332 |
|
|
|
333 |
|
|
u_close (h2); |
334 |
|
|
|
335 |
|
|
if (!success) |
336 |
|
|
break; |
337 |
|
|
|
338 |
|
|
success = s1.dwVolumeSerialNumber == s2.dwVolumeSerialNumber |
339 |
|
|
&& s1.nFileIndexHigh == s2.nFileIndexHigh |
340 |
|
|
&& s1.nFileIndexLow == s2.nFileIndexLow; |
341 |
|
|
} |
342 |
root |
1.1 |
#else |
343 |
|
|
struct stat s1, s2; |
344 |
|
|
|
345 |
|
|
if (fstat (h, &s1) || stat (path, &s2)) |
346 |
|
|
break; |
347 |
|
|
|
348 |
|
|
success = s1.st_dev == s2.st_dev |
349 |
|
|
&& s1.st_ino == s2.st_ino; |
350 |
|
|
#endif |
351 |
|
|
|
352 |
|
|
if (success) |
353 |
|
|
return h; // lock successfully acquired |
354 |
|
|
|
355 |
|
|
// files differ, close and retry - should be very rare |
356 |
|
|
u_close (h); |
357 |
|
|
} |
358 |
|
|
|
359 |
|
|
// failure |
360 |
|
|
u_close (h); |
361 |
|
|
return u_invalid_handle; |
362 |
|
|
} |
363 |
|
|
|