ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/Urlader/urlader.c
Revision: 1.12
Committed: Fri Jan 6 07:56:36 2012 UTC (12 years, 4 months ago) by root
Content type: text/plain
Branch: MAIN
CVS Tags: rel-0_2
Changes since 1.11: +50 -35 lines
Log Message:
*** empty log message ***

File Contents

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