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

# User Rev Content
1 root 1.9 #include "urlib.h"
2 root 1.8 #include "urlib.c"
3 root 1.6
4 root 1.1 #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 root 1.2 #include "liblzf/lzf_d.c"
12 root 1.1
13 root 1.6 /* some simple? dynamic memory management for paths might save ltos of ram */
14 root 1.1 static u_handle pack_handle;
15 root 1.6 static u_handle lock_handle;
16 root 1.1 static char tmppath[MAX_PATH];
17    
18     static int exe_argc;
19 root 1.12 static u_dynbuf exe_argv;
20     static u_dynbuf exe_args; /* actual arguments strings copied here */
21 root 1.1
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 root 1.6 systemv (const char *const argv[])
42 root 1.1 {
43     #ifdef _WIN32
44     _spawnv (P_WAIT, argv [0], argv);
45     #else
46 root 1.6 pid_t pid = fork ();
47 root 1.1
48     if (pid < 0)
49 root 1.9 u_fatal ("fork failure");
50 root 1.1
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 root 1.6 systemv (argv);
73 root 1.1 }
74    
75     static char *pack_base, *pack_end;
76 root 1.12 static struct u_pack_tail *pack_tail;
77 root 1.8 static struct u_pack_hdr *pack_cur;
78 root 1.2 static char *scratch;
79 root 1.6 static unsigned int scratch_size;
80 root 1.1
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 root 1.8 pack_cur = (struct u_pack_hdr *)(PACK_DATA + d);
91 root 1.1 }
92    
93     static void
94     pack_unmap (void)
95     {
96 root 1.6 if (pack_base)
97     {
98     u_munmap (pack_base, pack_end - pack_base);
99     pack_base = 0;
100     }
101 root 1.1
102 root 1.6 if (scratch)
103     {
104     u_free (scratch, scratch_size);
105     scratch = 0;
106     }
107 root 1.1 }
108    
109     static int
110     pack_map (void)
111     {
112 root 1.6 char *addr;
113     unsigned int size;
114    
115 root 1.1 #ifdef _WIN32
116     BY_HANDLE_FILE_INFORMATION fi;
117    
118     if (!GetFileInformationByHandle (pack_handle, &fi))
119     return 0;
120    
121 root 1.6 size = fi.nFileSizeLow;
122     #else
123     size = lseek (pack_handle, 0, SEEK_END);
124     #endif
125 root 1.1
126 root 1.6 addr = u_mmap (pack_handle, size);
127     if (!addr)
128 root 1.1 return 0;
129    
130 root 1.12 /*pack_unmap ();*/
131 root 1.1
132 root 1.6 pack_base = addr;
133     pack_end = pack_base + size;
134 root 1.1
135 root 1.12 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 root 1.1
140 root 1.12 pack_cur = (struct u_pack_hdr *)(pack_end - u_32 (pack_tail->size));
141 root 1.1
142 root 1.12 if (pack_cur->type != T_META)
143 root 1.1 return 0;
144    
145 root 1.12 scratch = u_malloc (scratch_size = u_32 (pack_tail->max_uncompressed));
146 root 1.6 if (!scratch)
147     return 0;
148 root 1.2
149 root 1.1 return 1;
150     }
151    
152     static void
153 root 1.12 add_arg (char *arg, unsigned int len)
154 root 1.1 {
155 root 1.12 char *addr = u_dynbuf_append (&exe_args, arg, len);
156     u_dynbuf_append (&exe_argv, &addr, sizeof (addr));
157 root 1.1 }
158    
159     static void
160     load (void)
161     {
162 root 1.12 strcpy (exe_id , PACK_NAME);
163     strcpy (exe_ver, PACK_DATA);
164     u_set_exe_info ();
165    
166 root 1.1 if (u_chdir (exe_dir))
167 root 1.9 u_fatal ("unable to change to application data directory");
168 root 1.1
169     u_handle h = u_open ("override");
170 root 1.5 if (u_valid (h))
171 root 1.1 {
172     u_handle oh = pack_handle;
173    
174 root 1.12 pack_unmap ();
175 root 1.1 pack_handle = h;
176 root 1.12
177     if (pack_map ()
178     && strcmp (exe_id , PACK_NAME) == 0
179     && strcmp (exe_ver, PACK_DATA) <= 0)
180 root 1.11 u_setenv ("URLADER_OVERRIDE", "override");
181     else
182 root 1.1 {
183 root 1.12 pack_unmap ();
184 root 1.1 pack_handle = oh;
185     oh = h;
186 root 1.12 pack_map ();
187 root 1.1 }
188    
189     u_close (oh);
190     }
191    
192     strcpy (exe_ver, PACK_DATA);
193 root 1.9 u_set_exe_info ();
194 root 1.1 pack_next ();
195    
196 root 1.4 for (;;)
197 root 1.1 {
198 root 1.9 if (pack_cur->type == T_ENV)
199 root 1.4 u_setenv (PACK_NAME, PACK_DATA);
200 root 1.9 else if (pack_cur->type == T_ARG)
201 root 1.12 add_arg (PACK_NAME, u_16 (pack_cur->namelen) + 1);
202 root 1.4 else
203     break;
204 root 1.1
205     pack_next ();
206     }
207 root 1.4
208     done_env_arg:
209 root 1.1
210 root 1.6 strcat (strcpy (tmppath, execdir), ".lck");
211 root 1.7 lock_handle = u_lock (tmppath, 0, 1);
212 root 1.6 if (!lock_handle)
213 root 1.9 u_fatal ("unable to lock application instance");
214 root 1.6
215 root 1.1 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 root 1.9 u_fatal ("unable to change to new instance directory");
222 root 1.1
223     for (;;)
224     {
225     switch (pack_cur->type)
226     {
227 root 1.9 case T_DIR:
228 root 1.1 u_mkdir (PACK_NAME);
229     break;
230    
231 root 1.9 case T_FILE:
232 root 1.1 {
233 root 1.9 u_handle h = u_creat (PACK_NAME, pack_cur->flags & F_EXEC);
234 root 1.2 unsigned int dlen, len = u_32 (pack_cur->datalen);
235     char *data = PACK_DATA;
236    
237 root 1.9 if (pack_cur->flags & F_LZF)
238 root 1.6 if (dlen = lzf_decompress (data, len, scratch, scratch_size))
239 root 1.2 {
240     data = scratch;
241     len = dlen;
242     }
243     else
244 root 1.9 u_fatal ("unable to uncompress file data - pack corrupted?");
245 root 1.1
246 root 1.5 if (!u_valid (h))
247 root 1.9 u_fatal ("unable to unpack file from packfile - disk full?");
248 root 1.1
249 root 1.2 if (u_write (h, data, len) != len)
250 root 1.9 u_fatal ("unable to unpack file from packfile - disk full?");
251 root 1.1
252 root 1.4 u_fsync (h);
253 root 1.1 u_close (h);
254     }
255     break;
256    
257 root 1.9 case T_NULL:
258 root 1.1 goto done;
259     }
260    
261     pack_next ();
262     }
263    
264     done:
265     if (u_chdir (datadir))
266 root 1.9 u_fatal ("unable to change to data directory");
267 root 1.1
268 root 1.3 u_sync ();
269    
270 root 1.1 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 root 1.2 if (u_chdir (execdir))
278 root 1.9 u_fatal ("unable to change to application instance directory");
279 root 1.2
280 root 1.1 u_setenv ("URLADER_VERSION", URLADER_VERSION);
281    
282 root 1.5 #if 0
283 root 1.1 // 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 root 1.5 #endif
293 root 1.1 }
294    
295 root 1.2 static void
296     execute (void)
297     {
298 root 1.12 char *null = 0;
299     u_dynbuf_append (&exe_argv, &null, sizeof (null));
300     systemv ((const char *const *)exe_argv.addr);
301 root 1.2 }
302    
303 root 1.12 // this argc/argv is without argv [0]
304 root 1.9 static void
305 root 1.12 doit (int argc, char *argv[])
306 root 1.9 {
307 root 1.12 int i;
308    
309     u_setenv ("URLADER_CURRDIR", currdir);
310    
311 root 1.9 u_set_datadir ();
312     u_mkdir (datadir);
313    
314 root 1.12 if (!pack_map ())
315     u_fatal ("unable to map pack file - executable corrupted?");
316 root 1.9
317     load ();
318 root 1.12
319     while (argc--)
320     {
321     add_arg (*argv, strlen (*argv) + 1);
322     ++argv;
323     }
324    
325 root 1.9 execute ();
326     }
327    
328 root 1.1 #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 root 1.9 u_fatal ("unable to find executable pack");
335 root 1.1
336 root 1.12 u_setenv ("URLADER_EXEPATH", tmppath);
337    
338 root 1.5 pack_handle = u_open (tmppath);
339     if (!u_valid (pack_handle))
340 root 1.9 u_fatal ("unable to open executable pack");
341 root 1.1
342     if (!GetCurrentDirectory (sizeof (currdir), currdir))
343     strcpy (currdir, ".");
344    
345 root 1.12 doit (1, &argv);
346 root 1.11
347 root 1.1 return 0;
348     }
349    
350     #else
351    
352     int
353     main (int argc, char *argv[])
354     {
355 root 1.12 u_setenv ("URLADER_EXEPATH", argv [0]);
356    
357 root 1.5 pack_handle = u_open (argv [0]);
358     if (!u_valid (pack_handle))
359 root 1.9 u_fatal ("unable to open executable pack");
360 root 1.1
361     if (!getcwd (currdir, sizeof (currdir)))
362     strcpy (currdir, ".");
363    
364 root 1.5 #if 0
365 root 1.11 /* intersperse hostname, for whatever reason */
366    
367 root 1.1 if (gethostname (tmppath, sizeof (tmppath)))
368     strcpy (tmppath, "default");
369    
370     u_append (datadir, tmppath);
371 root 1.5 #endif
372 root 1.1
373 root 1.12 doit (argc - 1, argv + 1);
374 root 1.1
375     return 0;
376     }
377    
378     #endif
379