ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/Urlader/urlader.c
Revision: 1.9
Committed: Mon Jan 2 09:23:03 2012 UTC (12 years, 4 months ago) by root
Content type: text/plain
Branch: MAIN
Changes since 1.8: +40 -92 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.6 scratch = u_malloc (scratch_size = u_32 (tail->max_filesize));
145     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     if (!pack_map ())
176     {
177     pack_handle = oh;
178     oh = h;
179     }
180    
181     u_close (oh);
182     }
183    
184 root 1.9 if (pack_cur->type != T_META)
185     u_fatal ("unable to locate override metadata");
186 root 1.1
187     strcpy (exe_ver, PACK_DATA);
188 root 1.9 u_set_exe_info ();
189 root 1.1 pack_next ();
190    
191 root 1.4 for (;;)
192 root 1.1 {
193 root 1.9 if (pack_cur->type == T_ENV)
194 root 1.4 u_setenv (PACK_NAME, PACK_DATA);
195 root 1.9 else if (pack_cur->type == T_ARG)
196 root 1.6 {
197     int len = u_16 (pack_cur->namelen) + 1;
198     exe_argv [exe_argc++] = exe_args + exe_argo;
199     memcpy (exe_args + exe_argo, PACK_NAME, len);
200     exe_argo += len;
201     }
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     exe_argv [exe_argc] = 0;
299 root 1.6 systemv (exe_argv);
300 root 1.2 }
301    
302 root 1.9 static void
303     doit (void)
304     {
305     u_set_datadir ();
306     u_mkdir (datadir);
307    
308     exe_info ();
309     u_set_exe_info ();
310    
311     load ();
312     execute ();
313     }
314    
315 root 1.1 #ifdef _WIN32
316    
317     int APIENTRY
318     WinMain (HINSTANCE hI, HINSTANCE hP, LPSTR argv, int command_show)
319     {
320     if (!GetModuleFileName (hI, tmppath, sizeof (tmppath)))
321 root 1.9 u_fatal ("unable to find executable pack");
322 root 1.1
323 root 1.5 pack_handle = u_open (tmppath);
324     if (!u_valid (pack_handle))
325 root 1.9 u_fatal ("unable to open executable pack");
326 root 1.1
327     if (!GetCurrentDirectory (sizeof (currdir), currdir))
328     strcpy (currdir, ".");
329    
330     return 0;
331     }
332    
333     #else
334    
335     int
336     main (int argc, char *argv[])
337     {
338 root 1.5 pack_handle = u_open (argv [0]);
339     if (!u_valid (pack_handle))
340 root 1.9 u_fatal ("unable to open executable pack");
341 root 1.1
342     if (!getcwd (currdir, sizeof (currdir)))
343     strcpy (currdir, ".");
344    
345 root 1.5 #if 0
346 root 1.1 if (gethostname (tmppath, sizeof (tmppath)))
347     strcpy (tmppath, "default");
348    
349     u_append (datadir, tmppath);
350 root 1.5 #endif
351 root 1.1
352 root 1.9 doit ();
353 root 1.1
354     return 0;
355     }
356    
357     #endif
358