1 |
root |
1.8 |
#include "urlib.c" |
2 |
root |
1.6 |
|
3 |
root |
1.1 |
#include <stdio.h> |
4 |
|
|
#include <stdlib.h> |
5 |
|
|
#include <unistd.h> |
6 |
|
|
#include <errno.h> |
7 |
|
|
#include <string.h> |
8 |
|
|
#include <time.h> |
9 |
|
|
|
10 |
root |
1.2 |
#include "liblzf/lzf_d.c" |
11 |
root |
1.1 |
|
12 |
root |
1.8 |
#include "urlib.h" |
13 |
root |
1.1 |
|
14 |
root |
1.6 |
/* some simple? dynamic memory management for paths might save ltos of ram */ |
15 |
root |
1.1 |
static u_handle pack_handle; |
16 |
root |
1.6 |
static u_handle lock_handle; |
17 |
root |
1.1 |
static char tmppath[MAX_PATH]; |
18 |
|
|
static char currdir[MAX_PATH]; |
19 |
|
|
static char datadir[MAX_PATH]; // %AppData%/urlader |
20 |
|
|
static char exe_dir[MAX_PATH]; // %AppData%/urlader/EXE_ID |
21 |
|
|
static char execdir[MAX_PATH]; // %AppData%/urlader/EXE_ID/EXE_VER |
22 |
|
|
static char exe_id[MAX_PATH]; |
23 |
|
|
static char exe_ver[MAX_PATH]; |
24 |
|
|
|
25 |
|
|
static int exe_argc; |
26 |
root |
1.6 |
static const char *exe_argv[MAX_ARGC]; |
27 |
|
|
static char exe_args[MAX_ARGS]; /* actual arguments strings copied here */ |
28 |
|
|
static unsigned int exe_argo; |
29 |
root |
1.1 |
|
30 |
|
|
static void |
31 |
|
|
fatal (const char *msg) |
32 |
|
|
{ |
33 |
|
|
#ifdef _WIN32 |
34 |
|
|
MessageBox (0, msg, URLADER, 0); |
35 |
|
|
#else |
36 |
root |
1.6 |
write (2, URLADER ": ", sizeof (URLADER ": ") - 1); |
37 |
|
|
write (2, msg, strlen (msg)); |
38 |
|
|
write (2, "\n", 1); |
39 |
root |
1.1 |
#endif |
40 |
|
|
|
41 |
|
|
_exit (1); |
42 |
|
|
} |
43 |
|
|
|
44 |
|
|
static void |
45 |
|
|
tmpdir (const char *dir) |
46 |
|
|
{ |
47 |
|
|
static int cnt; |
48 |
|
|
|
49 |
|
|
for (;;) |
50 |
|
|
{ |
51 |
|
|
// #ifdef _WIN32 |
52 |
|
|
// sprintf (tmppath, "%s/%x_%x.tmp", dir, (unsigned int)GetCurrentProcessId (), ++cnt); |
53 |
|
|
// #else |
54 |
|
|
sprintf (tmppath, "%s/t-%x_%x.tmp", dir, (unsigned int)getpid () , ++cnt); |
55 |
|
|
// #endif |
56 |
|
|
|
57 |
|
|
if (!u_mkdir (tmppath)) |
58 |
|
|
return; |
59 |
|
|
} |
60 |
|
|
} |
61 |
|
|
|
62 |
|
|
static void |
63 |
root |
1.6 |
systemv (const char *const argv[]) |
64 |
root |
1.1 |
{ |
65 |
|
|
#ifdef _WIN32 |
66 |
|
|
_spawnv (P_WAIT, argv [0], argv); |
67 |
|
|
#else |
68 |
root |
1.6 |
pid_t pid = fork (); |
69 |
root |
1.1 |
|
70 |
|
|
if (pid < 0) |
71 |
|
|
fatal ("fork failure"); |
72 |
|
|
|
73 |
|
|
if (!pid) |
74 |
|
|
{ |
75 |
|
|
execv (argv [0], (void *)argv); |
76 |
|
|
_exit (124); |
77 |
|
|
} |
78 |
|
|
|
79 |
|
|
int status; |
80 |
|
|
waitpid (pid, &status, 0); |
81 |
|
|
#endif |
82 |
|
|
} |
83 |
|
|
|
84 |
|
|
static void |
85 |
|
|
deltree (const char *path) |
86 |
|
|
{ |
87 |
|
|
#ifdef _WIN32 |
88 |
|
|
char buf[MAX_PATH * 2 + 64]; |
89 |
|
|
const char *argv[] = { getenv ("COMSPEC"), "/c", "rd", "/s", "/q", buf, 0 }; |
90 |
|
|
sprintf (buf, "\"%s\"", path); |
91 |
|
|
#else |
92 |
|
|
const char *argv[] = { "/bin/rm", "-rf", path, 0 }; |
93 |
|
|
#endif |
94 |
root |
1.6 |
systemv (argv); |
95 |
root |
1.1 |
} |
96 |
|
|
|
97 |
|
|
static char *pack_base, *pack_end; |
98 |
root |
1.8 |
static struct u_pack_hdr *pack_cur; |
99 |
root |
1.2 |
static char *scratch; |
100 |
root |
1.6 |
static unsigned int scratch_size; |
101 |
root |
1.1 |
|
102 |
|
|
#define PACK_NAME ((char *)(pack_cur + 1)) |
103 |
|
|
#define PACK_DATA (PACK_NAME + u_16 (pack_cur->namelen) + 1) |
104 |
|
|
#define PACK_VALID pack_cur->type |
105 |
|
|
|
106 |
|
|
static void |
107 |
|
|
pack_next (void) |
108 |
|
|
{ |
109 |
|
|
unsigned int d = u_32 (pack_cur->datalen); |
110 |
|
|
|
111 |
root |
1.8 |
pack_cur = (struct u_pack_hdr *)(PACK_DATA + d); |
112 |
root |
1.1 |
} |
113 |
|
|
|
114 |
|
|
static void |
115 |
|
|
pack_unmap (void) |
116 |
|
|
{ |
117 |
root |
1.6 |
if (pack_base) |
118 |
|
|
{ |
119 |
|
|
u_munmap (pack_base, pack_end - pack_base); |
120 |
|
|
pack_base = 0; |
121 |
|
|
} |
122 |
root |
1.1 |
|
123 |
root |
1.6 |
if (scratch) |
124 |
|
|
{ |
125 |
|
|
u_free (scratch, scratch_size); |
126 |
|
|
scratch = 0; |
127 |
|
|
} |
128 |
root |
1.1 |
} |
129 |
|
|
|
130 |
|
|
static int |
131 |
|
|
pack_map (void) |
132 |
|
|
{ |
133 |
root |
1.6 |
char *addr; |
134 |
|
|
unsigned int size; |
135 |
|
|
|
136 |
root |
1.1 |
#ifdef _WIN32 |
137 |
|
|
BY_HANDLE_FILE_INFORMATION fi; |
138 |
|
|
|
139 |
|
|
if (!GetFileInformationByHandle (pack_handle, &fi)) |
140 |
|
|
return 0; |
141 |
|
|
|
142 |
root |
1.6 |
size = fi.nFileSizeLow; |
143 |
|
|
#else |
144 |
|
|
size = lseek (pack_handle, 0, SEEK_END); |
145 |
|
|
#endif |
146 |
root |
1.1 |
|
147 |
root |
1.6 |
addr = u_mmap (pack_handle, size); |
148 |
|
|
if (!addr) |
149 |
root |
1.1 |
return 0; |
150 |
|
|
|
151 |
|
|
pack_unmap (); |
152 |
|
|
|
153 |
root |
1.6 |
pack_base = addr; |
154 |
|
|
pack_end = pack_base + size; |
155 |
root |
1.1 |
|
156 |
root |
1.8 |
struct u_pack_tail *tail; |
157 |
root |
1.1 |
|
158 |
|
|
tail = (void *)(pack_end - sizeof (*tail)); |
159 |
|
|
|
160 |
|
|
if (memcmp (tail->magic, TAIL_MAGIC, sizeof (TAIL_MAGIC) - 1)) |
161 |
|
|
return 0; |
162 |
|
|
|
163 |
root |
1.8 |
pack_cur = (struct u_pack_hdr *)(pack_end - u_32 (tail->size)); |
164 |
root |
1.1 |
|
165 |
root |
1.6 |
scratch = u_malloc (scratch_size = u_32 (tail->max_filesize)); |
166 |
|
|
if (!scratch) |
167 |
|
|
return 0; |
168 |
root |
1.2 |
|
169 |
root |
1.1 |
return 1; |
170 |
|
|
} |
171 |
|
|
|
172 |
|
|
static void |
173 |
|
|
exe_info (void) |
174 |
|
|
{ |
175 |
|
|
if (!pack_map ()) |
176 |
|
|
fatal ("unable to locate packfile in executable - executable corrupted?"); |
177 |
|
|
|
178 |
root |
1.8 |
if (pack_cur->type != U_T_META) |
179 |
root |
1.1 |
fatal ("unable to locate executable metadata - executable corrupted?"); |
180 |
|
|
|
181 |
|
|
strcpy (exe_id, PACK_NAME); |
182 |
|
|
} |
183 |
|
|
|
184 |
|
|
static void |
185 |
|
|
load (void) |
186 |
|
|
{ |
187 |
|
|
u_mkdir (datadir); |
188 |
|
|
|
189 |
|
|
strcpy (exe_dir, datadir); |
190 |
|
|
u_append (exe_dir, exe_id); |
191 |
|
|
u_mkdir (exe_dir); |
192 |
|
|
|
193 |
|
|
if (u_chdir (exe_dir)) |
194 |
|
|
fatal ("unable to change to application data directory"); |
195 |
|
|
|
196 |
|
|
u_handle h = u_open ("override"); |
197 |
root |
1.5 |
if (u_valid (h)) |
198 |
root |
1.1 |
{ |
199 |
|
|
u_handle oh = pack_handle; |
200 |
|
|
|
201 |
|
|
pack_handle = h; |
202 |
|
|
if (!pack_map ()) |
203 |
|
|
{ |
204 |
|
|
pack_handle = oh; |
205 |
|
|
oh = h; |
206 |
|
|
} |
207 |
|
|
|
208 |
|
|
u_close (oh); |
209 |
|
|
} |
210 |
|
|
|
211 |
root |
1.8 |
if (pack_cur->type != U_T_META) |
212 |
root |
1.1 |
fatal ("unable to locate override metadata"); |
213 |
|
|
|
214 |
|
|
strcpy (exe_ver, PACK_DATA); |
215 |
|
|
pack_next (); |
216 |
|
|
|
217 |
root |
1.4 |
for (;;) |
218 |
root |
1.1 |
{ |
219 |
root |
1.8 |
if (pack_cur->type == U_T_ENV) |
220 |
root |
1.4 |
u_setenv (PACK_NAME, PACK_DATA); |
221 |
root |
1.8 |
else if (pack_cur->type == U_T_ARG) |
222 |
root |
1.6 |
{ |
223 |
|
|
int len = u_16 (pack_cur->namelen) + 1; |
224 |
|
|
exe_argv [exe_argc++] = exe_args + exe_argo; |
225 |
|
|
memcpy (exe_args + exe_argo, PACK_NAME, len); |
226 |
|
|
exe_argo += len; |
227 |
|
|
} |
228 |
root |
1.4 |
else |
229 |
|
|
break; |
230 |
root |
1.1 |
|
231 |
|
|
pack_next (); |
232 |
|
|
} |
233 |
root |
1.4 |
|
234 |
|
|
done_env_arg: |
235 |
root |
1.1 |
strcpy (execdir, exe_dir); |
236 |
|
|
u_append (execdir, "i-"); |
237 |
|
|
strcat (execdir, exe_ver); |
238 |
|
|
|
239 |
root |
1.6 |
strcat (strcpy (tmppath, execdir), ".lck"); |
240 |
root |
1.7 |
lock_handle = u_lock (tmppath, 0, 1); |
241 |
root |
1.6 |
if (!lock_handle) |
242 |
root |
1.7 |
fatal ("unable to lock application instance"); |
243 |
root |
1.6 |
|
244 |
root |
1.1 |
if (access (execdir, F_OK)) |
245 |
|
|
{ |
246 |
|
|
// does not exist yet, so unpack and move |
247 |
|
|
tmpdir (exe_dir); |
248 |
|
|
|
249 |
|
|
if (u_chdir (tmppath)) |
250 |
|
|
fatal ("unable to change to new instance directory"); |
251 |
|
|
|
252 |
|
|
for (;;) |
253 |
|
|
{ |
254 |
|
|
switch (pack_cur->type) |
255 |
|
|
{ |
256 |
root |
1.8 |
case U_T_DIR: |
257 |
root |
1.1 |
u_mkdir (PACK_NAME); |
258 |
|
|
break; |
259 |
|
|
|
260 |
root |
1.8 |
case U_T_FILE: |
261 |
root |
1.1 |
{ |
262 |
root |
1.8 |
u_handle h = u_creat (PACK_NAME, pack_cur->flags & U_F_EXEC); |
263 |
root |
1.2 |
unsigned int dlen, len = u_32 (pack_cur->datalen); |
264 |
|
|
char *data = PACK_DATA; |
265 |
|
|
|
266 |
root |
1.8 |
if (pack_cur->flags & U_F_LZF) |
267 |
root |
1.6 |
if (dlen = lzf_decompress (data, len, scratch, scratch_size)) |
268 |
root |
1.2 |
{ |
269 |
|
|
data = scratch; |
270 |
|
|
len = dlen; |
271 |
|
|
} |
272 |
|
|
else |
273 |
|
|
fatal ("unable to uncompress file data - pack corrupted?"); |
274 |
root |
1.1 |
|
275 |
root |
1.5 |
if (!u_valid (h)) |
276 |
root |
1.1 |
fatal ("unable to unpack file from packfile - disk full?"); |
277 |
|
|
|
278 |
root |
1.2 |
if (u_write (h, data, len) != len) |
279 |
root |
1.1 |
fatal ("unable to unpack file from packfile - disk full?"); |
280 |
|
|
|
281 |
root |
1.4 |
u_fsync (h); |
282 |
root |
1.1 |
u_close (h); |
283 |
|
|
} |
284 |
|
|
break; |
285 |
|
|
|
286 |
root |
1.8 |
case U_T_NULL: |
287 |
root |
1.1 |
goto done; |
288 |
|
|
} |
289 |
|
|
|
290 |
|
|
pack_next (); |
291 |
|
|
} |
292 |
|
|
|
293 |
|
|
done: |
294 |
|
|
if (u_chdir (datadir)) |
295 |
|
|
fatal ("unable to change to data directory"); |
296 |
|
|
|
297 |
root |
1.3 |
u_sync (); |
298 |
|
|
|
299 |
root |
1.1 |
if (u_rename (tmppath, execdir)) |
300 |
|
|
deltree (tmppath); // if move fails, delete new, assume other process created it independently |
301 |
|
|
} |
302 |
|
|
|
303 |
|
|
pack_unmap (); |
304 |
|
|
u_close (pack_handle); |
305 |
|
|
|
306 |
root |
1.2 |
if (u_chdir (execdir)) |
307 |
|
|
fatal ("unable to change to application instance directory"); |
308 |
|
|
|
309 |
root |
1.1 |
u_setenv ("URLADER_VERSION", URLADER_VERSION); |
310 |
|
|
u_setenv ("URLADER_DATADIR", datadir); |
311 |
|
|
u_setenv ("URLADER_EXECDIR", execdir); |
312 |
|
|
u_setenv ("URLADER_EXE_ID" , exe_id); |
313 |
|
|
u_setenv ("URLADER_EXE_DIR", exe_dir); |
314 |
|
|
u_setenv ("URLADER_EXE_VER", exe_ver); |
315 |
|
|
|
316 |
root |
1.5 |
#if 0 |
317 |
root |
1.1 |
// yes, this is overkill |
318 |
|
|
u_setenv ("SHLIB_PATH" , execdir); // hpux |
319 |
|
|
u_setenv ("LIBPATH" , execdir); // aix |
320 |
|
|
u_setenv ("LD_LIBRARY_PATH" , execdir); // most elf systems |
321 |
|
|
u_setenv ("LD_LIBRARY_PATH_32", execdir); // solaris |
322 |
|
|
u_setenv ("LD_LIBRARY_PATH_64", execdir); // solaris |
323 |
|
|
u_setenv ("LD_LIBRARYN32_PATH", execdir); // irix |
324 |
|
|
u_setenv ("LD_LIBRARY64_PATH" , execdir); // irix |
325 |
|
|
u_setenv ("DYLD_LIBRARY_PATH" , execdir); // os sucks from apple |
326 |
root |
1.5 |
#endif |
327 |
root |
1.1 |
} |
328 |
|
|
|
329 |
root |
1.2 |
static void |
330 |
|
|
execute (void) |
331 |
|
|
{ |
332 |
|
|
exe_argv [exe_argc] = 0; |
333 |
root |
1.6 |
systemv (exe_argv); |
334 |
root |
1.2 |
} |
335 |
|
|
|
336 |
root |
1.1 |
#ifdef _WIN32 |
337 |
|
|
|
338 |
|
|
int APIENTRY |
339 |
|
|
WinMain (HINSTANCE hI, HINSTANCE hP, LPSTR argv, int command_show) |
340 |
|
|
{ |
341 |
|
|
if (!GetModuleFileName (hI, tmppath, sizeof (tmppath))) |
342 |
|
|
fatal ("unable to find executable pack"); |
343 |
|
|
|
344 |
root |
1.5 |
pack_handle = u_open (tmppath); |
345 |
|
|
if (!u_valid (pack_handle)) |
346 |
root |
1.1 |
fatal ("unable to open executable pack"); |
347 |
|
|
|
348 |
|
|
exe_info (); |
349 |
|
|
|
350 |
|
|
if (!GetCurrentDirectory (sizeof (currdir), currdir)) |
351 |
|
|
strcpy (currdir, "."); |
352 |
|
|
|
353 |
|
|
if (SHGetFolderPath (0, CSIDL_APPDATA | CSIDL_FLAG_CREATE, NULL, SHGFP_TYPE_CURRENT, datadir) != S_OK) |
354 |
|
|
fatal ("unable to find application data directory"); |
355 |
|
|
|
356 |
|
|
u_mkdir (datadir); |
357 |
|
|
u_append (datadir, URLADER); |
358 |
|
|
|
359 |
|
|
load (); |
360 |
|
|
execute (); |
361 |
|
|
|
362 |
|
|
return 0; |
363 |
|
|
} |
364 |
|
|
|
365 |
|
|
#else |
366 |
|
|
|
367 |
|
|
int |
368 |
|
|
main (int argc, char *argv[]) |
369 |
|
|
{ |
370 |
|
|
char *home = getenv ("HOME"); |
371 |
|
|
|
372 |
root |
1.5 |
pack_handle = u_open (argv [0]); |
373 |
|
|
if (!u_valid (pack_handle)) |
374 |
root |
1.1 |
fatal ("unable to open executable pack"); |
375 |
|
|
|
376 |
|
|
exe_info (); |
377 |
|
|
|
378 |
|
|
if (!home) |
379 |
|
|
{ |
380 |
|
|
struct passwd *pw; |
381 |
|
|
|
382 |
|
|
if ((pw = getpwuid (getuid ()))) |
383 |
|
|
home = pw->pw_dir; |
384 |
|
|
else |
385 |
|
|
home = "/tmp"; |
386 |
|
|
} |
387 |
|
|
|
388 |
|
|
if (!getcwd (currdir, sizeof (currdir))) |
389 |
|
|
strcpy (currdir, "."); |
390 |
|
|
|
391 |
|
|
u_mkdir (home); |
392 |
root |
1.6 |
//strcat (strcat (strcpy (datadir, home), "/."), URLADER); |
393 |
root |
1.1 |
sprintf (datadir, "%s/.%s", home, URLADER); |
394 |
|
|
u_mkdir (datadir); |
395 |
|
|
|
396 |
root |
1.5 |
#if 0 |
397 |
root |
1.1 |
if (gethostname (tmppath, sizeof (tmppath))) |
398 |
|
|
strcpy (tmppath, "default"); |
399 |
|
|
|
400 |
|
|
u_append (datadir, tmppath); |
401 |
root |
1.5 |
#endif |
402 |
root |
1.1 |
|
403 |
|
|
load (); |
404 |
|
|
execute (); |
405 |
|
|
|
406 |
|
|
return 0; |
407 |
|
|
} |
408 |
|
|
|
409 |
|
|
#endif |
410 |
|
|
|