Urlader

 view release on metacpan or  search on metacpan

urlader.c  view on Meta::CPAN


  size = fi.nFileSizeLow;
#else
  size = lseek (pack_handle, 0, SEEK_END);
#endif

  addr = u_mmap (pack_handle, size);
  if (!addr)
    return 0;

  /*pack_unmap ();*/

  pack_base = addr;
  pack_end  = pack_base + size;

  pack_tail = (void *)(pack_end - sizeof (*pack_tail));

  if (memcmp (pack_tail->magic, TAIL_MAGIC, sizeof (TAIL_MAGIC) - 1))
    return 0;

  pack_cur = (struct u_pack_hdr *)(pack_end - u_32 (pack_tail->size));

  if (pack_cur->type != T_META)
    return 0;

  scratch = u_malloc (scratch_size = u_32 (pack_tail->max_uncompressed));
  if (!scratch)
    return 0;

  return 1;
}

static void
add_arg (char *arg, unsigned int len)
{
  char *addr = u_dynbuf_append (&exe_args,  arg, len);
  u_dynbuf_append (&exe_argv, &addr, sizeof (addr));
}

static void
load (void)
{
  strcpy (exe_id , PACK_NAME);
  strcpy (exe_ver, PACK_DATA);
  u_set_exe_info ();

  if (u_chdir (exe_dir))
    u_fatal ("unable to change to application data directory");

  u_handle h = u_open ("override");
  if (u_valid (h))
    {
      u_handle oh = pack_handle;

      pack_unmap ();
      pack_handle = h;

      if (pack_map ()
          && strcmp (exe_id , PACK_NAME) == 0
          && strcmp (exe_ver, PACK_DATA) <= 0)
        u_setenv ("URLADER_OVERRIDE", "override");
      else
        {
          pack_unmap ();
          pack_handle = oh;
          oh = h;
          pack_map ();
        }

      u_close (oh);
    }

  strcpy (exe_ver, PACK_DATA);
  u_set_exe_info ();
  pack_next ();

  for (;;)
    {
      if (pack_cur->type == T_ENV)
        u_setenv (PACK_NAME, PACK_DATA);
      else if (pack_cur->type == T_ARG)
        add_arg (PACK_NAME, u_16 (pack_cur->namelen) + 1);
      else
        break;

      pack_next ();
    }
 
done_env_arg:

  strcat (strcpy (tmppath, execdir), ".lck");
  lock_handle = u_lock (tmppath, 0, 1);
  if (!lock_handle)
    u_fatal ("unable to lock application instance");

  if (access (execdir, F_OK))
    {
      // does not exist yet, so unpack and move
      tmpdir (exe_dir);

      if (u_chdir (tmppath))
        u_fatal ("unable to change to new instance directory");

      for (;;)
        {
          switch (pack_cur->type)
            {
              case T_DIR:
                u_mkdir (PACK_NAME);
                break;

              case T_FILE:
                {
                  u_handle h = u_creat (PACK_NAME, pack_cur->flags & F_EXEC);
                  unsigned int dlen, len = u_32 (pack_cur->datalen);
                  char *data = PACK_DATA;

                  if (pack_cur->flags & F_LZF)
                    if (dlen = lzf_decompress (data, len, scratch, scratch_size))
                      {
                        data = scratch;
                        len  = dlen;
                      }
                    else
                      u_fatal ("unable to uncompress file data - pack corrupted?");

                  if (!u_valid (h))
                    u_fatal ("unable to unpack file from packfile - disk full?");

                  if (u_write (h, data, len) != len)
                    u_fatal ("unable to unpack file from packfile - disk full?");

                  u_fsync (h);
                  u_close (h);
                }
                break;

              case T_NULL:
                goto done;
            }

          pack_next ();
        }

done:
      if (u_chdir (datadir))
        u_fatal ("unable to change to data directory");

      u_sync ();

      if (u_rename (tmppath, execdir))
        deltree (tmppath); // if move fails, delete new, assume other process created it independently
    }

  pack_unmap ();
  u_close (pack_handle);

  if (u_chdir (execdir))
    u_fatal ("unable to change to application instance directory");

  u_setenv ("URLADER_VERSION", URLADER_VERSION);

#if 0
  // yes, this is overkill
  u_setenv ("SHLIB_PATH"        , execdir); // hpux
  u_setenv ("LIBPATH"           , execdir); // aix
  u_setenv ("LD_LIBRARY_PATH"   , execdir); // most elf systems
  u_setenv ("LD_LIBRARY_PATH_32", execdir); // solaris
  u_setenv ("LD_LIBRARY_PATH_64", execdir); // solaris
  u_setenv ("LD_LIBRARYN32_PATH", execdir); // irix
  u_setenv ("LD_LIBRARY64_PATH" , execdir); // irix
  u_setenv ("DYLD_LIBRARY_PATH" , execdir); // os sucks from apple
#endif
}

static void
execute (void)
{
  char *null = 0;
  u_dynbuf_append (&exe_argv, &null, sizeof (null));
  systemv ((const char *const *)exe_argv.addr);
}

// this argc/argv is without argv [0]
static void
doit (int argc, char *argv[])
{
  int i;

  u_setenv ("URLADER_CURRDIR", currdir);

  u_set_datadir ();
  u_mkdir (datadir);

  if (!pack_map ())
    u_fatal ("unable to map pack file - executable corrupted?");

  load ();

  while (argc--)
    {
      add_arg (*argv, strlen (*argv) + 1);
      ++argv;
    }

  execute ();
}

#ifdef _WIN32

int APIENTRY
WinMain (HINSTANCE hI, HINSTANCE hP, LPSTR argv, int command_show)
{
  if (!GetModuleFileName (hI, tmppath, sizeof (tmppath)))
    u_fatal ("unable to find executable pack");

  u_setenv ("URLADER_EXEPATH", tmppath);

  pack_handle = u_open (tmppath);
  if (!u_valid (pack_handle))
    u_fatal ("unable to open executable pack");

  if (!GetCurrentDirectory (sizeof (currdir), currdir))
    strcpy (currdir, ".");

  doit (1, &argv);

  return 0;
}

#else

int
main (int argc, char *argv[])
{
  if (!getcwd (currdir, sizeof (currdir)))
    strcpy (currdir, ".");

  {
    const char *exe_path = 0;

    if (strchr (argv [0], '/'))
      exe_path = argv [0];
    else
      {
        const char *p, *path = getenv ("PATH");

        if (!path)
          u_fatal ("unable to find executable, try running with full path.");

        for (p = path; ; )
          {
            const char *e = p;
            int l;

            while (*e && *e != ':')
              ++e;

            l = e - p;
            memcpy (tmppath, p, l);

            if (!l)
              tmppath [l++] = '.';

            tmppath [l++] = '/';

            strcpy (tmppath + l, argv [0]);

            if (!access (tmppath, X_OK))
              break;

            p = e;
            if (!*p)
              u_fatal ("unable to find executable, try running with full path.");

            ++p;
          }

        exe_path = tmppath;
      }

    pack_handle = u_open (exe_path);
    if (!u_valid (pack_handle))
      u_fatal ("unable to open executable for reading - permissions problem?");

    u_setenv ("URLADER_EXEPATH", exe_path);
  }

#if 0
  /* intersperse hostname, for whatever reason */

  if (gethostname (tmppath, sizeof (tmppath)))
    strcpy (tmppath, "default");

  u_append (datadir, tmppath);
#endif

  doit (argc - 1, argv + 1);

  return 0;
}

#endif



( run in 2.260 seconds using v1.01-cache-2.11-cpan-39bf76dae61 )