ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/Urlader/urlader.c
Revision: 1.8
Committed: Fri Dec 30 23:34:08 2011 UTC (12 years, 4 months ago) by root
Content type: text/plain
Branch: MAIN
Changes since 1.7: +15 -285 lines
Log Message:
*** empty log message ***

File Contents

# Content
1 #include "urlib.c"
2
3 #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 #include "liblzf/lzf_d.c"
11
12 #include "urlib.h"
13
14 /* some simple? dynamic memory management for paths might save ltos of ram */
15 static u_handle pack_handle;
16 static u_handle lock_handle;
17 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 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
30 static void
31 fatal (const char *msg)
32 {
33 #ifdef _WIN32
34 MessageBox (0, msg, URLADER, 0);
35 #else
36 write (2, URLADER ": ", sizeof (URLADER ": ") - 1);
37 write (2, msg, strlen (msg));
38 write (2, "\n", 1);
39 #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 systemv (const char *const argv[])
64 {
65 #ifdef _WIN32
66 _spawnv (P_WAIT, argv [0], argv);
67 #else
68 pid_t pid = fork ();
69
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 systemv (argv);
95 }
96
97 static char *pack_base, *pack_end;
98 static struct u_pack_hdr *pack_cur;
99 static char *scratch;
100 static unsigned int scratch_size;
101
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 pack_cur = (struct u_pack_hdr *)(PACK_DATA + d);
112 }
113
114 static void
115 pack_unmap (void)
116 {
117 if (pack_base)
118 {
119 u_munmap (pack_base, pack_end - pack_base);
120 pack_base = 0;
121 }
122
123 if (scratch)
124 {
125 u_free (scratch, scratch_size);
126 scratch = 0;
127 }
128 }
129
130 static int
131 pack_map (void)
132 {
133 char *addr;
134 unsigned int size;
135
136 #ifdef _WIN32
137 BY_HANDLE_FILE_INFORMATION fi;
138
139 if (!GetFileInformationByHandle (pack_handle, &fi))
140 return 0;
141
142 size = fi.nFileSizeLow;
143 #else
144 size = lseek (pack_handle, 0, SEEK_END);
145 #endif
146
147 addr = u_mmap (pack_handle, size);
148 if (!addr)
149 return 0;
150
151 pack_unmap ();
152
153 pack_base = addr;
154 pack_end = pack_base + size;
155
156 struct u_pack_tail *tail;
157
158 tail = (void *)(pack_end - sizeof (*tail));
159
160 if (memcmp (tail->magic, TAIL_MAGIC, sizeof (TAIL_MAGIC) - 1))
161 return 0;
162
163 pack_cur = (struct u_pack_hdr *)(pack_end - u_32 (tail->size));
164
165 scratch = u_malloc (scratch_size = u_32 (tail->max_filesize));
166 if (!scratch)
167 return 0;
168
169 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 if (pack_cur->type != U_T_META)
179 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 if (u_valid (h))
198 {
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 if (pack_cur->type != U_T_META)
212 fatal ("unable to locate override metadata");
213
214 strcpy (exe_ver, PACK_DATA);
215 pack_next ();
216
217 for (;;)
218 {
219 if (pack_cur->type == U_T_ENV)
220 u_setenv (PACK_NAME, PACK_DATA);
221 else if (pack_cur->type == U_T_ARG)
222 {
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 else
229 break;
230
231 pack_next ();
232 }
233
234 done_env_arg:
235 strcpy (execdir, exe_dir);
236 u_append (execdir, "i-");
237 strcat (execdir, exe_ver);
238
239 strcat (strcpy (tmppath, execdir), ".lck");
240 lock_handle = u_lock (tmppath, 0, 1);
241 if (!lock_handle)
242 fatal ("unable to lock application instance");
243
244 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 case U_T_DIR:
257 u_mkdir (PACK_NAME);
258 break;
259
260 case U_T_FILE:
261 {
262 u_handle h = u_creat (PACK_NAME, pack_cur->flags & U_F_EXEC);
263 unsigned int dlen, len = u_32 (pack_cur->datalen);
264 char *data = PACK_DATA;
265
266 if (pack_cur->flags & U_F_LZF)
267 if (dlen = lzf_decompress (data, len, scratch, scratch_size))
268 {
269 data = scratch;
270 len = dlen;
271 }
272 else
273 fatal ("unable to uncompress file data - pack corrupted?");
274
275 if (!u_valid (h))
276 fatal ("unable to unpack file from packfile - disk full?");
277
278 if (u_write (h, data, len) != len)
279 fatal ("unable to unpack file from packfile - disk full?");
280
281 u_fsync (h);
282 u_close (h);
283 }
284 break;
285
286 case U_T_NULL:
287 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 u_sync ();
298
299 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 if (u_chdir (execdir))
307 fatal ("unable to change to application instance directory");
308
309 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 #if 0
317 // 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 #endif
327 }
328
329 static void
330 execute (void)
331 {
332 exe_argv [exe_argc] = 0;
333 systemv (exe_argv);
334 }
335
336 #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 pack_handle = u_open (tmppath);
345 if (!u_valid (pack_handle))
346 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 pack_handle = u_open (argv [0]);
373 if (!u_valid (pack_handle))
374 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 //strcat (strcat (strcpy (datadir, home), "/."), URLADER);
393 sprintf (datadir, "%s/.%s", home, URLADER);
394 u_mkdir (datadir);
395
396 #if 0
397 if (gethostname (tmppath, sizeof (tmppath)))
398 strcpy (tmppath, "default");
399
400 u_append (datadir, tmppath);
401 #endif
402
403 load ();
404 execute ();
405
406 return 0;
407 }
408
409 #endif
410