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

# 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_uncompressed));
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 u_setenv ("URLADER_OVERRIDE", "override");
177 else
178 {
179 pack_handle = oh;
180 oh = h;
181 }
182
183 u_close (oh);
184 }
185
186 if (pack_cur->type != T_META)
187 u_fatal ("unable to locate override metadata");
188
189 strcpy (exe_ver, PACK_DATA);
190 u_set_exe_info ();
191 pack_next ();
192
193 for (;;)
194 {
195 if (pack_cur->type == T_ENV)
196 u_setenv (PACK_NAME, PACK_DATA);
197 else if (pack_cur->type == T_ARG)
198 {
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 else
205 break;
206
207 pack_next ();
208 }
209
210 done_env_arg:
211
212 strcat (strcpy (tmppath, execdir), ".lck");
213 lock_handle = u_lock (tmppath, 0, 1);
214 if (!lock_handle)
215 u_fatal ("unable to lock application instance");
216
217 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 u_fatal ("unable to change to new instance directory");
224
225 for (;;)
226 {
227 switch (pack_cur->type)
228 {
229 case T_DIR:
230 u_mkdir (PACK_NAME);
231 break;
232
233 case T_FILE:
234 {
235 u_handle h = u_creat (PACK_NAME, pack_cur->flags & F_EXEC);
236 unsigned int dlen, len = u_32 (pack_cur->datalen);
237 char *data = PACK_DATA;
238
239 if (pack_cur->flags & F_LZF)
240 if (dlen = lzf_decompress (data, len, scratch, scratch_size))
241 {
242 data = scratch;
243 len = dlen;
244 }
245 else
246 u_fatal ("unable to uncompress file data - pack corrupted?");
247
248 if (!u_valid (h))
249 u_fatal ("unable to unpack file from packfile - disk full?");
250
251 if (u_write (h, data, len) != len)
252 u_fatal ("unable to unpack file from packfile - disk full?");
253
254 u_fsync (h);
255 u_close (h);
256 }
257 break;
258
259 case T_NULL:
260 goto done;
261 }
262
263 pack_next ();
264 }
265
266 done:
267 if (u_chdir (datadir))
268 u_fatal ("unable to change to data directory");
269
270 u_sync ();
271
272 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 if (u_chdir (execdir))
280 u_fatal ("unable to change to application instance directory");
281
282 u_setenv ("URLADER_VERSION", URLADER_VERSION);
283
284 #if 0
285 // 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 #endif
295 }
296
297 static void
298 execute (void)
299 {
300 exe_argv [exe_argc] = 0;
301 systemv (exe_argv);
302 }
303
304 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 #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 u_fatal ("unable to find executable pack");
324
325 pack_handle = u_open (tmppath);
326 if (!u_valid (pack_handle))
327 u_fatal ("unable to open executable pack");
328
329 if (!GetCurrentDirectory (sizeof (currdir), currdir))
330 strcpy (currdir, ".");
331
332 doit ();
333
334 return 0;
335 }
336
337 #else
338
339 int
340 main (int argc, char *argv[])
341 {
342 pack_handle = u_open (argv [0]);
343 if (!u_valid (pack_handle))
344 u_fatal ("unable to open executable pack");
345
346 if (!getcwd (currdir, sizeof (currdir)))
347 strcpy (currdir, ".");
348
349 #if 0
350 /* intersperse hostname, for whatever reason */
351
352 if (gethostname (tmppath, sizeof (tmppath)))
353 strcpy (tmppath, "default");
354
355 u_append (datadir, tmppath);
356 #endif
357
358 doit ();
359
360 return 0;
361 }
362
363 #endif
364