ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/Urlader/urlader.c
Revision: 1.8
Committed: Fri Dec 30 23:34:08 2011 UTC (12 years, 4 months ago) by root
Content type: text/plain
Branch: MAIN
Changes since 1.7: +15 -285 lines
Log Message:
*** empty log message ***

File Contents

# User Rev Content
1 root 1.8 #include "urlib.c"
2 root 1.6
3 root 1.1 #include <stdio.h>
4     #include <stdlib.h>
5     #include <unistd.h>
6     #include <errno.h>
7     #include <string.h>
8     #include <time.h>
9    
10 root 1.2 #include "liblzf/lzf_d.c"
11 root 1.1
12 root 1.8 #include "urlib.h"
13 root 1.1
14 root 1.6 /* some simple? dynamic memory management for paths might save ltos of ram */
15 root 1.1 static u_handle pack_handle;
16 root 1.6 static u_handle lock_handle;
17 root 1.1 static char tmppath[MAX_PATH];
18     static char currdir[MAX_PATH];
19     static char datadir[MAX_PATH]; // %AppData%/urlader
20     static char exe_dir[MAX_PATH]; // %AppData%/urlader/EXE_ID
21     static char execdir[MAX_PATH]; // %AppData%/urlader/EXE_ID/EXE_VER
22     static char exe_id[MAX_PATH];
23     static char exe_ver[MAX_PATH];
24    
25     static int exe_argc;
26 root 1.6 static const char *exe_argv[MAX_ARGC];
27     static char exe_args[MAX_ARGS]; /* actual arguments strings copied here */
28     static unsigned int exe_argo;
29 root 1.1
30     static void
31     fatal (const char *msg)
32     {
33     #ifdef _WIN32
34     MessageBox (0, msg, URLADER, 0);
35     #else
36 root 1.6 write (2, URLADER ": ", sizeof (URLADER ": ") - 1);
37     write (2, msg, strlen (msg));
38     write (2, "\n", 1);
39 root 1.1 #endif
40    
41     _exit (1);
42     }
43    
44     static void
45     tmpdir (const char *dir)
46     {
47     static int cnt;
48    
49     for (;;)
50     {
51     // #ifdef _WIN32
52     // sprintf (tmppath, "%s/%x_%x.tmp", dir, (unsigned int)GetCurrentProcessId (), ++cnt);
53     // #else
54     sprintf (tmppath, "%s/t-%x_%x.tmp", dir, (unsigned int)getpid () , ++cnt);
55     // #endif
56    
57     if (!u_mkdir (tmppath))
58     return;
59     }
60     }
61    
62     static void
63 root 1.6 systemv (const char *const argv[])
64 root 1.1 {
65     #ifdef _WIN32
66     _spawnv (P_WAIT, argv [0], argv);
67     #else
68 root 1.6 pid_t pid = fork ();
69 root 1.1
70     if (pid < 0)
71     fatal ("fork failure");
72    
73     if (!pid)
74     {
75     execv (argv [0], (void *)argv);
76     _exit (124);
77     }
78    
79     int status;
80     waitpid (pid, &status, 0);
81     #endif
82     }
83    
84     static void
85     deltree (const char *path)
86     {
87     #ifdef _WIN32
88     char buf[MAX_PATH * 2 + 64];
89     const char *argv[] = { getenv ("COMSPEC"), "/c", "rd", "/s", "/q", buf, 0 };
90     sprintf (buf, "\"%s\"", path);
91     #else
92     const char *argv[] = { "/bin/rm", "-rf", path, 0 };
93     #endif
94 root 1.6 systemv (argv);
95 root 1.1 }
96    
97     static char *pack_base, *pack_end;
98 root 1.8 static struct u_pack_hdr *pack_cur;
99 root 1.2 static char *scratch;
100 root 1.6 static unsigned int scratch_size;
101 root 1.1
102     #define PACK_NAME ((char *)(pack_cur + 1))
103     #define PACK_DATA (PACK_NAME + u_16 (pack_cur->namelen) + 1)
104     #define PACK_VALID pack_cur->type
105    
106     static void
107     pack_next (void)
108     {
109     unsigned int d = u_32 (pack_cur->datalen);
110    
111 root 1.8 pack_cur = (struct u_pack_hdr *)(PACK_DATA + d);
112 root 1.1 }
113    
114     static void
115     pack_unmap (void)
116     {
117 root 1.6 if (pack_base)
118     {
119     u_munmap (pack_base, pack_end - pack_base);
120     pack_base = 0;
121     }
122 root 1.1
123 root 1.6 if (scratch)
124     {
125     u_free (scratch, scratch_size);
126     scratch = 0;
127     }
128 root 1.1 }
129    
130     static int
131     pack_map (void)
132     {
133 root 1.6 char *addr;
134     unsigned int size;
135    
136 root 1.1 #ifdef _WIN32
137     BY_HANDLE_FILE_INFORMATION fi;
138    
139     if (!GetFileInformationByHandle (pack_handle, &fi))
140     return 0;
141    
142 root 1.6 size = fi.nFileSizeLow;
143     #else
144     size = lseek (pack_handle, 0, SEEK_END);
145     #endif
146 root 1.1
147 root 1.6 addr = u_mmap (pack_handle, size);
148     if (!addr)
149 root 1.1 return 0;
150    
151     pack_unmap ();
152    
153 root 1.6 pack_base = addr;
154     pack_end = pack_base + size;
155 root 1.1
156 root 1.8 struct u_pack_tail *tail;
157 root 1.1
158     tail = (void *)(pack_end - sizeof (*tail));
159    
160     if (memcmp (tail->magic, TAIL_MAGIC, sizeof (TAIL_MAGIC) - 1))
161     return 0;
162    
163 root 1.8 pack_cur = (struct u_pack_hdr *)(pack_end - u_32 (tail->size));
164 root 1.1
165 root 1.6 scratch = u_malloc (scratch_size = u_32 (tail->max_filesize));
166     if (!scratch)
167     return 0;
168 root 1.2
169 root 1.1 return 1;
170     }
171    
172     static void
173     exe_info (void)
174     {
175     if (!pack_map ())
176     fatal ("unable to locate packfile in executable - executable corrupted?");
177    
178 root 1.8 if (pack_cur->type != U_T_META)
179 root 1.1 fatal ("unable to locate executable metadata - executable corrupted?");
180    
181     strcpy (exe_id, PACK_NAME);
182     }
183    
184     static void
185     load (void)
186     {
187     u_mkdir (datadir);
188    
189     strcpy (exe_dir, datadir);
190     u_append (exe_dir, exe_id);
191     u_mkdir (exe_dir);
192    
193     if (u_chdir (exe_dir))
194     fatal ("unable to change to application data directory");
195    
196     u_handle h = u_open ("override");
197 root 1.5 if (u_valid (h))
198 root 1.1 {
199     u_handle oh = pack_handle;
200    
201     pack_handle = h;
202     if (!pack_map ())
203     {
204     pack_handle = oh;
205     oh = h;
206     }
207    
208     u_close (oh);
209     }
210    
211 root 1.8 if (pack_cur->type != U_T_META)
212 root 1.1 fatal ("unable to locate override metadata");
213    
214     strcpy (exe_ver, PACK_DATA);
215     pack_next ();
216    
217 root 1.4 for (;;)
218 root 1.1 {
219 root 1.8 if (pack_cur->type == U_T_ENV)
220 root 1.4 u_setenv (PACK_NAME, PACK_DATA);
221 root 1.8 else if (pack_cur->type == U_T_ARG)
222 root 1.6 {
223     int len = u_16 (pack_cur->namelen) + 1;
224     exe_argv [exe_argc++] = exe_args + exe_argo;
225     memcpy (exe_args + exe_argo, PACK_NAME, len);
226     exe_argo += len;
227     }
228 root 1.4 else
229     break;
230 root 1.1
231     pack_next ();
232     }
233 root 1.4
234     done_env_arg:
235 root 1.1 strcpy (execdir, exe_dir);
236     u_append (execdir, "i-");
237     strcat (execdir, exe_ver);
238    
239 root 1.6 strcat (strcpy (tmppath, execdir), ".lck");
240 root 1.7 lock_handle = u_lock (tmppath, 0, 1);
241 root 1.6 if (!lock_handle)
242 root 1.7 fatal ("unable to lock application instance");
243 root 1.6
244 root 1.1 if (access (execdir, F_OK))
245     {
246     // does not exist yet, so unpack and move
247     tmpdir (exe_dir);
248    
249     if (u_chdir (tmppath))
250     fatal ("unable to change to new instance directory");
251    
252     for (;;)
253     {
254     switch (pack_cur->type)
255     {
256 root 1.8 case U_T_DIR:
257 root 1.1 u_mkdir (PACK_NAME);
258     break;
259    
260 root 1.8 case U_T_FILE:
261 root 1.1 {
262 root 1.8 u_handle h = u_creat (PACK_NAME, pack_cur->flags & U_F_EXEC);
263 root 1.2 unsigned int dlen, len = u_32 (pack_cur->datalen);
264     char *data = PACK_DATA;
265    
266 root 1.8 if (pack_cur->flags & U_F_LZF)
267 root 1.6 if (dlen = lzf_decompress (data, len, scratch, scratch_size))
268 root 1.2 {
269     data = scratch;
270     len = dlen;
271     }
272     else
273     fatal ("unable to uncompress file data - pack corrupted?");
274 root 1.1
275 root 1.5 if (!u_valid (h))
276 root 1.1 fatal ("unable to unpack file from packfile - disk full?");
277    
278 root 1.2 if (u_write (h, data, len) != len)
279 root 1.1 fatal ("unable to unpack file from packfile - disk full?");
280    
281 root 1.4 u_fsync (h);
282 root 1.1 u_close (h);
283     }
284     break;
285    
286 root 1.8 case U_T_NULL:
287 root 1.1 goto done;
288     }
289    
290     pack_next ();
291     }
292    
293     done:
294     if (u_chdir (datadir))
295     fatal ("unable to change to data directory");
296    
297 root 1.3 u_sync ();
298    
299 root 1.1 if (u_rename (tmppath, execdir))
300     deltree (tmppath); // if move fails, delete new, assume other process created it independently
301     }
302    
303     pack_unmap ();
304     u_close (pack_handle);
305    
306 root 1.2 if (u_chdir (execdir))
307     fatal ("unable to change to application instance directory");
308    
309 root 1.1 u_setenv ("URLADER_VERSION", URLADER_VERSION);
310     u_setenv ("URLADER_DATADIR", datadir);
311     u_setenv ("URLADER_EXECDIR", execdir);
312     u_setenv ("URLADER_EXE_ID" , exe_id);
313     u_setenv ("URLADER_EXE_DIR", exe_dir);
314     u_setenv ("URLADER_EXE_VER", exe_ver);
315    
316 root 1.5 #if 0
317 root 1.1 // yes, this is overkill
318     u_setenv ("SHLIB_PATH" , execdir); // hpux
319     u_setenv ("LIBPATH" , execdir); // aix
320     u_setenv ("LD_LIBRARY_PATH" , execdir); // most elf systems
321     u_setenv ("LD_LIBRARY_PATH_32", execdir); // solaris
322     u_setenv ("LD_LIBRARY_PATH_64", execdir); // solaris
323     u_setenv ("LD_LIBRARYN32_PATH", execdir); // irix
324     u_setenv ("LD_LIBRARY64_PATH" , execdir); // irix
325     u_setenv ("DYLD_LIBRARY_PATH" , execdir); // os sucks from apple
326 root 1.5 #endif
327 root 1.1 }
328    
329 root 1.2 static void
330     execute (void)
331     {
332     exe_argv [exe_argc] = 0;
333 root 1.6 systemv (exe_argv);
334 root 1.2 }
335    
336 root 1.1 #ifdef _WIN32
337    
338     int APIENTRY
339     WinMain (HINSTANCE hI, HINSTANCE hP, LPSTR argv, int command_show)
340     {
341     if (!GetModuleFileName (hI, tmppath, sizeof (tmppath)))
342     fatal ("unable to find executable pack");
343    
344 root 1.5 pack_handle = u_open (tmppath);
345     if (!u_valid (pack_handle))
346 root 1.1 fatal ("unable to open executable pack");
347    
348     exe_info ();
349    
350     if (!GetCurrentDirectory (sizeof (currdir), currdir))
351     strcpy (currdir, ".");
352    
353     if (SHGetFolderPath (0, CSIDL_APPDATA | CSIDL_FLAG_CREATE, NULL, SHGFP_TYPE_CURRENT, datadir) != S_OK)
354     fatal ("unable to find application data directory");
355    
356     u_mkdir (datadir);
357     u_append (datadir, URLADER);
358    
359     load ();
360     execute ();
361    
362     return 0;
363     }
364    
365     #else
366    
367     int
368     main (int argc, char *argv[])
369     {
370     char *home = getenv ("HOME");
371    
372 root 1.5 pack_handle = u_open (argv [0]);
373     if (!u_valid (pack_handle))
374 root 1.1 fatal ("unable to open executable pack");
375    
376     exe_info ();
377    
378     if (!home)
379     {
380     struct passwd *pw;
381    
382     if ((pw = getpwuid (getuid ())))
383     home = pw->pw_dir;
384     else
385     home = "/tmp";
386     }
387    
388     if (!getcwd (currdir, sizeof (currdir)))
389     strcpy (currdir, ".");
390    
391     u_mkdir (home);
392 root 1.6 //strcat (strcat (strcpy (datadir, home), "/."), URLADER);
393 root 1.1 sprintf (datadir, "%s/.%s", home, URLADER);
394     u_mkdir (datadir);
395    
396 root 1.5 #if 0
397 root 1.1 if (gethostname (tmppath, sizeof (tmppath)))
398     strcpy (tmppath, "default");
399    
400     u_append (datadir, tmppath);
401 root 1.5 #endif
402 root 1.1
403     load ();
404     execute ();
405    
406     return 0;
407     }
408    
409     #endif
410