ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/Urlader/urlader.c
Revision: 1.11
Committed: Thu Jan 5 06:00:13 2012 UTC (12 years, 4 months ago) by root
Content type: text/plain
Branch: MAIN
Changes since 1.10: +7 -1 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.6 static const char *exe_argv[MAX_ARGC];
20     static char exe_args[MAX_ARGS]; /* actual arguments strings copied here */
21     static unsigned int exe_argo;
22 root 1.1
23     static void
24     tmpdir (const char *dir)
25     {
26     static int cnt;
27    
28     for (;;)
29     {
30     // #ifdef _WIN32
31     // sprintf (tmppath, "%s/%x_%x.tmp", dir, (unsigned int)GetCurrentProcessId (), ++cnt);
32     // #else
33     sprintf (tmppath, "%s/t-%x_%x.tmp", dir, (unsigned int)getpid () , ++cnt);
34     // #endif
35    
36     if (!u_mkdir (tmppath))
37     return;
38     }
39     }
40    
41     static void
42 root 1.6 systemv (const char *const argv[])
43 root 1.1 {
44     #ifdef _WIN32
45     _spawnv (P_WAIT, argv [0], argv);
46     #else
47 root 1.6 pid_t pid = fork ();
48 root 1.1
49     if (pid < 0)
50 root 1.9 u_fatal ("fork failure");
51 root 1.1
52     if (!pid)
53     {
54     execv (argv [0], (void *)argv);
55     _exit (124);
56     }
57    
58     int status;
59     waitpid (pid, &status, 0);
60     #endif
61     }
62    
63     static void
64     deltree (const char *path)
65     {
66     #ifdef _WIN32
67     char buf[MAX_PATH * 2 + 64];
68     const char *argv[] = { getenv ("COMSPEC"), "/c", "rd", "/s", "/q", buf, 0 };
69     sprintf (buf, "\"%s\"", path);
70     #else
71     const char *argv[] = { "/bin/rm", "-rf", path, 0 };
72     #endif
73 root 1.6 systemv (argv);
74 root 1.1 }
75    
76     static char *pack_base, *pack_end;
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     pack_unmap ();
131    
132 root 1.6 pack_base = addr;
133     pack_end = pack_base + size;
134 root 1.1
135 root 1.8 struct u_pack_tail *tail;
136 root 1.1
137     tail = (void *)(pack_end - sizeof (*tail));
138    
139     if (memcmp (tail->magic, TAIL_MAGIC, sizeof (TAIL_MAGIC) - 1))
140     return 0;
141    
142 root 1.8 pack_cur = (struct u_pack_hdr *)(pack_end - u_32 (tail->size));
143 root 1.1
144 root 1.10 scratch = u_malloc (scratch_size = u_32 (tail->max_uncompressed));
145 root 1.6 if (!scratch)
146     return 0;
147 root 1.2
148 root 1.1 return 1;
149     }
150    
151     static void
152     exe_info (void)
153     {
154     if (!pack_map ())
155 root 1.9 u_fatal ("unable to locate packfile in executable - executable corrupted?");
156 root 1.1
157 root 1.9 if (pack_cur->type != T_META)
158     u_fatal ("unable to locate executable metadata - executable corrupted?");
159 root 1.1
160     strcpy (exe_id, PACK_NAME);
161     }
162    
163     static void
164     load (void)
165     {
166     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     pack_handle = h;
175 root 1.11 if (pack_map ())
176     u_setenv ("URLADER_OVERRIDE", "override");
177     else
178 root 1.1 {
179     pack_handle = oh;
180     oh = h;
181     }
182    
183     u_close (oh);
184     }
185    
186 root 1.9 if (pack_cur->type != T_META)
187     u_fatal ("unable to locate override metadata");
188 root 1.1
189     strcpy (exe_ver, PACK_DATA);
190 root 1.9 u_set_exe_info ();
191 root 1.1 pack_next ();
192    
193 root 1.4 for (;;)
194 root 1.1 {
195 root 1.9 if (pack_cur->type == T_ENV)
196 root 1.4 u_setenv (PACK_NAME, PACK_DATA);
197 root 1.9 else if (pack_cur->type == T_ARG)
198 root 1.6 {
199     int len = u_16 (pack_cur->namelen) + 1;
200     exe_argv [exe_argc++] = exe_args + exe_argo;
201     memcpy (exe_args + exe_argo, PACK_NAME, len);
202     exe_argo += len;
203     }
204 root 1.4 else
205     break;
206 root 1.1
207     pack_next ();
208     }
209 root 1.4
210     done_env_arg:
211 root 1.1
212 root 1.6 strcat (strcpy (tmppath, execdir), ".lck");
213 root 1.7 lock_handle = u_lock (tmppath, 0, 1);
214 root 1.6 if (!lock_handle)
215 root 1.9 u_fatal ("unable to lock application instance");
216 root 1.6
217 root 1.1 if (access (execdir, F_OK))
218     {
219     // does not exist yet, so unpack and move
220     tmpdir (exe_dir);
221    
222     if (u_chdir (tmppath))
223 root 1.9 u_fatal ("unable to change to new instance directory");
224 root 1.1
225     for (;;)
226     {
227     switch (pack_cur->type)
228     {
229 root 1.9 case T_DIR:
230 root 1.1 u_mkdir (PACK_NAME);
231     break;
232    
233 root 1.9 case T_FILE:
234 root 1.1 {
235 root 1.9 u_handle h = u_creat (PACK_NAME, pack_cur->flags & F_EXEC);
236 root 1.2 unsigned int dlen, len = u_32 (pack_cur->datalen);
237     char *data = PACK_DATA;
238    
239 root 1.9 if (pack_cur->flags & F_LZF)
240 root 1.6 if (dlen = lzf_decompress (data, len, scratch, scratch_size))
241 root 1.2 {
242     data = scratch;
243     len = dlen;
244     }
245     else
246 root 1.9 u_fatal ("unable to uncompress file data - pack corrupted?");
247 root 1.1
248 root 1.5 if (!u_valid (h))
249 root 1.9 u_fatal ("unable to unpack file from packfile - disk full?");
250 root 1.1
251 root 1.2 if (u_write (h, data, len) != len)
252 root 1.9 u_fatal ("unable to unpack file from packfile - disk full?");
253 root 1.1
254 root 1.4 u_fsync (h);
255 root 1.1 u_close (h);
256     }
257     break;
258    
259 root 1.9 case T_NULL:
260 root 1.1 goto done;
261     }
262    
263     pack_next ();
264     }
265    
266     done:
267     if (u_chdir (datadir))
268 root 1.9 u_fatal ("unable to change to data directory");
269 root 1.1
270 root 1.3 u_sync ();
271    
272 root 1.1 if (u_rename (tmppath, execdir))
273     deltree (tmppath); // if move fails, delete new, assume other process created it independently
274     }
275    
276     pack_unmap ();
277     u_close (pack_handle);
278    
279 root 1.2 if (u_chdir (execdir))
280 root 1.9 u_fatal ("unable to change to application instance directory");
281 root 1.2
282 root 1.1 u_setenv ("URLADER_VERSION", URLADER_VERSION);
283    
284 root 1.5 #if 0
285 root 1.1 // yes, this is overkill
286     u_setenv ("SHLIB_PATH" , execdir); // hpux
287     u_setenv ("LIBPATH" , execdir); // aix
288     u_setenv ("LD_LIBRARY_PATH" , execdir); // most elf systems
289     u_setenv ("LD_LIBRARY_PATH_32", execdir); // solaris
290     u_setenv ("LD_LIBRARY_PATH_64", execdir); // solaris
291     u_setenv ("LD_LIBRARYN32_PATH", execdir); // irix
292     u_setenv ("LD_LIBRARY64_PATH" , execdir); // irix
293     u_setenv ("DYLD_LIBRARY_PATH" , execdir); // os sucks from apple
294 root 1.5 #endif
295 root 1.1 }
296    
297 root 1.2 static void
298     execute (void)
299     {
300     exe_argv [exe_argc] = 0;
301 root 1.6 systemv (exe_argv);
302 root 1.2 }
303    
304 root 1.9 static void
305     doit (void)
306     {
307     u_set_datadir ();
308     u_mkdir (datadir);
309    
310     exe_info ();
311     u_set_exe_info ();
312    
313     load ();
314     execute ();
315     }
316    
317 root 1.1 #ifdef _WIN32
318    
319     int APIENTRY
320     WinMain (HINSTANCE hI, HINSTANCE hP, LPSTR argv, int command_show)
321     {
322     if (!GetModuleFileName (hI, tmppath, sizeof (tmppath)))
323 root 1.9 u_fatal ("unable to find executable pack");
324 root 1.1
325 root 1.5 pack_handle = u_open (tmppath);
326     if (!u_valid (pack_handle))
327 root 1.9 u_fatal ("unable to open executable pack");
328 root 1.1
329     if (!GetCurrentDirectory (sizeof (currdir), currdir))
330     strcpy (currdir, ".");
331    
332 root 1.11 doit ();
333    
334 root 1.1 return 0;
335     }
336    
337     #else
338    
339     int
340     main (int argc, char *argv[])
341     {
342 root 1.5 pack_handle = u_open (argv [0]);
343     if (!u_valid (pack_handle))
344 root 1.9 u_fatal ("unable to open executable pack");
345 root 1.1
346     if (!getcwd (currdir, sizeof (currdir)))
347     strcpy (currdir, ".");
348    
349 root 1.5 #if 0
350 root 1.11 /* intersperse hostname, for whatever reason */
351    
352 root 1.1 if (gethostname (tmppath, sizeof (tmppath)))
353     strcpy (tmppath, "default");
354    
355     u_append (datadir, tmppath);
356 root 1.5 #endif
357 root 1.1
358 root 1.9 doit ();
359 root 1.1
360     return 0;
361     }
362    
363     #endif
364