mirror of
https://github.com/autc04/Retro68.git
synced 2024-06-07 13:33:06 +00:00
701 lines
20 KiB
C++
701 lines
20 KiB
C++
/* Copyright (C) 2021 Free Software Foundation, Inc.
|
|
Contributed by Oracle.
|
|
|
|
This file is part of GNU Binutils.
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation; either version 3, or (at your option)
|
|
any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program; if not, write to the Free Software
|
|
Foundation, 51 Franklin Street - Fifth Floor, Boston,
|
|
MA 02110-1301, USA. */
|
|
|
|
#include "config.h"
|
|
#include <ctype.h>
|
|
#include <errno.h>
|
|
#include <unistd.h>
|
|
#include <getopt.h>
|
|
|
|
#include "util.h"
|
|
#include "StringMap.h"
|
|
#include "LoadObject.h"
|
|
#include "DbeSession.h"
|
|
#include "DbeFile.h"
|
|
#include "SourceFile.h"
|
|
#include "Elf.h"
|
|
#include "gp-archive.h"
|
|
#include "ArchiveExp.h"
|
|
#include "Print.h"
|
|
#include "Module.h"
|
|
|
|
er_archive::er_archive (int argc, char *argv[]) : DbeApplication (argc, argv)
|
|
{
|
|
force = 0;
|
|
common_archive_dir = NULL;
|
|
quiet = 0;
|
|
descendant = 1;
|
|
use_relative_path = 0;
|
|
s_option = ARCH_EXE_ONLY;
|
|
mask = NULL;
|
|
}
|
|
|
|
er_archive::~er_archive ()
|
|
{
|
|
if (mask)
|
|
{
|
|
for (long i = 0, sz = mask->size (); i < sz; i++)
|
|
{
|
|
regex_t *regex_desc = mask->get (i);
|
|
regfree (regex_desc);
|
|
delete regex_desc;
|
|
}
|
|
delete mask;
|
|
}
|
|
delete common_archive_dir;
|
|
}
|
|
|
|
int
|
|
er_archive::mask_is_on (const char *str)
|
|
{
|
|
if (mask == NULL)
|
|
return 1;
|
|
for (long i = 0, sz = mask->size (); i < sz; i++)
|
|
{
|
|
regex_t *regex_desc = mask->get (i);
|
|
if (regexec (regex_desc, str, 0, NULL, 0) == 0)
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
void
|
|
er_archive::usage ()
|
|
{
|
|
/*
|
|
fprintf (stderr, GTXT ("Usage: %s [-nqFV] [-a on|ldobjects|src|usedldobjects|usedsrc|off] [-m regexp] experiment\n"), whoami);
|
|
*/
|
|
|
|
/*
|
|
Ruud - Isolate this line because it has an argument. Otherwise it would be at the
|
|
end of this long list.
|
|
*/
|
|
printf ( GTXT (
|
|
"Usage: gprofng archive [OPTION(S)] EXPERIMENT\n"));
|
|
|
|
printf ( GTXT (
|
|
"\n"
|
|
"Archive the associated application binaries and source files in a gprofng\n"
|
|
"experiment to make it self contained and portable.\n"
|
|
"\n"
|
|
"Options:\n"
|
|
"\n"
|
|
" --version print the version number and exit.\n"
|
|
" --help print usage information and exit.\n"
|
|
" --verbose {on|off} enable (on) or disable (off) verbose mode; the default is \"off\".\n"
|
|
"\n"
|
|
" -a {off|on|ldobjects|src|usedldobjects|usedsrc} specify archiving of binaries and other files;\n"
|
|
" in addition to disable this feature (off), or enable archiving off all\n"
|
|
" loadobjects and sources (on), the other options support a more\n"
|
|
" refined selection. All of these options enable archiving, but the\n"
|
|
" keyword controls what exactly is selected: all load objects (ldobjects),\n"
|
|
" all source files (src), the loadobjects asscoiated with a program counter\n"
|
|
" (usedldobjects), or the source files associated with a program counter\n"
|
|
" (usedsrc); the default is \"-a ldobjects\".\n"
|
|
"\n"
|
|
" -n archive the named experiment only, not any of its descendants.\n"
|
|
"\n"
|
|
" -q do not write any warnings to stderr; messages are archived and\n"
|
|
" can be retrieved later.\n"
|
|
"\n"
|
|
" -F force writing or rewriting of the archive; ignored with the -n\n"
|
|
" or -m options, or if this is a subexperiment.\n"
|
|
"\n"
|
|
" -d <path> specifies the location of a common archive; this is a directory that\n"
|
|
" contains archived files.\n"
|
|
"\n"
|
|
" -m <regex> archive only those source, object, and debug info files whose full\n"
|
|
" path name matches the given POSIX compliant regular expression.\n"
|
|
"\n"
|
|
"Limitations:\n"
|
|
"\n"
|
|
"Default archiving does not occur in case the application profiled terminates prematurely,\n"
|
|
"or if archiving is disabled when collecting the performance data. In such cases, this\n"
|
|
"tool can be used to afterwards archive the information, but it has to run on the same \n"
|
|
"system where the profiling data was recorded.\n"
|
|
"\n"
|
|
"Documentation:\n"
|
|
"\n"
|
|
"A getting started guide for gprofng is maintained as a Texinfo manual. If the info and\n"
|
|
"gprofng programs are properly installed at your site, the command \"info gprofng\"\n"
|
|
"should give you access to this document.\n"
|
|
"\n"
|
|
"See also:\n"
|
|
"\n"
|
|
"gprofng(1), gp-collect-app(1), gp-display-html(1), gp-display-src(1), gp-display-text(1)\n"));
|
|
// Ruud
|
|
/*
|
|
fprintf (stderr, GTXT ("GNU %s version %s\n"), get_basename (prog_name), VERSION);
|
|
*/
|
|
exit (1);
|
|
}
|
|
|
|
Vector <LoadObject*> *
|
|
er_archive::get_loadObjs ()
|
|
{
|
|
Vector <LoadObject*> *objs = new Vector<LoadObject*>();
|
|
Vector <LoadObject*> *loadObjs = dbeSession->get_text_segments ();
|
|
if (s_option != ARCH_NOTHING)
|
|
{
|
|
for (long i = 0, sz = VecSize(loadObjs); i < sz; i++)
|
|
{
|
|
LoadObject *lo = loadObjs->get (i);
|
|
if ((lo->flags & SEG_FLAG_DYNAMIC) != 0)
|
|
continue;
|
|
DbeFile *df = lo->dbeFile;
|
|
if (df && ((df->filetype & DbeFile::F_FICTION) != 0))
|
|
continue;
|
|
if (!lo->isUsed && ((s_option & (ARCH_USED_EXE_ONLY | ARCH_USED_SRC_ONLY)) != 0))
|
|
continue;
|
|
objs->append (lo);
|
|
}
|
|
}
|
|
if (DEBUG_ARCHIVE)
|
|
{
|
|
Dprintf (DEBUG_ARCHIVE, NTXT ("get_text_segments(): %d\n"),
|
|
(int) (loadObjs ? loadObjs->size () : -1));
|
|
for (long i = 0, sz = loadObjs ? loadObjs->size () : 0; i < sz; i++)
|
|
{
|
|
LoadObject *lo = loadObjs->get (i);
|
|
Dprintf (DEBUG_ARCHIVE, NTXT ("%s:%d [%2ld] %s\n"),
|
|
get_basename (__FILE__), (int) __LINE__, i, STR (lo->dump ()));
|
|
}
|
|
Dprintf (DEBUG_ARCHIVE, NTXT ("\nget_loadObjs(): %d\n"),
|
|
(int) (objs ? objs->size () : -1));
|
|
for (long i = 0, sz = VecSize(objs); i < sz; i++)
|
|
{
|
|
LoadObject *lo = objs->get (i);
|
|
Dprintf (DEBUG_ARCHIVE, NTXT ("%s:%d [%2ld] %s\n"),
|
|
get_basename (__FILE__), (int) __LINE__, i, STR (lo->dump ()));
|
|
}
|
|
}
|
|
delete loadObjs;
|
|
return objs;
|
|
}
|
|
|
|
/**
|
|
* Clean old archive
|
|
* Except the following cases:
|
|
* 1. Founder experiment is an MPI experiment
|
|
* 2. "-n" option is passed (do not archive descendants)
|
|
* 3. "-m" option is passed (partial archiving)
|
|
* 4. Experiment name is not the founder experiment (it is a sub-experiment)
|
|
* @param expname
|
|
* @param founder_exp
|
|
* @return 0 - success
|
|
*/
|
|
int
|
|
er_archive::clean_old_archive (char *expname, ArchiveExp *founder_exp)
|
|
{
|
|
if (0 == descendant)
|
|
{ // do not archive descendants
|
|
fprintf (stderr, GTXT ("Warning: Option -F is ignored because -n option is specified (do not archive descendants)\n"));
|
|
return 1;
|
|
}
|
|
if (NULL != mask)
|
|
{ // partial archiving
|
|
fprintf (stderr, GTXT ("Warning: Option -F is ignored because -m option is specified\n"));
|
|
return 1;
|
|
}
|
|
// Check if the experiment is the founder
|
|
char *s1 = dbe_strdup (expname);
|
|
char *s2 = dbe_strdup (founder_exp->get_expt_name ());
|
|
if (!s1 || !s2)
|
|
{
|
|
fprintf (stderr, GTXT ("Cannot allocate memory\n"));
|
|
exit (1);
|
|
}
|
|
// remove trailing slashes
|
|
for (int n = strlen (s1); n > 0; n--)
|
|
{
|
|
if ('/' != s1[n - 1])
|
|
break;
|
|
s1[n - 1] = 0;
|
|
}
|
|
for (int n = strlen (s2); n > 0; n--)
|
|
{
|
|
if ('/' != s2[n - 1])
|
|
break;
|
|
s2[n - 1] = 0;
|
|
}
|
|
if (strcmp (s1, s2) != 0)
|
|
{ // not founder
|
|
fprintf (stderr, GTXT ("Warning: Option -F is ignored because specified experiment name %s does not match founder experiment name %s\n"), s1, s2);
|
|
free (s1);
|
|
free (s2);
|
|
return 1;
|
|
}
|
|
// Remove old "archives"
|
|
char *arch = founder_exp->get_arch_name ();
|
|
fprintf (stderr, GTXT ("INFO: removing existing archive: %s\n"), arch);
|
|
if (dbe_stat (arch, NULL) == 0)
|
|
{
|
|
char *cmd = dbe_sprintf ("/bin/rm -rf %s", arch);
|
|
system (cmd);
|
|
free (cmd);
|
|
if (dbe_stat (arch, NULL) != 0)
|
|
{ // create "archives"
|
|
if (!founder_exp->create_dir (founder_exp->get_arch_name ()))
|
|
{
|
|
fprintf (stderr, GTXT ("Unable to create directory `%s'\n"), founder_exp->get_arch_name ());
|
|
exit (1);
|
|
}
|
|
}
|
|
}
|
|
free (s1);
|
|
free (s2);
|
|
return 0;
|
|
} // clean_old_archive_if_necessary
|
|
|
|
void
|
|
er_archive::start (int argc, char *argv[])
|
|
{
|
|
int last = argc - 1;
|
|
if (check_args (argc, argv) != last)
|
|
usage ();
|
|
check_env_var ();
|
|
if (s_option == ARCH_NOTHING)
|
|
return;
|
|
|
|
ArchiveExp *founder_exp = new ArchiveExp (argv[last]);
|
|
if (founder_exp->get_status () == Experiment::FAILURE)
|
|
{
|
|
if (!quiet)
|
|
fprintf (stderr, GTXT ("er_archive: %s: %s\n"), argv[last],
|
|
pr_mesgs (founder_exp->fetch_errors (), NTXT (""), NTXT ("")));
|
|
exit (1);
|
|
}
|
|
if (!founder_exp->create_dir (founder_exp->get_arch_name ()))
|
|
{
|
|
fprintf (stderr, GTXT ("Unable to create directory `%s'\n"), founder_exp->get_arch_name ());
|
|
exit (1);
|
|
}
|
|
if (!common_archive_dir)
|
|
common_archive_dir = dbe_strdup (getenv ("GPROFNG_ARCHIVE_COMMON_DIR"));
|
|
if (common_archive_dir)
|
|
{
|
|
if (!founder_exp->create_dir (common_archive_dir))
|
|
if (dbe_stat (common_archive_dir, NULL) != 0)
|
|
{
|
|
fprintf (stderr, GTXT ("Unable to create directory for common archive `%s'\n"), common_archive_dir);
|
|
exit (1);
|
|
}
|
|
}
|
|
// Clean old archives if necessary
|
|
if (force)
|
|
clean_old_archive (argv[last], founder_exp);
|
|
Vector<ArchiveExp*> *exps = new Vector<ArchiveExp*>();
|
|
exps->append (founder_exp);
|
|
if (descendant)
|
|
{
|
|
Vector<char*> *exp_names = founder_exp->get_descendants_names ();
|
|
if (exp_names)
|
|
{
|
|
for (long i = 0, sz = exp_names->size (); i < sz; i++)
|
|
{
|
|
char *exp_path = exp_names->get (i);
|
|
ArchiveExp *exp = new ArchiveExp (exp_path);
|
|
if (exp->get_status () == Experiment::FAILURE)
|
|
{
|
|
if (!quiet)
|
|
fprintf (stderr, GTXT ("er_archive: %s: %s\n"), exp_path,
|
|
pr_mesgs (exp->fetch_errors (), NTXT (""), NTXT ("")));
|
|
delete exp;
|
|
continue;
|
|
}
|
|
exps->append (exp);
|
|
}
|
|
exp_names->destroy ();
|
|
delete exp_names;
|
|
}
|
|
}
|
|
for (long i = 0, sz = exps->size (); i < sz; i++)
|
|
{
|
|
ArchiveExp *exp = exps->get (i);
|
|
exp->read_data (s_option);
|
|
}
|
|
|
|
Vector <DbeFile*> *copy_files = new Vector<DbeFile*>();
|
|
Vector <LoadObject*> *loadObjs = get_loadObjs ();
|
|
for (long i = 0, sz = VecSize(loadObjs); i < sz; i++)
|
|
{
|
|
LoadObject *lo = loadObjs->get (i);
|
|
if (strcmp (lo->get_pathname (), "LinuxKernel") == 0)
|
|
continue;
|
|
DbeFile *df = lo->dbeFile;
|
|
if ((df->filetype & DbeFile::F_FICTION) != 0)
|
|
continue;
|
|
if (df->get_location () == NULL)
|
|
{
|
|
copy_files->append (df);
|
|
continue;
|
|
}
|
|
if ((df->filetype & DbeFile::F_JAVACLASS) != 0)
|
|
{
|
|
if (df->container)
|
|
{ // Found in .jar file
|
|
copy_files->append (df->container);
|
|
}
|
|
copy_files->append (df);
|
|
if ((s_option & ARCH_EXE_ONLY) != 0)
|
|
continue;
|
|
}
|
|
lo->sync_read_stabs ();
|
|
Elf *elf = lo->get_elf ();
|
|
if (elf && (lo->checksum != 0) && (lo->checksum != elf->elf_checksum ()))
|
|
{
|
|
if (!quiet)
|
|
fprintf (stderr, GTXT ("er_archive: '%s' has an unexpected checksum value; perhaps it was rebuilt. File ignored\n"),
|
|
df->get_location ());
|
|
continue;
|
|
}
|
|
copy_files->append (df);
|
|
if (elf)
|
|
{
|
|
Elf *f = elf->find_ancillary_files (lo->get_pathname ());
|
|
if (f)
|
|
copy_files->append (f->dbeFile);
|
|
for (long i1 = 0, sz1 = VecSize(elf->ancillary_files); i1 < sz1; i1++)
|
|
{
|
|
Elf *ancElf = elf->ancillary_files->get (i1);
|
|
copy_files->append (ancElf->dbeFile);
|
|
}
|
|
}
|
|
Vector<Module*> *modules = lo->seg_modules;
|
|
for (long i1 = 0, sz1 = VecSize(modules); i1 < sz1; i1++)
|
|
{
|
|
Module *mod = modules->get (i1);
|
|
if ((mod->flags & MOD_FLAG_UNKNOWN) != 0)
|
|
continue;
|
|
else if ((s_option & (ARCH_USED_EXE_ONLY | ARCH_USED_SRC_ONLY)) != 0 &&
|
|
!mod->isUsed)
|
|
continue;
|
|
if ((s_option & ARCH_ALL) != 0)
|
|
mod->read_stabs (false); // Find all Sources
|
|
if (mod->dot_o_file && mod->dot_o_file->dbeFile)
|
|
copy_files->append (mod->dot_o_file->dbeFile);
|
|
}
|
|
}
|
|
delete loadObjs;
|
|
|
|
int bmask = DbeFile::F_LOADOBJ | DbeFile::F_JAVACLASS | DbeFile::F_JAR_FILE |
|
|
DbeFile::F_DOT_O | DbeFile::F_DEBUG_FILE;
|
|
if ((s_option & (ARCH_USED_SRC_ONLY | ARCH_ALL)) != 0)
|
|
{
|
|
bmask |= DbeFile::F_JAVA_SOURCE | DbeFile::F_SOURCE;
|
|
Vector<SourceFile*> *sources = dbeSession->get_sources ();
|
|
for (long i = 0, sz = VecSize(sources); i < sz; i++)
|
|
{
|
|
SourceFile *src = sources->get (i);
|
|
if ((src->flags & SOURCE_FLAG_UNKNOWN) != 0)
|
|
continue;
|
|
else if ((s_option & ARCH_USED_SRC_ONLY) != 0)
|
|
{
|
|
if ((src->dbeFile->filetype & DbeFile::F_JAVA_SOURCE) != 0 &&
|
|
!src->isUsed)
|
|
continue;
|
|
}
|
|
if (src->dbeFile)
|
|
copy_files->append (src->dbeFile);
|
|
}
|
|
}
|
|
|
|
Vector <DbeFile*> *notfound_files = new Vector<DbeFile*>();
|
|
for (long i = 0, sz = VecSize(copy_files); i < sz; i++)
|
|
{
|
|
DbeFile *df = copy_files->get (i);
|
|
char *fnm = df->get_location ();
|
|
char *nm = df->get_name ();
|
|
Dprintf (DEBUG_ARCHIVE,
|
|
"%s::%d copy_files[%ld] filetype=%4d inArchive=%d '%s' --> '%s'\n",
|
|
get_basename (__FILE__), (int) __LINE__, i,
|
|
df->filetype, df->inArchive ? 1 : 0, STR (nm), STR (fnm));
|
|
Dprintf (DEBUG_ARCHIVE && df->container,
|
|
" copy_files[%ld]: Found '%s' in '%s'\n",
|
|
i, STR (nm), STR (df->container->get_name ()));
|
|
if (fnm == NULL)
|
|
{
|
|
if (!quiet)
|
|
notfound_files->append (df);
|
|
continue;
|
|
}
|
|
else if (df->inArchive)
|
|
{
|
|
Dprintf (DEBUG_ARCHIVE,
|
|
" NOT COPIED: copy_files[%ld]: inArchive=1 '%s'\n",
|
|
i, STR (nm));
|
|
continue;
|
|
}
|
|
else if ((df->filetype & bmask) == 0)
|
|
{
|
|
Dprintf (DEBUG_ARCHIVE,
|
|
" NOT COPIED: copy_files[%ld]: container=%p filetype=%d bmask=%d '%s'\n",
|
|
i, df->container, df->filetype, bmask, STR (nm));
|
|
continue;
|
|
}
|
|
else if (df->container &&
|
|
(df->filetype & (DbeFile::F_JAVA_SOURCE | DbeFile::F_SOURCE)) == 0)
|
|
{
|
|
Dprintf (DEBUG_ARCHIVE,
|
|
" NOT COPIED: copy_files[%ld]: container=%p filetype=%d bmask=%d '%s'\n",
|
|
i, df->container, df->filetype, bmask, STR (nm));
|
|
continue;
|
|
}
|
|
else if (!mask_is_on (df->get_name ()))
|
|
{
|
|
Dprintf (DEBUG_ARCHIVE,
|
|
" NOT COPIED: copy_files[%ld]: mask is off for '%s'\n",
|
|
i, STR (nm));
|
|
continue;
|
|
}
|
|
char *anm = founder_exp->getNameInArchive (nm, false);
|
|
if (force)
|
|
unlink (anm);
|
|
int res = founder_exp->copy_file (fnm, anm, quiet, common_archive_dir, use_relative_path);
|
|
if (0 == res) // file successfully archived
|
|
df->inArchive = 1;
|
|
delete anm;
|
|
}
|
|
delete copy_files;
|
|
|
|
if (notfound_files->size () > 0)
|
|
{
|
|
for (long i = 0, sz = notfound_files->size (); i < sz; i++)
|
|
{
|
|
DbeFile *df = notfound_files->get (i);
|
|
fprintf (stderr, GTXT ("er_archive: Cannot find file: `%s'\n"), df->get_name ());
|
|
}
|
|
fprintf (stderr, GTXT ("\n If you know the correct location of the missing file(s)"
|
|
" you can help %s to find them by manually editing the .gprofng.rc file."
|
|
" See %s man pages for more details.\n"),
|
|
whoami, whoami);
|
|
}
|
|
delete notfound_files;
|
|
}
|
|
|
|
int
|
|
er_archive::check_args (int argc, char *argv[])
|
|
{
|
|
int opt;
|
|
int rseen = 0;
|
|
int dseen = 0;
|
|
// Parsing the command line
|
|
opterr = 0;
|
|
optind = 1;
|
|
static struct option long_options[] = {
|
|
{"help", no_argument, 0, 'h'},
|
|
{"version", no_argument, 0, 'V'},
|
|
{"whoami", required_argument, 0, 'w'},
|
|
{"outfile", required_argument, 0, 'O'},
|
|
{NULL, 0, 0, 0}
|
|
};
|
|
while (1)
|
|
{
|
|
int option_index = 0;
|
|
opt = getopt_long (argc, argv, NTXT (":VFa:d:qnr:m:"),
|
|
long_options, &option_index);
|
|
if (opt == EOF)
|
|
break;
|
|
switch (opt)
|
|
{
|
|
case 'F':
|
|
force = 1;
|
|
break;
|
|
case 'd': // Common archive directory (absolute path)
|
|
if (rseen)
|
|
{
|
|
fprintf (stderr, GTXT ("Error: invalid combination of options: -r and -d are in conflict.\n"));
|
|
return -1;
|
|
}
|
|
if (dseen)
|
|
fprintf (stderr, GTXT ("Warning: option -d was specified several times. Last value is used.\n"));
|
|
free (common_archive_dir);
|
|
common_archive_dir = strdup (optarg);
|
|
dseen = 1;
|
|
break;
|
|
case 'q':
|
|
quiet = 1;
|
|
break;
|
|
case 'n':
|
|
descendant = 0;
|
|
break;
|
|
case 'r': // Common archive directory (relative path)
|
|
if (dseen)
|
|
{
|
|
fprintf (stderr, GTXT ("Error: invalid combination of options: -d and -r are in conflict.\n"));
|
|
return -1;
|
|
}
|
|
if (rseen)
|
|
fprintf (stderr, GTXT ("Warning: option -r was specified several times. Last value is used.\n"));
|
|
free (common_archive_dir);
|
|
common_archive_dir = strdup (optarg);
|
|
use_relative_path = 1;
|
|
rseen = 1;
|
|
break;
|
|
case 'a':
|
|
if (strcmp (optarg, "off") == 0)
|
|
s_option = ARCH_NOTHING;
|
|
else if (strcmp (optarg, "on") == 0 ||
|
|
strcmp (optarg, "ldobjects") == 0)
|
|
s_option = ARCH_EXE_ONLY;
|
|
else if (strcmp (optarg, "usedldobjects") == 0)
|
|
s_option = ARCH_USED_EXE_ONLY;
|
|
else if (strcmp (optarg, "usedsrc") == 0)
|
|
s_option = ARCH_USED_EXE_ONLY | ARCH_USED_SRC_ONLY;
|
|
else if (strcmp (optarg, "all") == 0 || strcmp (optarg, "src") == 0)
|
|
s_option = ARCH_ALL;
|
|
else
|
|
{
|
|
fprintf (stderr, GTXT ("Error: invalid option: `-%c %s'\n"),
|
|
optopt, optarg);
|
|
return -1;
|
|
}
|
|
break;
|
|
case 'm':
|
|
{
|
|
regex_t *regex_desc = new regex_t ();
|
|
if (regcomp (regex_desc, optarg, REG_EXTENDED | REG_NOSUB | REG_NEWLINE))
|
|
{
|
|
delete regex_desc;
|
|
fprintf (stderr, GTXT ("Error: invalid option: `-%c %s'\n"),
|
|
optopt, optarg);
|
|
return -1;
|
|
}
|
|
if (mask == NULL)
|
|
mask = new Vector<regex_t *>();
|
|
mask->append (regex_desc);
|
|
break;
|
|
}
|
|
case 'O':
|
|
{
|
|
int fd = open (optarg, O_WRONLY | O_CREAT | O_APPEND, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
|
|
if (fd == -1)
|
|
{
|
|
fprintf (stderr, GTXT ("er_archive: Can't open %s: %s\n"),
|
|
optarg, strerror (errno));
|
|
break;
|
|
}
|
|
if (dup2 (fd, 2) == -1)
|
|
{
|
|
close (fd);
|
|
fprintf (stderr, GTXT ("er_archive: Can't divert stderr: %s\n"),
|
|
strerror (errno));
|
|
break;
|
|
}
|
|
if (dup2 (fd, 1) == -1)
|
|
{
|
|
close (fd);
|
|
fprintf (stderr, GTXT ("er_archive: Can't divert stdout: %s\n"),
|
|
strerror (errno));
|
|
break;
|
|
}
|
|
close (fd);
|
|
struct timeval tp;
|
|
gettimeofday (&tp, NULL);
|
|
fprintf (stderr, "### Start %s#", ctime (&tp.tv_sec));
|
|
for (int i = 0; i < argc; i++)
|
|
fprintf (stderr, " %s", argv[i]);
|
|
fprintf (stderr, "\n");
|
|
break;
|
|
}
|
|
case 'V':
|
|
// Ruud
|
|
Application::print_version_info ();
|
|
/*
|
|
printf (GTXT ("GNU %s version %s\n"), get_basename (prog_name), VERSION);
|
|
*/
|
|
exit (0);
|
|
case 'w':
|
|
whoami = optarg;
|
|
break;
|
|
case 'h':
|
|
usage ();
|
|
exit (0);
|
|
case ':': // -s -m without operand
|
|
fprintf (stderr, GTXT ("Option -%c requires an operand\n"), optopt);
|
|
return -1;
|
|
case '?':
|
|
default:
|
|
fprintf (stderr, GTXT ("Unrecognized option: -%c\n"), optopt);
|
|
return -1;
|
|
}
|
|
}
|
|
return optind;
|
|
}
|
|
|
|
void
|
|
er_archive::check_env_var ()
|
|
{
|
|
char *ename = NTXT ("GPROFNG_ARCHIVE");
|
|
char *var = getenv (ename);
|
|
if (var == NULL)
|
|
return;
|
|
var = dbe_strdup (var);
|
|
Vector<char*> *opts = new Vector<char*>();
|
|
opts->append (ename);
|
|
for (char *s = var;;)
|
|
{
|
|
while (*s && isblank (*s))
|
|
s++;
|
|
if (*s == 0)
|
|
break;
|
|
opts->append (s);
|
|
while (*s && !isblank (*s))
|
|
s++;
|
|
if (*s == 0)
|
|
break;
|
|
*s = 0;
|
|
s++;
|
|
}
|
|
if (opts->size () > 0)
|
|
{
|
|
char **arr = (char **) malloc (sizeof (char *) *opts->size ());
|
|
for (long i = 0; i < opts->size (); i++)
|
|
arr[i] = opts->get (i);
|
|
if (-1 == check_args (opts->size (), arr))
|
|
fprintf (stderr, GTXT ("Error: Wrong SP_ER_ARCHIVE: '%s'\n"), var);
|
|
free (arr);
|
|
}
|
|
delete opts;
|
|
free (var);
|
|
}
|
|
|
|
static int
|
|
real_main (int argc, char *argv[])
|
|
{
|
|
er_archive *archive = new er_archive (argc, argv);
|
|
dbeSession->archive_mode = 1;
|
|
archive->start (argc, argv);
|
|
dbeSession->unlink_tmp_files ();
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
* Call catch_out_of_memory(int (*real_main)(int, char*[]), int argc, char *argv[]) which will call real_main()
|
|
* @param argc
|
|
* @param argv
|
|
* @return
|
|
*/
|
|
int
|
|
main (int argc, char *argv[])
|
|
{
|
|
return catch_out_of_memory (real_main, argc, argv);
|
|
}
|