Exheredludis/paludis/tar_merger.cc
Saleem Abdulrasool 16b3eee5ba cleanup not-reached warnings
Use the preprocessor more aggresively to avoid a not-reached warning, and mark
functions as non-return if necessary.
2013-03-02 09:24:47 -08:00

212 lines
6.1 KiB
C++

/* vim: set sw=4 sts=4 et foldmethod=syntax : */
/*
* Copyright (c) 2010, 2011 Ciaran McCreesh
*
* This file is part of the Paludis package manager. Paludis is free software;
* you can redistribute it and/or modify it under the terms of the GNU General
* Public License version 2, as published by the Free Software Foundation.
*
* Paludis 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, Inc., 59 Temple
* Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <paludis/tar_merger.hh>
#include <paludis/tar_extras.hh>
#include <paludis/util/pimp-impl.hh>
#include <paludis/util/make_named_values.hh>
#include <paludis/util/singleton-impl.hh>
#include <paludis/util/strip.hh>
#include <paludis/util/exception.hh>
#include <paludis/util/stringify.hh>
#include <paludis/about.hh>
#include <ostream>
#include <dlfcn.h>
#include <stdint.h>
#include "config.h"
#define STUPID_CAST(type, val) reinterpret_cast<type>(reinterpret_cast<uintptr_t>(val))
using namespace paludis;
#include <paludis/tar_merger-se.cc>
namespace
{
struct TarMergerHandle :
Singleton<TarMergerHandle>
{
typedef PaludisTarExtras * (* InitPtr) (const std::string &, const std::string &);
typedef void (* AddFilePtr) (PaludisTarExtras * const, const std::string &, const std::string &);
typedef void (* AddSymPtr) (PaludisTarExtras * const, const std::string &, const std::string &, const std::string &);
typedef void (* CleanupPtr) (PaludisTarExtras * const);
void * handle;
InitPtr init;
AddFilePtr add_file;
AddSymPtr add_sym;
CleanupPtr cleanup;
TarMergerHandle()
#ifndef ENABLE_PBINS
PALUDIS_ATTRIBUTE((noreturn))
#endif
{
#ifndef ENABLE_PBINS
throw NotAvailableError("Paludis was built without support for pbins");
#else
handle = ::dlopen(("libpaludistarextras_" + stringify(PALUDIS_PC_SLOT) + ".so").c_str(), RTLD_NOW | RTLD_GLOBAL);
if (! handle)
throw MergerError("Unable to open libpaludistarextras due to error '" + stringify(::dlerror()) + "' from dlopen");
init = STUPID_CAST(InitPtr, ::dlsym(handle, "paludis_tar_extras_init"));
if (! init)
throw MergerError("Unable to init from libpaludistarextras due to error '" + stringify(::dlerror()) + "' from dlsym");
add_file = STUPID_CAST(AddFilePtr, ::dlsym(handle, "paludis_tar_extras_add_file"));
if (! add_file)
throw MergerError("Unable to add_file from libpaludistarextras due to error '" + stringify(::dlerror()) + "' from dlsym");
add_sym = STUPID_CAST(AddSymPtr, ::dlsym(handle, "paludis_tar_extras_add_sym"));
if (! add_sym)
throw MergerError("Unable to add_sym from libpaludistarextras due to error '" + stringify(::dlerror()) + "' from dlsym");
cleanup = STUPID_CAST(CleanupPtr, ::dlsym(handle, "paludis_tar_extras_cleanup"));
if (! cleanup)
throw MergerError("Unable to cleanup from libpaludistarextras due to error '" + stringify(::dlerror()) + "' from dlsym");
#endif
}
~TarMergerHandle()
{
if (handle)
::dlclose(handle);
}
};
}
namespace paludis
{
template <>
struct Imp<TarMerger>
{
TarMergerParams params;
PaludisTarExtras * tar;
Imp(const TarMergerParams & p) :
params(p)
{
}
};
}
TarMerger::TarMerger(const TarMergerParams & p) :
Merger(make_named_values<MergerParams>(
n::environment() = p.environment(),
n::fix_mtimes_before() = p.fix_mtimes_before(),
n::get_new_ids_or_minus_one() = p.get_new_ids_or_minus_one(),
n::image() = p.image(),
n::install_under() = FSPath("/"),
n::maybe_output_manager() = p.maybe_output_manager(),
n::merged_entries() = p.merged_entries(),
n::no_chown() = p.no_chown(),
n::options() = p.options(),
n::permit_destination() = p.permit_destination(),
n::root() = p.root()
)),
_imp(p)
{
}
TarMerger::~TarMerger() = default;
void
TarMerger::on_file_main(bool is_check, const FSPath & src, const FSPath & dst)
{
if (is_check)
return;
add_file(src, dst / src.basename());
}
void
TarMerger::add_file(const FSPath & src, const FSPath & dst)
{
track_install_file(src, dst);
(*TarMergerHandle::get_instance()->add_file)(_imp->tar, stringify(src), strip_leading(stringify(dst), "/"));
}
void
TarMerger::on_dir_main(bool, const FSPath &, const FSPath &)
{
}
void
TarMerger::on_sym_main(bool is_check, const FSPath & src, const FSPath & dst)
{
if (is_check)
return;
track_install_sym(src, dst / src.basename());
(*TarMergerHandle::get_instance()->add_sym)(_imp->tar, stringify(src), strip_leading(stringify(dst / src.basename()), "/"),
stringify(src.readlink()));
}
void
TarMerger::prepare_install_under()
{
}
void
TarMerger::merge()
{
std::string compress;
switch (_imp->params.compression())
{
case tmc_none:
compress = "none";
break;
case tmc_bz2:
compress = "bz2";
break;
case last_tmc:
break;
};
if (compress.empty())
throw InternalError(PALUDIS_HERE, "unknown compress");
_imp->tar = (*TarMergerHandle::get_instance()->init)(stringify(_imp->params.tar_file()), compress);
try
{
Merger::merge();
(*TarMergerHandle::get_instance()->cleanup)(_imp->tar);
}
catch (...)
{
(*TarMergerHandle::get_instance()->cleanup)(_imp->tar);
throw;
}
}
FSPath
TarMerger::canonicalise_root_path(const FSPath & f)
{
return f;
}