56 using namespace basis;
70 #define BASE_LOG(to_print) program_wide_logger::get().log(to_print, ALWAYS_PRINT)
71 #define LOG(to_print) STAMPED_EMERGENCY_LOG(program_wide_logger::get(), to_print)
76 const char *
ERROR_TITLE =
"An Error Caused Incomplete Installation";
89 virtual int execute();
106 MessageBox(0, to_unicode_temp(msg), to_unicode_temp(title),
107 MB_OK | MB_ICONINFORMATION);
114 %s: This program unpacks its contents into the locations\n\
115 specified at packing time. The --target flag can be used to specify a\n\
116 different %s directory for the installation (for components that use\n\
117 the default %s variable to specify their install folder).\n\
118 One can also pass a --keyword flag to specify a keyword; the files in the\n\
119 bundle that are marked with that keyword will be installed, but files that\n\
120 are missing the keyword will not be.\n\
121 Further, variables can be overridden on the command line in the\n\
123 The line below uses all these parameters as an example:\n\n\
124 %s --target c:\\Program Files\\gubernator --keyword dlls_only SILENT=true\n\
128 One helpful variable is \"%s\". This is where the unpacking log file\n\
129 will be written to. The default is \"~/logs\" (or \"$TMP/logs\" on win32)\n\
142 const int MAXIMUM_BACKUPS = 200;
144 for (
int i = 0; i < MAXIMUM_BACKUPS; i++) {
146 if (target_file.
exists()) {
164 = {
'm',
'u',
'f',
't',
'i',
'l',
'o',
'c', 0, 0, 0, 0, 0, 0, 0, 0 };
166 int unpacker_stub::execute()
170 if (IsUserAnAdmin()) {
171 ::MessageBox(0, to_unicode_temp(
"IS admin in bundler"), to_unicode_temp(
"bundler"), MB_OK);
173 ::MessageBox(0, to_unicode_temp(
"NOT admin in bundler"), to_unicode_temp(
"bundler"), MB_OK);
187 environment::set(
"EXE_END",
"");
188 environment::set(
"DLL_START",
"lib");
189 environment::set(
"DLL_END",
".so");
191 environment::set(
"EXE_END",
".exe");
192 environment::set(
"DLL_START",
"");
193 environment::set(
"DLL_END",
".dll");
197 bool provided_target =
false;
199 cmds.get_value(
"target", target);
201 provided_target =
false;
205 provided_target =
true;
212 logdir = environment::TMP() +
"/logs";
217 astring homedir = environment::get(
"HOME");
218 logdir = homedir +
"/logs";
225 cmds.get_value(
"keyword", keyword);
229 for (
int x = 0; x < cmds.entries(); x++) {
232 if (curr.
text().
find(
'=', 0) < 0)
continue;
238 vars_set +=
astring(
"variable set: ") + var +
"=" + value
239 + parser_bits::platform_eol_to_chars();
241 provided_target =
true;
244 _variables.add(var, value);
245 environment::set(var, value);
253 astring logname = logdir +
"/" + appname +
".log";
259 BASE_LOG(appname +
" command-line parameters:");
269 "stubby window title");
282 if (!this_exe.exists()) {
290 our_exe.seek(manifest_offset);
293 if (our_exe.read(temp_packed, 2 *
sizeof(
int)) <= 0) {
301 _manifest.insert(0, item_count);
304 for (
int i = 0; i < (int)item_count; i++) {
323 LOG(
"read the following info from manifest:");
325 for (
int i = 0; i < _manifest.length(); i++) {
330 critical_events::alert_message(temp,
"manifest contents");
336 for (
int festdex = 0; festdex < _manifest.length(); festdex++) {
338 int size_left = curr.
_size;
342 curr.
_parms = parser_bits::substitute_env_vars(curr.
_parms,
false);
351 bool keyword_good =
true;
354 keyword_good =
false;
364 +
": was provided explicitly as " + target);
365 }
else if (_variables.find(curr.
_payload)) {
367 +
": was provided on command line.");
376 astring logname = logdir +
"/" + appname +
".log";
383 provided_target =
true;
391 if (var_value.
empty()) {
394 "*not* defined, for item #%d.", curr.
_payload.
s(), festdex),
405 if (!provided_target) {
407 BASE_LOG(
astring(
"No TARGET has been specified; please provide one on the command line.") + parser_bits::platform_eol_to_chars());
414 if (keyword_good && !target_dir.
exists()
415 && !directory::recursive_create(target_dir)) {
416 LOG(
a_sprintf(
"failed to create directory %s for item #%d: ",
423 if (target_file.exists()) {
425 keyword_good =
false;
432 if (target_file.exists()) {
434 if (!new_file_name) {
436 keyword_good =
false;
442 int retval = rename(curr.
_payload.
s(), new_file_name.
s());
445 keyword_good =
false;
456 bool first_read =
true;
458 bool too_tiny_complaint_already =
false;
464 while (first_read || !our_exe.eof()) {
502 " size on read (expected %d, got %d): ", festdex,
packed_size,
506 uncompressed.reset(real_size +
KILOBYTE);
507 uLongf destlen = uncompressed.length();
508 int uncomp_ret = uncompress(uncompressed.access(), &destlen,
510 if (uncomp_ret != Z_OK) {
516 if (
int(destlen) != real_size) {
517 LOG(
a_sprintf(
"got a different unpacked size for item #%d: ",
522 size_left -= real_size;
524 if (!too_tiny_complaint_already) {
525 LOG(
a_sprintf(
"item #%d was larger than expected (non-fatal): ",
527 too_tiny_complaint_already =
true;
531 uncompressed.zap(real_size, uncompressed.length() - 1);
535 ret = targo->
write(uncompressed);
536 if (ret != uncompressed.length()) {
544 if (targo) targo->
close();
566 astring prev_dir = application_configuration::current_directory();
575 launch_process::AWAIT_APP_EXIT | launch_process::HIDE_APP_WINDOW, kid);
580 LOG(
astring(
"failed to launch process, targ=")
590 LOG(
astring(
"ignoring failure to launch process, targ=")
614 #ifdef __BUILD_STATIC_APPLICATION__
int print_instructions(bool good, const astring &program_name)
The application_shell is a base object for console programs.
const basis::astring & text() const
observes the string contents.
parameter_types type() const
observes the type of the parameter.
a_sprintf is a specialization of astring that provides printf style support.
Provides a dynamically resizable ASCII character string.
const char * s() const
synonym for observe. the 's' stands for "string", if that helps.
bool empty() const
empty() reports if the string is empty, that is, of zero length().
int length() const
Returns the current length of the string.
int find(char to_find, int position=0, bool reverse=false) const
Locates "to_find" in "this".
virtual const char * observe() const
observes the underlying pointer to the zero-terminated string.
A very common template for a dynamic array of bytes.
Manages a bank of textual definitions of variables.
const structures::string_table & table() const
provides a constant peek at the string_table holding the values.
int symbols() const
returns the number of entries in the variable_tokenizer.
bool parse(const basis::astring &to_tokenize)
parses the string using our established sentinel characters.
Provides file managment services using the standard I/O support.
int write(const basis::abyte *buffer, int buffer_size)
writes "buffer_size" bytes into the file from "buffer".
void close()
shuts down the open file, if any.
bool set_time(const basis::astring &filename)
sets the time for the the "filename" to the currently held time.
virtual bool unpack(basis::byte_array &packed_form)
Provides operations commonly needed on file names.
bool exists() const
returns true if the file exists.
basis::astring rootname() const
returns the root part of the basename without an extension.
const basis::astring & raw() const
returns the astring that we're holding onto for the path.
filename dirname() const
returns the directory for the filename.
combines a file_logger with a console logger, behaving like the 'tee' command.
A base class for a very usable logger with a filter_set and eol awareness.
bool member(const contents &to_test) const
Returns true if the item "to_test" is a member of this set.
Provides a symbol_table that holds strings as the content.
const basis::astring & name(int index) const
returns the name held at the "index".
@ TEST_VARIABLE_DEFINED
check for required variable's presence.
@ OMIT_PACKING
for a source side exe, do not pack the file.
@ SET_VARIABLE
this item just has a variable assignment.
@ QUIET_FAILURE
when errors happen, no popup message happens.
@ IGNORE_ERRORS
if set, errors in an item will not stop program.
@ TARGET_EXECUTE
the file should be executed on unbundling.
@ MAKE_BACKUP_FILE
save a copy if original file already exists.
@ NO_OVERWRITE
target file will not be overwritten if exists.
#define NULL_POINTER
The value representing a pointer to nothing.
#define DEFINE_CLASS_NAME(objname)
Defines the name of a class by providing a couple standard methods.
Provides macros that implement the 'main' program of an application.
#define HOOPLE_MAIN(obj_name, obj_args)
options that should work for most unix and linux apps.
Implements an application lock to ensure only one is running at once.
window_handle create_simplistic_window(const basis::astring &formal(window_title), const basis::astring &formal(class_name))
void whack_simplistic_window(window_handle formal(f_window))
The guards collection helps in testing preconditions and reporting errors.
void WHACK(contents *&ptr)
deletion with clearing of the pointer.
unsigned char abyte
A fairly important unit which is seldom defined...
unsigned int un_int
Abbreviated name for unsigned integers.
const int KILOBYTE
Number of bytes in a kilobyte.
A platform independent way to obtain the timestamp of a file.
A logger that sends to the console screen using the standard output device.
A dynamic container class that holds any kind of object via pointers.
bool obscure_detach(byte_array &packed_form, un_int &to_detach)
shifts the number back and checks validity, false returned if corrupted.
int packed_size(const byte_array &packed_form)
Reports the size required to pack a byte array into a byte array.
we will read the manifest pieces out of our own exe image.
basis::un_int _flags
uses the special_bundling_flags.
basis::astring _parms
the parameters to pass on the command line.
basis::astring _payload
guts of the chunk, such as location for file on target or a variable definition.
static bool read_an_obscured_int(filesystem::byte_filer &bundle, basis::un_int &found)
reads in our obscured packing format for an int, which takes 8 bytes.
static bool read_manifest(filesystem::byte_filer &bundle, manifest_chunk &to_fill)
reads a chunk out of the "bundle" and stores it in "to_fill".
basis::un_int _size
the size of the packed file.
virtual void text_form(basis::base_string &state_fill) const
Provides a text view of all the important info owned by this object.
basis::byte_array c_filetime
more than enough room for unix file time.
structures::string_set _keywords
keywords applicable to this item.
#define BASE_LOG(to_print)
abyte MANIFEST_OFFSET_ARRAY[]
const astring TARGET_WORD
const astring LOGDIR_WORD
astring find_unique_backup_name(astring original_file)
void show_message(const astring &msg, const astring &title)
Support for unicode builds.