1 |
root |
1.1 |
#ifndef URLADER |
2 |
|
|
# define URLADER "urlader" |
3 |
|
|
#endif |
4 |
root |
1.5 |
#define URLADER_VERSION "1.0" // a decimal number, not a version string |
5 |
root |
1.1 |
|
6 |
root |
1.6 |
#define MAX_ARGC 32 |
7 |
|
|
#define MAX_ARGS 256 |
8 |
|
|
|
9 |
root |
1.1 |
#include <stdio.h> |
10 |
|
|
#include <stdlib.h> |
11 |
|
|
#include <unistd.h> |
12 |
|
|
#include <errno.h> |
13 |
|
|
#include <string.h> |
14 |
|
|
#include <time.h> |
15 |
|
|
#include <fcntl.h> |
16 |
|
|
|
17 |
root |
1.2 |
#include "liblzf/lzf_d.c" |
18 |
root |
1.1 |
|
19 |
|
|
#define TAIL_MAGIC "SCHMORPPACK0" |
20 |
|
|
|
21 |
|
|
#ifdef _WIN32 |
22 |
|
|
|
23 |
root |
1.6 |
#include <windows.h> |
24 |
|
|
//#include <winbase.h> |
25 |
|
|
#include <shlobj.h> |
26 |
|
|
#include <shlwapi.h> |
27 |
|
|
#include <wininet.h> |
28 |
|
|
|
29 |
|
|
static DWORD dword; |
30 |
|
|
|
31 |
|
|
#define u_handle HANDLE |
32 |
|
|
#define u_invalid_handle 0 |
33 |
|
|
#define u_valid(handle) (!!handle) |
34 |
|
|
|
35 |
|
|
#define u_setenv(name,value) SetEnvironmentVariable (name, value) |
36 |
|
|
#define u_mkdir(path) !CreateDirectory (path, NULL) |
37 |
|
|
#define u_chdir(path) !SetCurrentDirectory (path) |
38 |
|
|
#define u_rename(fr,to) !MoveFile (fr, to) |
39 |
|
|
#define u_open(path) CreateFile (path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL) |
40 |
|
|
#define u_creat(path,exec) CreateFile (path, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL) |
41 |
|
|
#define u_creat(path,exec) CreateFile (path, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL) |
42 |
|
|
#define u_close(handle) CloseHandle (handle) |
43 |
|
|
#define u_append(path,add) PathAppend (path, add) |
44 |
|
|
#define u_write(handle,data,len) (WriteFile (handle, data, len, &dword, 0) ? dword : -1) |
45 |
|
|
|
46 |
|
|
#define u_fsync(handle) FlushFileBuffers (handle) |
47 |
|
|
#define u_sync() |
48 |
|
|
|
49 |
|
|
#define u_lockfile(path) CreateFile (path, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL) |
50 |
|
|
#define u_cloexec(handle) |
51 |
|
|
|
52 |
|
|
#else |
53 |
|
|
|
54 |
|
|
#define _GNU_SOURCE 1 |
55 |
|
|
#define _BSD_SOURCE 1 |
56 |
|
|
// the above increases our chances of getting MAP_ANONYMOUS |
57 |
|
|
|
58 |
|
|
#include <sys/mman.h> |
59 |
|
|
#include <sys/types.h> |
60 |
root |
1.7 |
#include <sys/stat.h> |
61 |
|
|
#include <unistd.h> |
62 |
root |
1.6 |
#include <pwd.h> |
63 |
root |
1.4 |
|
64 |
root |
1.6 |
#if defined (MAP_ANON) && !defined (MAP_ANONYMOUS) |
65 |
|
|
#define MAP_ANONYMOUS MAP_ANON |
66 |
|
|
#endif |
67 |
root |
1.1 |
|
68 |
root |
1.6 |
#ifdef PATH_MAX |
69 |
|
|
#define MAX_PATH (PATH_MAX < 4096 ? 4096 : PATH_MAX) |
70 |
|
|
#else |
71 |
|
|
#define MAX_PATH 4096 |
72 |
|
|
#endif |
73 |
root |
1.1 |
|
74 |
root |
1.6 |
#define u_handle int |
75 |
|
|
#define u_invalid_handle -1 |
76 |
|
|
#define u_valid(fd) ((fd) >= 0) |
77 |
|
|
|
78 |
|
|
#define u_setenv(name,value) setenv (name, value, 1) |
79 |
|
|
#define u_mkdir(path) mkdir (path, 0777) |
80 |
|
|
#define u_chdir(path) chdir (path) |
81 |
|
|
#define u_rename(fr,to) rename (fr, to) |
82 |
|
|
#define u_open(path) open (path, O_RDONLY) |
83 |
|
|
#define u_creat(path,exec) open (path, O_WRONLY | O_CREAT | O_TRUNC, (exec) ? 0777 : 0666) |
84 |
|
|
#define u_close(handle) close (handle) |
85 |
|
|
#define u_append(path,add) strcat (strcat (path, "/"), add) |
86 |
|
|
#define u_write(handle,data,len) write (handle, data, len) |
87 |
|
|
|
88 |
|
|
// on a mostly idle system, a sync at the end is certainly faster, hope for the best |
89 |
|
|
#define u_fsync(handle) |
90 |
|
|
#define u_sync() sync () |
91 |
|
|
|
92 |
|
|
#define u_lockfile(path) open (path, O_RDWR | O_CREAT, 0666) |
93 |
|
|
#define u_cloexec(handle) fcntl (handle, F_SETFD, FD_CLOEXEC) |
94 |
root |
1.1 |
|
95 |
|
|
#endif |
96 |
|
|
|
97 |
|
|
#define u_16(ptr) (((ptr)[0] << 8) | (ptr)[1]) |
98 |
|
|
#define u_32(ptr) (((ptr)[0] << 24) | ((ptr)[1] << 16) | ((ptr)[2] << 8) | (ptr)[3]) |
99 |
|
|
|
100 |
root |
1.6 |
/* some simple? dynamic memory management for paths might save ltos of ram */ |
101 |
root |
1.1 |
static u_handle pack_handle; |
102 |
root |
1.6 |
static u_handle lock_handle; |
103 |
root |
1.1 |
static char tmppath[MAX_PATH]; |
104 |
|
|
static char currdir[MAX_PATH]; |
105 |
|
|
static char datadir[MAX_PATH]; // %AppData%/urlader |
106 |
|
|
static char exe_dir[MAX_PATH]; // %AppData%/urlader/EXE_ID |
107 |
|
|
static char execdir[MAX_PATH]; // %AppData%/urlader/EXE_ID/EXE_VER |
108 |
|
|
static char exe_id[MAX_PATH]; |
109 |
|
|
static char exe_ver[MAX_PATH]; |
110 |
|
|
|
111 |
|
|
static int exe_argc; |
112 |
root |
1.6 |
static const char *exe_argv[MAX_ARGC]; |
113 |
|
|
static char exe_args[MAX_ARGS]; /* actual arguments strings copied here */ |
114 |
|
|
static unsigned int exe_argo; |
115 |
root |
1.1 |
|
116 |
|
|
static void |
117 |
|
|
fatal (const char *msg) |
118 |
|
|
{ |
119 |
|
|
#ifdef _WIN32 |
120 |
|
|
MessageBox (0, msg, URLADER, 0); |
121 |
|
|
#else |
122 |
root |
1.6 |
write (2, URLADER ": ", sizeof (URLADER ": ") - 1); |
123 |
|
|
write (2, msg, strlen (msg)); |
124 |
|
|
write (2, "\n", 1); |
125 |
root |
1.1 |
#endif |
126 |
|
|
|
127 |
|
|
_exit (1); |
128 |
|
|
} |
129 |
|
|
|
130 |
root |
1.6 |
static void * |
131 |
|
|
u_malloc (unsigned int size) |
132 |
|
|
{ |
133 |
|
|
void *addr; |
134 |
|
|
|
135 |
|
|
#ifdef _WIN32 |
136 |
|
|
HANDLE handle = CreateFileMapping (0, 0, PAGE_READWRITE, 0, size, NULL); |
137 |
|
|
|
138 |
|
|
if (!handle) |
139 |
|
|
return 0; |
140 |
|
|
|
141 |
|
|
addr = MapViewOfFile (handle, FILE_MAP_WRITE, 0, 0, size); |
142 |
|
|
|
143 |
|
|
CloseHandle (handle); |
144 |
|
|
#elif defined (MAP_ANONYMOUS) |
145 |
|
|
addr = mmap (0, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0); |
146 |
|
|
|
147 |
|
|
if (addr == (void *)-1) |
148 |
|
|
addr = 0; |
149 |
|
|
#else |
150 |
|
|
addr = malloc (size); |
151 |
|
|
#endif |
152 |
|
|
|
153 |
|
|
return addr; |
154 |
|
|
} |
155 |
|
|
|
156 |
|
|
static void |
157 |
|
|
u_free (void *addr, unsigned int size) |
158 |
|
|
{ |
159 |
|
|
#ifdef _WIN32 |
160 |
|
|
UnmapViewOfFile (addr); |
161 |
|
|
#elif defined (MAP_ANONYMOUS) |
162 |
|
|
munmap (addr, size); |
163 |
|
|
#else |
164 |
|
|
free (addr); |
165 |
|
|
#endif |
166 |
|
|
} |
167 |
|
|
|
168 |
|
|
static void * |
169 |
|
|
u_mmap (u_handle h, unsigned int size) |
170 |
|
|
{ |
171 |
|
|
void *addr; |
172 |
|
|
|
173 |
|
|
#ifdef _WIN32 |
174 |
|
|
HANDLE handle = CreateFileMapping (h, 0, PAGE_READONLY, 0, size, NULL); |
175 |
|
|
|
176 |
|
|
if (!handle) |
177 |
|
|
return 0; |
178 |
|
|
|
179 |
|
|
addr = MapViewOfFile (handle, FILE_MAP_READ, 0, 0, size); |
180 |
|
|
|
181 |
|
|
CloseHandle (handle); |
182 |
|
|
#else |
183 |
|
|
addr = mmap (0, size, PROT_READ, MAP_SHARED, h, 0); |
184 |
|
|
|
185 |
|
|
if (addr == (void *)-1) |
186 |
|
|
addr = 0; |
187 |
|
|
#endif |
188 |
|
|
|
189 |
|
|
return addr; |
190 |
|
|
} |
191 |
|
|
|
192 |
|
|
static void |
193 |
|
|
u_munmap (void *addr, unsigned int len) |
194 |
|
|
{ |
195 |
|
|
#ifdef _WIN32 |
196 |
|
|
UnmapViewOfFile (addr); |
197 |
|
|
#else |
198 |
|
|
munmap (addr, len); |
199 |
|
|
#endif |
200 |
|
|
} |
201 |
|
|
|
202 |
root |
1.1 |
static void |
203 |
|
|
tmpdir (const char *dir) |
204 |
|
|
{ |
205 |
|
|
static int cnt; |
206 |
|
|
|
207 |
|
|
for (;;) |
208 |
|
|
{ |
209 |
|
|
// #ifdef _WIN32 |
210 |
|
|
// sprintf (tmppath, "%s/%x_%x.tmp", dir, (unsigned int)GetCurrentProcessId (), ++cnt); |
211 |
|
|
// #else |
212 |
|
|
sprintf (tmppath, "%s/t-%x_%x.tmp", dir, (unsigned int)getpid () , ++cnt); |
213 |
|
|
// #endif |
214 |
|
|
|
215 |
|
|
if (!u_mkdir (tmppath)) |
216 |
|
|
return; |
217 |
|
|
} |
218 |
|
|
} |
219 |
|
|
|
220 |
root |
1.7 |
static u_handle |
221 |
|
|
u_lock (const char *path, int excl, int dowait) |
222 |
root |
1.6 |
{ |
223 |
root |
1.7 |
u_handle h; |
224 |
|
|
|
225 |
|
|
h = u_lockfile (path); |
226 |
|
|
if (!u_valid (h)) |
227 |
|
|
return h; |
228 |
|
|
|
229 |
|
|
u_cloexec (h); |
230 |
|
|
|
231 |
|
|
for (;;) |
232 |
|
|
{ |
233 |
|
|
int success; |
234 |
root |
1.6 |
|
235 |
root |
1.7 |
// acquire the lock |
236 |
root |
1.6 |
#ifdef _WIN32 |
237 |
|
|
OVERLAPPED ov = { 0 }; |
238 |
|
|
|
239 |
root |
1.7 |
success = LockFileEx (h, |
240 |
|
|
(excl ? LOCKFILE_EXCLUSIVE_LOCK : 0) |
241 |
|
|
| (dowait ? 0 : LOCKFILE_FAIL_IMMEDIATELY), |
242 |
|
|
0, |
243 |
|
|
1, 0, |
244 |
|
|
&ov); |
245 |
|
|
#else |
246 |
|
|
struct flock lck = { 0 }; |
247 |
|
|
|
248 |
|
|
lck.l_type = excl ? F_WRLCK : F_RDLCK; |
249 |
|
|
lck.l_whence = SEEK_SET; |
250 |
|
|
lck.l_len = 1; |
251 |
|
|
|
252 |
|
|
success = !fcntl (h, dowait ? F_SETLKW : F_SETLK, &lck); |
253 |
|
|
#endif |
254 |
|
|
|
255 |
|
|
if (!success) |
256 |
|
|
break; |
257 |
|
|
|
258 |
|
|
// we have the lock, now verify that the lockfile still exists |
259 |
|
|
|
260 |
|
|
#ifdef _WIN32 |
261 |
|
|
// apparently, we have to open the file to get its info :( |
262 |
|
|
BY_HANDLE_FILE_INFORMATION s1, s2; |
263 |
|
|
u_handle h2 = u_lockfile (path); |
264 |
|
|
if (!u_valid (h)) |
265 |
|
|
break; |
266 |
|
|
|
267 |
|
|
success = GetFileInformationByHandle (h, &s1) |
268 |
|
|
&& GetFileInformationByHandle (h2, &s2); |
269 |
|
|
|
270 |
|
|
u_close (h2); |
271 |
|
|
|
272 |
|
|
if (!success) |
273 |
|
|
break; |
274 |
|
|
|
275 |
|
|
success = s1.dwVolumeSerialNumber == s2.dwVolumeSerialNumber |
276 |
|
|
&& s1.nFileIndexHigh == s2.nFileIndexHigh |
277 |
|
|
&& s1.nFileIndexLow == s2.nFileIndexLow; |
278 |
root |
1.6 |
#else |
279 |
root |
1.7 |
struct stat s1, s2; |
280 |
root |
1.6 |
|
281 |
root |
1.7 |
if (fstat (h, &s1) || stat (path, &s2)) |
282 |
|
|
break; |
283 |
|
|
|
284 |
|
|
success = s1.st_dev == s2.st_dev |
285 |
|
|
&& s1.st_ino == s2.st_ino; |
286 |
root |
1.6 |
#endif |
287 |
root |
1.7 |
|
288 |
|
|
if (success) |
289 |
|
|
return h; // lock successfully acquired |
290 |
|
|
|
291 |
|
|
// files differ, close and retry - should be very rare |
292 |
|
|
u_close (h); |
293 |
|
|
} |
294 |
|
|
|
295 |
|
|
// failure |
296 |
|
|
u_close (h); |
297 |
|
|
return u_invalid_handle; |
298 |
root |
1.6 |
} |
299 |
|
|
|
300 |
root |
1.1 |
static void |
301 |
root |
1.6 |
systemv (const char *const argv[]) |
302 |
root |
1.1 |
{ |
303 |
|
|
#ifdef _WIN32 |
304 |
|
|
_spawnv (P_WAIT, argv [0], argv); |
305 |
|
|
#else |
306 |
root |
1.6 |
pid_t pid = fork (); |
307 |
root |
1.1 |
|
308 |
|
|
if (pid < 0) |
309 |
|
|
fatal ("fork failure"); |
310 |
|
|
|
311 |
|
|
if (!pid) |
312 |
|
|
{ |
313 |
|
|
execv (argv [0], (void *)argv); |
314 |
|
|
_exit (124); |
315 |
|
|
} |
316 |
|
|
|
317 |
|
|
int status; |
318 |
|
|
waitpid (pid, &status, 0); |
319 |
|
|
#endif |
320 |
|
|
} |
321 |
|
|
|
322 |
|
|
static void |
323 |
|
|
deltree (const char *path) |
324 |
|
|
{ |
325 |
|
|
#ifdef _WIN32 |
326 |
|
|
char buf[MAX_PATH * 2 + 64]; |
327 |
|
|
const char *argv[] = { getenv ("COMSPEC"), "/c", "rd", "/s", "/q", buf, 0 }; |
328 |
|
|
sprintf (buf, "\"%s\"", path); |
329 |
|
|
#else |
330 |
|
|
const char *argv[] = { "/bin/rm", "-rf", path, 0 }; |
331 |
|
|
#endif |
332 |
root |
1.6 |
systemv (argv); |
333 |
root |
1.1 |
} |
334 |
|
|
|
335 |
|
|
enum |
336 |
|
|
{ |
337 |
|
|
T_NULL, // 5 |
338 |
|
|
T_META, // 1 : exe_id, exe_ver |
339 |
root |
1.4 |
T_ENV, // 2 : name, value |
340 |
|
|
T_ARG, // 3 : arg |
341 |
root |
1.1 |
T_DIR, // 4+: path |
342 |
|
|
T_FILE, // 4+: path, data |
343 |
|
|
T_NUM |
344 |
|
|
}; |
345 |
|
|
|
346 |
|
|
enum |
347 |
|
|
{ |
348 |
|
|
F_EXEC = 1, |
349 |
|
|
F_LZF = 2, |
350 |
|
|
F_NULL = 0 |
351 |
|
|
}; |
352 |
|
|
|
353 |
|
|
struct hdr |
354 |
|
|
{ |
355 |
|
|
unsigned char type; |
356 |
|
|
unsigned char flags; |
357 |
|
|
unsigned char namelen[2]; |
358 |
|
|
unsigned char datalen[4]; |
359 |
|
|
}; |
360 |
|
|
|
361 |
|
|
struct tail { |
362 |
|
|
unsigned char max_filesize[4]; |
363 |
|
|
unsigned char size[4]; |
364 |
|
|
char magic[12]; |
365 |
|
|
}; |
366 |
|
|
|
367 |
|
|
static char *pack_base, *pack_end; |
368 |
|
|
static struct hdr *pack_cur; |
369 |
root |
1.2 |
static char *scratch; |
370 |
root |
1.6 |
static unsigned int scratch_size; |
371 |
root |
1.1 |
|
372 |
|
|
#define PACK_NAME ((char *)(pack_cur + 1)) |
373 |
|
|
#define PACK_DATA (PACK_NAME + u_16 (pack_cur->namelen) + 1) |
374 |
|
|
#define PACK_VALID pack_cur->type |
375 |
|
|
|
376 |
|
|
static void |
377 |
|
|
pack_next (void) |
378 |
|
|
{ |
379 |
|
|
unsigned int d = u_32 (pack_cur->datalen); |
380 |
|
|
|
381 |
|
|
pack_cur = (struct hdr *)(PACK_DATA + d); |
382 |
|
|
} |
383 |
|
|
|
384 |
|
|
static void |
385 |
|
|
pack_unmap (void) |
386 |
|
|
{ |
387 |
root |
1.6 |
if (pack_base) |
388 |
|
|
{ |
389 |
|
|
u_munmap (pack_base, pack_end - pack_base); |
390 |
|
|
pack_base = 0; |
391 |
|
|
} |
392 |
root |
1.1 |
|
393 |
root |
1.6 |
if (scratch) |
394 |
|
|
{ |
395 |
|
|
u_free (scratch, scratch_size); |
396 |
|
|
scratch = 0; |
397 |
|
|
} |
398 |
root |
1.1 |
} |
399 |
|
|
|
400 |
|
|
static int |
401 |
|
|
pack_map (void) |
402 |
|
|
{ |
403 |
root |
1.6 |
char *addr; |
404 |
|
|
unsigned int size; |
405 |
|
|
|
406 |
root |
1.1 |
#ifdef _WIN32 |
407 |
|
|
BY_HANDLE_FILE_INFORMATION fi; |
408 |
|
|
|
409 |
|
|
if (!GetFileInformationByHandle (pack_handle, &fi)) |
410 |
|
|
return 0; |
411 |
|
|
|
412 |
root |
1.6 |
size = fi.nFileSizeLow; |
413 |
|
|
#else |
414 |
|
|
size = lseek (pack_handle, 0, SEEK_END); |
415 |
|
|
#endif |
416 |
root |
1.1 |
|
417 |
root |
1.6 |
addr = u_mmap (pack_handle, size); |
418 |
|
|
if (!addr) |
419 |
root |
1.1 |
return 0; |
420 |
|
|
|
421 |
|
|
pack_unmap (); |
422 |
|
|
|
423 |
root |
1.6 |
pack_base = addr; |
424 |
|
|
pack_end = pack_base + size; |
425 |
root |
1.1 |
|
426 |
|
|
struct tail *tail; |
427 |
|
|
|
428 |
|
|
tail = (void *)(pack_end - sizeof (*tail)); |
429 |
|
|
|
430 |
|
|
if (memcmp (tail->magic, TAIL_MAGIC, sizeof (TAIL_MAGIC) - 1)) |
431 |
|
|
return 0; |
432 |
|
|
|
433 |
|
|
pack_cur = (struct hdr *)(pack_end - u_32 (tail->size)); |
434 |
|
|
|
435 |
root |
1.6 |
scratch = u_malloc (scratch_size = u_32 (tail->max_filesize)); |
436 |
|
|
if (!scratch) |
437 |
|
|
return 0; |
438 |
root |
1.2 |
|
439 |
root |
1.1 |
return 1; |
440 |
|
|
} |
441 |
|
|
|
442 |
|
|
static void |
443 |
|
|
exe_info (void) |
444 |
|
|
{ |
445 |
|
|
if (!pack_map ()) |
446 |
|
|
fatal ("unable to locate packfile in executable - executable corrupted?"); |
447 |
|
|
|
448 |
|
|
if (pack_cur->type != T_META) |
449 |
|
|
fatal ("unable to locate executable metadata - executable corrupted?"); |
450 |
|
|
|
451 |
|
|
strcpy (exe_id, PACK_NAME); |
452 |
|
|
} |
453 |
|
|
|
454 |
|
|
static void |
455 |
|
|
load (void) |
456 |
|
|
{ |
457 |
|
|
u_mkdir (datadir); |
458 |
|
|
|
459 |
|
|
strcpy (exe_dir, datadir); |
460 |
|
|
u_append (exe_dir, exe_id); |
461 |
|
|
u_mkdir (exe_dir); |
462 |
|
|
|
463 |
|
|
if (u_chdir (exe_dir)) |
464 |
|
|
fatal ("unable to change to application data directory"); |
465 |
|
|
|
466 |
|
|
u_handle h = u_open ("override"); |
467 |
root |
1.5 |
if (u_valid (h)) |
468 |
root |
1.1 |
{ |
469 |
|
|
u_handle oh = pack_handle; |
470 |
|
|
|
471 |
|
|
pack_handle = h; |
472 |
|
|
if (!pack_map ()) |
473 |
|
|
{ |
474 |
|
|
pack_handle = oh; |
475 |
|
|
oh = h; |
476 |
|
|
} |
477 |
|
|
|
478 |
|
|
u_close (oh); |
479 |
|
|
} |
480 |
|
|
|
481 |
|
|
if (pack_cur->type != T_META) |
482 |
|
|
fatal ("unable to locate override metadata"); |
483 |
|
|
|
484 |
|
|
strcpy (exe_ver, PACK_DATA); |
485 |
|
|
pack_next (); |
486 |
|
|
|
487 |
root |
1.4 |
for (;;) |
488 |
root |
1.1 |
{ |
489 |
root |
1.4 |
if (pack_cur->type == T_ENV) |
490 |
|
|
u_setenv (PACK_NAME, PACK_DATA); |
491 |
|
|
else if (pack_cur->type == T_ARG) |
492 |
root |
1.6 |
{ |
493 |
|
|
int len = u_16 (pack_cur->namelen) + 1; |
494 |
|
|
exe_argv [exe_argc++] = exe_args + exe_argo; |
495 |
|
|
memcpy (exe_args + exe_argo, PACK_NAME, len); |
496 |
|
|
exe_argo += len; |
497 |
|
|
} |
498 |
root |
1.4 |
else |
499 |
|
|
break; |
500 |
root |
1.1 |
|
501 |
|
|
pack_next (); |
502 |
|
|
} |
503 |
root |
1.4 |
|
504 |
|
|
done_env_arg: |
505 |
root |
1.1 |
strcpy (execdir, exe_dir); |
506 |
|
|
u_append (execdir, "i-"); |
507 |
|
|
strcat (execdir, exe_ver); |
508 |
|
|
|
509 |
root |
1.6 |
strcat (strcpy (tmppath, execdir), ".lck"); |
510 |
root |
1.7 |
lock_handle = u_lock (tmppath, 0, 1); |
511 |
root |
1.6 |
if (!lock_handle) |
512 |
root |
1.7 |
fatal ("unable to lock application instance"); |
513 |
root |
1.6 |
|
514 |
root |
1.1 |
if (access (execdir, F_OK)) |
515 |
|
|
{ |
516 |
|
|
// does not exist yet, so unpack and move |
517 |
|
|
tmpdir (exe_dir); |
518 |
|
|
|
519 |
|
|
if (u_chdir (tmppath)) |
520 |
|
|
fatal ("unable to change to new instance directory"); |
521 |
|
|
|
522 |
|
|
for (;;) |
523 |
|
|
{ |
524 |
|
|
switch (pack_cur->type) |
525 |
|
|
{ |
526 |
|
|
case T_DIR: |
527 |
|
|
u_mkdir (PACK_NAME); |
528 |
|
|
break; |
529 |
|
|
|
530 |
|
|
case T_FILE: |
531 |
|
|
{ |
532 |
|
|
u_handle h = u_creat (PACK_NAME, pack_cur->flags & F_EXEC); |
533 |
root |
1.2 |
unsigned int dlen, len = u_32 (pack_cur->datalen); |
534 |
|
|
char *data = PACK_DATA; |
535 |
|
|
|
536 |
|
|
if (pack_cur->flags & F_LZF) |
537 |
root |
1.6 |
if (dlen = lzf_decompress (data, len, scratch, scratch_size)) |
538 |
root |
1.2 |
{ |
539 |
|
|
data = scratch; |
540 |
|
|
len = dlen; |
541 |
|
|
} |
542 |
|
|
else |
543 |
|
|
fatal ("unable to uncompress file data - pack corrupted?"); |
544 |
root |
1.1 |
|
545 |
root |
1.5 |
if (!u_valid (h)) |
546 |
root |
1.1 |
fatal ("unable to unpack file from packfile - disk full?"); |
547 |
|
|
|
548 |
root |
1.2 |
if (u_write (h, data, len) != len) |
549 |
root |
1.1 |
fatal ("unable to unpack file from packfile - disk full?"); |
550 |
|
|
|
551 |
root |
1.4 |
u_fsync (h); |
552 |
root |
1.1 |
u_close (h); |
553 |
|
|
} |
554 |
|
|
break; |
555 |
|
|
|
556 |
|
|
case T_NULL: |
557 |
|
|
goto done; |
558 |
|
|
} |
559 |
|
|
|
560 |
|
|
pack_next (); |
561 |
|
|
} |
562 |
|
|
|
563 |
|
|
done: |
564 |
|
|
if (u_chdir (datadir)) |
565 |
|
|
fatal ("unable to change to data directory"); |
566 |
|
|
|
567 |
root |
1.3 |
u_sync (); |
568 |
|
|
|
569 |
root |
1.1 |
if (u_rename (tmppath, execdir)) |
570 |
|
|
deltree (tmppath); // if move fails, delete new, assume other process created it independently |
571 |
|
|
} |
572 |
|
|
|
573 |
|
|
pack_unmap (); |
574 |
|
|
u_close (pack_handle); |
575 |
|
|
|
576 |
root |
1.2 |
if (u_chdir (execdir)) |
577 |
|
|
fatal ("unable to change to application instance directory"); |
578 |
|
|
|
579 |
root |
1.1 |
u_setenv ("URLADER_VERSION", URLADER_VERSION); |
580 |
|
|
u_setenv ("URLADER_DATADIR", datadir); |
581 |
|
|
u_setenv ("URLADER_EXECDIR", execdir); |
582 |
|
|
u_setenv ("URLADER_EXE_ID" , exe_id); |
583 |
|
|
u_setenv ("URLADER_EXE_DIR", exe_dir); |
584 |
|
|
u_setenv ("URLADER_EXE_VER", exe_ver); |
585 |
|
|
|
586 |
root |
1.5 |
#if 0 |
587 |
root |
1.1 |
// yes, this is overkill |
588 |
|
|
u_setenv ("SHLIB_PATH" , execdir); // hpux |
589 |
|
|
u_setenv ("LIBPATH" , execdir); // aix |
590 |
|
|
u_setenv ("LD_LIBRARY_PATH" , execdir); // most elf systems |
591 |
|
|
u_setenv ("LD_LIBRARY_PATH_32", execdir); // solaris |
592 |
|
|
u_setenv ("LD_LIBRARY_PATH_64", execdir); // solaris |
593 |
|
|
u_setenv ("LD_LIBRARYN32_PATH", execdir); // irix |
594 |
|
|
u_setenv ("LD_LIBRARY64_PATH" , execdir); // irix |
595 |
|
|
u_setenv ("DYLD_LIBRARY_PATH" , execdir); // os sucks from apple |
596 |
root |
1.5 |
#endif |
597 |
root |
1.1 |
} |
598 |
|
|
|
599 |
root |
1.2 |
static void |
600 |
|
|
execute (void) |
601 |
|
|
{ |
602 |
|
|
exe_argv [exe_argc] = 0; |
603 |
root |
1.6 |
systemv (exe_argv); |
604 |
root |
1.2 |
} |
605 |
|
|
|
606 |
root |
1.1 |
#ifdef _WIN32 |
607 |
|
|
|
608 |
|
|
int APIENTRY |
609 |
|
|
WinMain (HINSTANCE hI, HINSTANCE hP, LPSTR argv, int command_show) |
610 |
|
|
{ |
611 |
|
|
if (!GetModuleFileName (hI, tmppath, sizeof (tmppath))) |
612 |
|
|
fatal ("unable to find executable pack"); |
613 |
|
|
|
614 |
root |
1.5 |
pack_handle = u_open (tmppath); |
615 |
|
|
if (!u_valid (pack_handle)) |
616 |
root |
1.1 |
fatal ("unable to open executable pack"); |
617 |
|
|
|
618 |
|
|
exe_info (); |
619 |
|
|
|
620 |
|
|
if (!GetCurrentDirectory (sizeof (currdir), currdir)) |
621 |
|
|
strcpy (currdir, "."); |
622 |
|
|
|
623 |
|
|
if (SHGetFolderPath (0, CSIDL_APPDATA | CSIDL_FLAG_CREATE, NULL, SHGFP_TYPE_CURRENT, datadir) != S_OK) |
624 |
|
|
fatal ("unable to find application data directory"); |
625 |
|
|
|
626 |
|
|
u_mkdir (datadir); |
627 |
|
|
u_append (datadir, URLADER); |
628 |
|
|
|
629 |
|
|
load (); |
630 |
|
|
execute (); |
631 |
|
|
|
632 |
|
|
return 0; |
633 |
|
|
} |
634 |
|
|
|
635 |
|
|
#else |
636 |
|
|
|
637 |
|
|
int |
638 |
|
|
main (int argc, char *argv[]) |
639 |
|
|
{ |
640 |
|
|
char *home = getenv ("HOME"); |
641 |
|
|
|
642 |
root |
1.5 |
pack_handle = u_open (argv [0]); |
643 |
|
|
if (!u_valid (pack_handle)) |
644 |
root |
1.1 |
fatal ("unable to open executable pack"); |
645 |
|
|
|
646 |
|
|
exe_info (); |
647 |
|
|
|
648 |
|
|
if (!home) |
649 |
|
|
{ |
650 |
|
|
struct passwd *pw; |
651 |
|
|
|
652 |
|
|
if ((pw = getpwuid (getuid ()))) |
653 |
|
|
home = pw->pw_dir; |
654 |
|
|
else |
655 |
|
|
home = "/tmp"; |
656 |
|
|
} |
657 |
|
|
|
658 |
|
|
if (!getcwd (currdir, sizeof (currdir))) |
659 |
|
|
strcpy (currdir, "."); |
660 |
|
|
|
661 |
|
|
u_mkdir (home); |
662 |
root |
1.6 |
//strcat (strcat (strcpy (datadir, home), "/."), URLADER); |
663 |
root |
1.1 |
sprintf (datadir, "%s/.%s", home, URLADER); |
664 |
|
|
u_mkdir (datadir); |
665 |
|
|
|
666 |
root |
1.5 |
#if 0 |
667 |
root |
1.1 |
if (gethostname (tmppath, sizeof (tmppath))) |
668 |
|
|
strcpy (tmppath, "default"); |
669 |
|
|
|
670 |
|
|
u_append (datadir, tmppath); |
671 |
root |
1.5 |
#endif |
672 |
root |
1.1 |
|
673 |
|
|
load (); |
674 |
|
|
execute (); |
675 |
|
|
|
676 |
|
|
return 0; |
677 |
|
|
} |
678 |
|
|
|
679 |
|
|
#endif |
680 |
|
|
|