ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/Urlader/urlader.c
(Generate patch)

Comparing Urlader/urlader.c (file contents):
Revision 1.1 by root, Thu Dec 29 00:44:21 2011 UTC vs.
Revision 1.5 by root, Fri Dec 30 09:34:20 2011 UTC

1#ifndef URLADER 1#ifndef URLADER
2# define URLADER "urlader" 2# define URLADER "urlader"
3#endif 3#endif
4#define URLADER_VERSION "1.0" 4#define URLADER_VERSION "1.0" // a decimal number, not a version string
5 5
6#include <stdio.h> 6#include <stdio.h>
7#include <stdlib.h> 7#include <stdlib.h>
8#include <unistd.h> 8#include <unistd.h>
9#include <errno.h> 9#include <errno.h>
10#include <string.h> 10#include <string.h>
11#include <time.h> 11#include <time.h>
12#include <fcntl.h> 12#include <fcntl.h>
13 13
14#include "lzf_d.c" 14#include "liblzf/lzf_d.c"
15 15
16#define TAIL_MAGIC "SCHMORPPACK0" 16#define TAIL_MAGIC "SCHMORPPACK0"
17 17
18#ifdef _WIN32 18#ifdef _WIN32
19 19
24 #include <wininet.h> 24 #include <wininet.h>
25 25
26 static DWORD dword; 26 static DWORD dword;
27 27
28 #define u_handle HANDLE 28 #define u_handle HANDLE
29 #define u_valid(handle) (!!handle)
30
29 #define u_setenv(name,value) SetEnvironmentVariable (name, value) 31 #define u_setenv(name,value) SetEnvironmentVariable (name, value)
30 #define u_mkdir(path) !CreateDirectory (path, NULL) 32 #define u_mkdir(path) !CreateDirectory (path, NULL)
31 #define u_chdir(path) !SetCurrentDirectory (path) 33 #define u_chdir(path) !SetCurrentDirectory (path)
32 #define u_rename(fr,to) !MoveFile (fr, to) 34 #define u_rename(fr,to) !MoveFile (fr, to)
33 #define u_open(path) CreateFile (path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL) 35 #define u_open(path) CreateFile (path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL)
34 #define u_creat(path,exec) CreateFile (path, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL) 36 #define u_creat(path,exec) CreateFile (path, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL)
35 #define u_close(handle) CloseHandle (handle) 37 #define u_close(handle) CloseHandle (handle)
36 #define u_append(path,add) PathAppend (path, add) 38 #define u_append(path,add) PathAppend (path, add)
37 #define u_write(handle,data,len) (WriteFile (handle, data, len, &dword, 0) ? dword : -1) 39 #define u_write(handle,data,len) (WriteFile (handle, data, len, &dword, 0) ? dword : -1)
38 40
41 #define u_fsync(handle) FlushFileBuffers (handle)
42 #define u_sync()
43
39#else 44#else
40 45
41 #include <sys/mman.h> 46 #include <sys/mman.h>
42 #include <sys/types.h> 47 #include <sys/types.h>
43 #include <pwd.h> 48 #include <pwd.h>
47 #else 52 #else
48 #define MAX_PATH 4096 53 #define MAX_PATH 4096
49 #endif 54 #endif
50 55
51 #define u_handle int 56 #define u_handle int
57 #define u_valid(fd) ((fd) >= 0)
58
52 #define u_setenv(name,value) setenv (name, value, 1) 59 #define u_setenv(name,value) setenv (name, value, 1)
53 #define u_mkdir(path) mkdir (path, 0777) 60 #define u_mkdir(path) mkdir (path, 0777)
54 #define u_chdir(path) chdir (path) 61 #define u_chdir(path) chdir (path)
55 #define u_rename(fr,to) rename (fr, to) 62 #define u_rename(fr,to) rename (fr, to)
56 #define u_open(path) open (path, O_RDONLY) + 1 63 #define u_open(path) open (path, O_RDONLY)
57 #define u_creat(path,exec) open (path, O_WRONLY | O_CREAT | O_TRUNC, (exec) ? 0777 : 0666) + 1 64 #define u_creat(path,exec) open (path, O_WRONLY | O_CREAT | O_TRUNC, (exec) ? 0777 : 0666)
58 #define u_close(handle) close (handle - 1) 65 #define u_close(handle) close (handle)
59 #define u_append(path,add) strcat (strcat (path, "/"), add) 66 #define u_append(path,add) strcat (strcat (path, "/"), add)
60 #define u_write(handle,data,len) write ((handle) - 1, data, len) 67 #define u_write(handle,data,len) write (handle, data, len)
68
69 // on a mostly idle system, a sync at the end is certainly faster, hope for the best
70 #define u_fsync(handle)
71 #define u_sync() sync ()
61 72
62#endif 73#endif
63 74
64#define u_16(ptr) (((ptr)[0] << 8) | (ptr)[1]) 75#define u_16(ptr) (((ptr)[0] << 8) | (ptr)[1])
65#define u_32(ptr) (((ptr)[0] << 24) | ((ptr)[1] << 16) | ((ptr)[2] << 8) | (ptr)[3]) 76#define u_32(ptr) (((ptr)[0] << 24) | ((ptr)[1] << 16) | ((ptr)[2] << 8) | (ptr)[3])
105 return; 116 return;
106 } 117 }
107} 118}
108 119
109static void 120static void
110systemv (const char *const argv[]) 121systemv (const char *const argv[], int dowait)
111{ 122{
112#ifdef _WIN32 123#ifdef _WIN32
113 _spawnv (P_WAIT, argv [0], argv); 124 _spawnv (P_WAIT, argv [0], argv);
114#else 125#else
115 pid_t pid = fork (); 126 pid_t pid = dowait ? fork () : 0;
116 127
117 if (pid < 0) 128 if (pid < 0)
118 fatal ("fork failure"); 129 fatal ("fork failure");
119 130
120 if (!pid) 131 if (!pid)
136 const char *argv[] = { getenv ("COMSPEC"), "/c", "rd", "/s", "/q", buf, 0 }; 147 const char *argv[] = { getenv ("COMSPEC"), "/c", "rd", "/s", "/q", buf, 0 };
137 sprintf (buf, "\"%s\"", path); 148 sprintf (buf, "\"%s\"", path);
138 #else 149 #else
139 const char *argv[] = { "/bin/rm", "-rf", path, 0 }; 150 const char *argv[] = { "/bin/rm", "-rf", path, 0 };
140 #endif 151 #endif
141 systemv (argv); 152 systemv (argv, 1);
142}
143
144static void
145execute (void)
146{
147 exe_argv [exe_argc] = 0;
148 systemv (exe_argv);
149} 153}
150 154
151enum 155enum
152{ 156{
153 T_NULL, // 5 157 T_NULL, // 5
154 T_META, // 1 : exe_id, exe_ver 158 T_META, // 1 : exe_id, exe_ver
155 T_ARG, // 2 : arg
156 T_ENV, // 3 : name, value 159 T_ENV, // 2 : name, value
160 T_ARG, // 3 : arg
157 T_DIR, // 4+: path 161 T_DIR, // 4+: path
158 T_FILE, // 4+: path, data 162 T_FILE, // 4+: path, data
159 T_NUM 163 T_NUM
160}; 164};
161 165
180 char magic[12]; 184 char magic[12];
181}; 185};
182 186
183static char *pack_base, *pack_end; 187static char *pack_base, *pack_end;
184static struct hdr *pack_cur; 188static struct hdr *pack_cur;
189static char *scratch;
190static unsigned int scratch_len;
185 191
186#define PACK_NAME ((char *)(pack_cur + 1)) 192#define PACK_NAME ((char *)(pack_cur + 1))
187#define PACK_DATA (PACK_NAME + u_16 (pack_cur->namelen) + 1) 193#define PACK_DATA (PACK_NAME + u_16 (pack_cur->namelen) + 1)
188#define PACK_VALID pack_cur->type 194#define PACK_VALID pack_cur->type
189 195
198static void 204static void
199pack_unmap (void) 205pack_unmap (void)
200{ 206{
201 if (!pack_base) 207 if (!pack_base)
202 return; 208 return;
209
210 free (scratch);
203 211
204#ifdef _WIN32 212#ifdef _WIN32
205 UnmapViewOfFile (pack_base); 213 UnmapViewOfFile (pack_base);
206#else 214#else
207 munmap (pack_base, pack_end - pack_base); 215 munmap (pack_base, pack_end - pack_base);
254 if (memcmp (tail->magic, TAIL_MAGIC, sizeof (TAIL_MAGIC) - 1)) 262 if (memcmp (tail->magic, TAIL_MAGIC, sizeof (TAIL_MAGIC) - 1))
255 return 0; 263 return 0;
256 264
257 pack_cur = (struct hdr *)(pack_end - u_32 (tail->size)); 265 pack_cur = (struct hdr *)(pack_end - u_32 (tail->size));
258 266
267 free (scratch);
268 scratch = malloc (scratch_len = u_32 (tail->max_filesize));
269
259 return 1; 270 return 1;
260} 271}
261 272
262static void 273static void
263exe_info (void) 274exe_info (void)
282 293
283 if (u_chdir (exe_dir)) 294 if (u_chdir (exe_dir))
284 fatal ("unable to change to application data directory"); 295 fatal ("unable to change to application data directory");
285 296
286 u_handle h = u_open ("override"); 297 u_handle h = u_open ("override");
287 if (h) 298 if (u_valid (h))
288 { 299 {
289 u_handle oh = pack_handle; 300 u_handle oh = pack_handle;
290 301
291 pack_handle = h; 302 pack_handle = h;
292 if (!pack_map ()) 303 if (!pack_map ())
302 fatal ("unable to locate override metadata"); 313 fatal ("unable to locate override metadata");
303 314
304 strcpy (exe_ver, PACK_DATA); 315 strcpy (exe_ver, PACK_DATA);
305 pack_next (); 316 pack_next ();
306 317
307 while (pack_cur->type == T_ARG) 318 for (;;)
308 { 319 {
320 if (pack_cur->type == T_ENV)
321 u_setenv (PACK_NAME, PACK_DATA);
322 else if (pack_cur->type == T_ARG)
309 exe_argv [exe_argc++] = strdup (PACK_NAME); 323 exe_argv [exe_argc++] = strdup (PACK_NAME);
324 else
325 break;
326
310 pack_next (); 327 pack_next ();
311 } 328 }
312 329
313 while (pack_cur->type == T_ENV) 330done_env_arg:
314 {
315 u_setenv (PACK_NAME, PACK_DATA);
316 pack_next ();
317 }
318
319 strcpy (execdir, exe_dir); 331 strcpy (execdir, exe_dir);
320 u_append (execdir, "i-"); 332 u_append (execdir, "i-");
321 strcat (execdir, exe_ver); 333 strcat (execdir, exe_ver);
322 334
323 if (access (execdir, F_OK)) 335 if (access (execdir, F_OK))
337 break; 349 break;
338 350
339 case T_FILE: 351 case T_FILE:
340 { 352 {
341 u_handle h = u_creat (PACK_NAME, pack_cur->flags & F_EXEC); 353 u_handle h = u_creat (PACK_NAME, pack_cur->flags & F_EXEC);
342 unsigned int len = u_32 (pack_cur->datalen); 354 unsigned int dlen, len = u_32 (pack_cur->datalen);
355 char *data = PACK_DATA;
343 356
357 if (pack_cur->flags & F_LZF)
358 if (dlen = lzf_decompress (data, len, scratch, scratch_len))
359 {
360 data = scratch;
361 len = dlen;
362 }
363 else
364 fatal ("unable to uncompress file data - pack corrupted?");
365
344 if (!h) 366 if (!u_valid (h))
345 fatal ("unable to unpack file from packfile - disk full?"); 367 fatal ("unable to unpack file from packfile - disk full?");
346 368
347 if (u_write (h, PACK_DATA, len) != len) 369 if (u_write (h, data, len) != len)
348 fatal ("unable to unpack file from packfile - disk full?"); 370 fatal ("unable to unpack file from packfile - disk full?");
349 371
372 u_fsync (h);
350 u_close (h); 373 u_close (h);
351 } 374 }
352 break; 375 break;
353 376
354 case T_NULL: 377 case T_NULL:
360 383
361done: 384done:
362 if (u_chdir (datadir)) 385 if (u_chdir (datadir))
363 fatal ("unable to change to data directory"); 386 fatal ("unable to change to data directory");
364 387
388 u_sync ();
389
365 if (u_rename (tmppath, execdir)) 390 if (u_rename (tmppath, execdir))
366 deltree (tmppath); // if move fails, delete new, assume other process created it independently 391 deltree (tmppath); // if move fails, delete new, assume other process created it independently
367
368 if (u_chdir (execdir))
369 fatal ("unable to change to application instance directory");
370 } 392 }
371 393
372 pack_unmap (); 394 pack_unmap ();
373 u_close (pack_handle); 395 u_close (pack_handle);
396
397 if (u_chdir (execdir))
398 fatal ("unable to change to application instance directory");
374 399
375 u_setenv ("URLADER_VERSION", URLADER_VERSION); 400 u_setenv ("URLADER_VERSION", URLADER_VERSION);
376 u_setenv ("URLADER_DATADIR", datadir); 401 u_setenv ("URLADER_DATADIR", datadir);
377 u_setenv ("URLADER_EXECDIR", execdir); 402 u_setenv ("URLADER_EXECDIR", execdir);
378 u_setenv ("URLADER_EXE_ID" , exe_id); 403 u_setenv ("URLADER_EXE_ID" , exe_id);
379 u_setenv ("URLADER_EXE_DIR", exe_dir); 404 u_setenv ("URLADER_EXE_DIR", exe_dir);
380 u_setenv ("URLADER_EXE_VER", exe_ver); 405 u_setenv ("URLADER_EXE_VER", exe_ver);
381 406
407#if 0
382 // yes, this is overkill 408 // yes, this is overkill
383 u_setenv ("SHLIB_PATH" , execdir); // hpux 409 u_setenv ("SHLIB_PATH" , execdir); // hpux
384 u_setenv ("LIBPATH" , execdir); // aix 410 u_setenv ("LIBPATH" , execdir); // aix
385 u_setenv ("LD_LIBRARY_PATH" , execdir); // most elf systems 411 u_setenv ("LD_LIBRARY_PATH" , execdir); // most elf systems
386 u_setenv ("LD_LIBRARY_PATH_32", execdir); // solaris 412 u_setenv ("LD_LIBRARY_PATH_32", execdir); // solaris
387 u_setenv ("LD_LIBRARY_PATH_64", execdir); // solaris 413 u_setenv ("LD_LIBRARY_PATH_64", execdir); // solaris
388 u_setenv ("LD_LIBRARYN32_PATH", execdir); // irix 414 u_setenv ("LD_LIBRARYN32_PATH", execdir); // irix
389 u_setenv ("LD_LIBRARY64_PATH" , execdir); // irix 415 u_setenv ("LD_LIBRARY64_PATH" , execdir); // irix
390 u_setenv ("DYLD_LIBRARY_PATH" , execdir); // os sucks from apple 416 u_setenv ("DYLD_LIBRARY_PATH" , execdir); // os sucks from apple
417#endif
418}
419
420static void
421execute (void)
422{
423 exe_argv [exe_argc] = 0;
424 systemv (exe_argv, 0);
391} 425}
392 426
393#ifdef _WIN32 427#ifdef _WIN32
394 428
395int APIENTRY 429int APIENTRY
396WinMain (HINSTANCE hI, HINSTANCE hP, LPSTR argv, int command_show) 430WinMain (HINSTANCE hI, HINSTANCE hP, LPSTR argv, int command_show)
397{ 431{
398 if (!GetModuleFileName (hI, tmppath, sizeof (tmppath))) 432 if (!GetModuleFileName (hI, tmppath, sizeof (tmppath)))
399 fatal ("unable to find executable pack"); 433 fatal ("unable to find executable pack");
400 434
401 if (!(pack_handle = u_open (tmppath))) 435 pack_handle = u_open (tmppath);
436 if (!u_valid (pack_handle))
402 fatal ("unable to open executable pack"); 437 fatal ("unable to open executable pack");
403 438
404 exe_info (); 439 exe_info ();
405 440
406 if (!GetCurrentDirectory (sizeof (currdir), currdir)) 441 if (!GetCurrentDirectory (sizeof (currdir), currdir))
423int 458int
424main (int argc, char *argv[]) 459main (int argc, char *argv[])
425{ 460{
426 char *home = getenv ("HOME"); 461 char *home = getenv ("HOME");
427 462
428 // we assume fd 0 and 2 are "normal"
429
430 if (!(pack_handle = u_open (argv [0]))) 463 pack_handle = u_open (argv [0]);
464 if (!u_valid (pack_handle))
431 fatal ("unable to open executable pack"); 465 fatal ("unable to open executable pack");
432 466
433 exe_info (); 467 exe_info ();
434 468
435 if (!home) 469 if (!home)
447 481
448 u_mkdir (home); 482 u_mkdir (home);
449 sprintf (datadir, "%s/.%s", home, URLADER); 483 sprintf (datadir, "%s/.%s", home, URLADER);
450 u_mkdir (datadir); 484 u_mkdir (datadir);
451 485
486#if 0
452 if (gethostname (tmppath, sizeof (tmppath))) 487 if (gethostname (tmppath, sizeof (tmppath)))
453 strcpy (tmppath, "default"); 488 strcpy (tmppath, "default");
454 489
455 u_append (datadir, tmppath); 490 u_append (datadir, tmppath);
491#endif
456 492
457 load (); 493 load ();
458 execute (); 494 execute ();
459 495
460 return 0; 496 return 0;

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines