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

# 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 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
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 systemv (const char *const argv[])
43 {
44 #ifdef _WIN32
45 _spawnv (P_WAIT, argv [0], argv);
46 #else
47 pid_t pid = fork ();
48
49 if (pid < 0)
50 u_fatal ("fork failure");
51
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 systemv (argv);
74 }
75
76 static char *pack_base, *pack_end;
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 struct u_pack_tail *tail;
136
137 tail = (void *)(pack_end - sizeof (*tail));
138
139 if (memcmp (tail->magic, TAIL_MAGIC, sizeof (TAIL_MAGIC) - 1))
140 return 0;
141
142 pack_cur = (struct u_pack_hdr *)(pack_end - u_32 (tail->size));
143
144 scratch = u_malloc (scratch_size = u_32 (tail->max_filesize));
145 if (!scratch)
146 return 0;
147
148 return 1;
149 }
150
151 static void
152 exe_info (void)
153 {
154 if (!pack_map ())
155 u_fatal ("unable to locate packfile in executable - executable corrupted?");
156
157 if (pack_cur->type != T_META)
158 u_fatal ("unable to locate executable metadata - executable corrupted?");
159
160 strcpy (exe_id, PACK_NAME);
161 }
162
163 static void
164 load (void)
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_handle = h;
175 if (!pack_map ())
176 {
177 pack_handle = oh;
178 oh = h;
179 }
180
181 u_close (oh);
182 }
183
184 if (pack_cur->type != T_META)
185 u_fatal ("unable to locate override metadata");
186
187 strcpy (exe_ver, PACK_DATA);
188 u_set_exe_info ();
189 pack_next ();
190
191 for (;;)
192 {
193 if (pack_cur->type == T_ENV)
194 u_setenv (PACK_NAME, PACK_DATA);
195 else if (pack_cur->type == T_ARG)
196 {
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 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 exe_argv [exe_argc] = 0;
299 systemv (exe_argv);
300 }
301
302 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 #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 u_fatal ("unable to find executable pack");
322
323 pack_handle = u_open (tmppath);
324 if (!u_valid (pack_handle))
325 u_fatal ("unable to open executable pack");
326
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 pack_handle = u_open (argv [0]);
339 if (!u_valid (pack_handle))
340 u_fatal ("unable to open executable pack");
341
342 if (!getcwd (currdir, sizeof (currdir)))
343 strcpy (currdir, ".");
344
345 #if 0
346 if (gethostname (tmppath, sizeof (tmppath)))
347 strcpy (tmppath, "default");
348
349 u_append (datadir, tmppath);
350 #endif
351
352 doit ();
353
354 return 0;
355 }
356
357 #endif
358