diff options
author | 2010-11-25 17:38:25 +0000 | |
---|---|---|
committer | 2010-11-25 17:38:25 +0000 | |
commit | 4b361a649a3c620ff323710e598121a2fff03667 (patch) | |
tree | a896ce9279ab996ea54c2eb0dc16a423ebf4080e | |
parent | 9c9ff3fd4b60a97b261d343ddf49d43fc439cef8 (diff) | |
download | paludis-4b361a649a3c620ff323710e598121a2fff03667.tar.gz paludis-4b361a649a3c620ff323710e598121a2fff03667.tar.xz |
Use libmagic rather than file for stripping
-rw-r--r-- | paludis/Makefile.am.m4 | 9 | ||||
-rw-r--r-- | paludis/stripper.cc | 118 | ||||
-rw-r--r-- | paludis/stripper.hh | 8 | ||||
-rw-r--r-- | paludis/stripper_extras.cc | 73 | ||||
-rw-r--r-- | paludis/stripper_extras.hh | 32 |
5 files changed, 230 insertions, 10 deletions
diff --git a/paludis/Makefile.am.m4 b/paludis/Makefile.am.m4 index 3d6ca6008..32647626d 100644 --- a/paludis/Makefile.am.m4 +++ b/paludis/Makefile.am.m4 @@ -155,6 +155,15 @@ libpaludistarextras_@PALUDIS_PC_SLOT@_la_CXXFLAGS = $(AM_CXXFLAGS) libpaludistarextras_@PALUDIS_PC_SLOT@_la_LIBADD = -larchive libpaludistarextras_@PALUDIS_PC_SLOT@_la_LDFLAGS = -version-info @VERSION_LIB_CURRENT@:@VERSION_LIB_REVISION@:0 +if ENABLE_STRIPPER +lib_LTLIBRARIES += libpaludisstripperextras_@PALUDIS_PC_SLOT@.la +endif + +libpaludisstripperextras_@PALUDIS_PC_SLOT@_la_SOURCES = stripper_extras.cc stripper_extras.hh +libpaludisstripperextras_@PALUDIS_PC_SLOT@_la_CXXFLAGS = $(AM_CXXFLAGS) $(LIBMAGICDEPS_CFLAGS) +libpaludisstripperextras_@PALUDIS_PC_SLOT@_la_LIBADD = $(LIBMAGICDEPS_LIBS) +libpaludisstripperextras_@PALUDIS_PC_SLOT@_la_LDFLAGS = -version-info @VERSION_LIB_CURRENT@:@VERSION_LIB_REVISION@:0 + paludis_includedir = $(includedir)/paludis-$(PALUDIS_PC_SLOT)/paludis/ paludis_include_HEADERS = headerlist seheaderlist diff --git a/paludis/stripper.cc b/paludis/stripper.cc index 320d7a878..c77e562c6 100644 --- a/paludis/stripper.cc +++ b/paludis/stripper.cc @@ -18,6 +18,8 @@ */ #include <paludis/stripper.hh> +#include <paludis/stripper_extras.hh> +#include <paludis/about.hh> #include <paludis/util/pimp-impl.hh> #include <paludis/util/strip.hh> #include <paludis/util/stringify.hh> @@ -26,6 +28,7 @@ #include <paludis/util/fs_iterator.hh> #include <paludis/util/fs_stat.hh> #include <paludis/util/options.hh> +#include <paludis/util/singleton-impl.hh> #include <functional> #include <sstream> #include <list> @@ -33,10 +36,86 @@ #include <algorithm> #include <sys/stat.h> +#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; typedef std::set<std::pair<dev_t, ino_t> > StrippedSet; +StripperError::StripperError(const std::string & s) throw () : + Exception(s) +{ +} + +namespace +{ + struct StripperHandle : + Singleton<StripperHandle> + { + typedef PaludisStripperExtras * (* InitPtr) (); + typedef const std::string (* LookupPtr) (PaludisStripperExtras * const, const std::string &); + typedef void (* CleanupPtr) (PaludisStripperExtras * const); + + void * handle; + InitPtr init; + LookupPtr lookup; + CleanupPtr cleanup; + + StripperHandle() : + handle(0), + init(0), + lookup(0), + cleanup(0) + { +#ifndef ENABLE_STRIPPER + Log::get_instance()->message("strip.unsupported", ll_warning, lc_context) + << "Paludis was built without support for stripping. No stripping will be done."; +#else + do + { + handle = ::dlopen(("libpaludisstripperextras_" + stringify(PALUDIS_PC_SLOT) + ".so").c_str(), RTLD_NOW | RTLD_GLOBAL); + if (! handle) + break; + + init = STUPID_CAST(InitPtr, ::dlsym(handle, "paludis_stripper_extras_init")); + if (! init) + break; + + lookup = STUPID_CAST(LookupPtr, ::dlsym(handle, "paludis_stripper_extras_lookup")); + if (! lookup) + break; + + cleanup = STUPID_CAST(CleanupPtr, ::dlsym(handle, "paludis_stripper_extras_cleanup")); + if (! cleanup) + break; + } + while (false); + + if (! (handle && init && lookup && cleanup)) + { + Log::get_instance()->message("strip.broken", ll_warning, lc_context) + << "Stripping cannot be used due to error '" << stringify(::dlerror()) << "' when using libpaludisstripperextras"; + + if (handle) + ::dlclose(handle); + handle = 0; + } +#endif + } + + ~StripperHandle() + { + if (handle) + ::dlclose(handle); + } + }; +} + namespace paludis { template <> @@ -44,10 +123,29 @@ namespace paludis { StripperOptions options; StrippedSet stripped_ids; + PaludisStripperExtras * stripper_extras; Imp(const StripperOptions & o) : - options(o) + options(o), + stripper_extras(0) { + try + { + if (StripperHandle::get_instance()->handle) + stripper_extras = StripperHandle::get_instance()->init(); + } + catch (const StripperError & e) + { + Log::get_instance()->message("strip.broken", ll_warning, lc_context) + << "Got error '" << e.message() << "' (" << e.what() << ") when attempting to strip"; + stripper_extras = 0; + } + } + + ~Imp() + { + if (stripper_extras) + StripperHandle::get_instance()->cleanup(stripper_extras); } }; } @@ -129,15 +227,15 @@ Stripper::file_type(const FSPath & f) { Context context("When finding the file type of '" + stringify(f) + "':"); - std::stringstream s; - - Process file_process(ProcessCommand({ "file", stringify(f) })); - file_process.capture_stdout(s); - if (0 != file_process.run().wait()) - Log::get_instance()->message("strip.identification_failed", ll_warning, lc_context) - << "Couldn't work out the file type of '" << f << "'"; - - return s.str(); + if (_imp->stripper_extras) + { + std::string result(StripperHandle::get_instance()->lookup(_imp->stripper_extras, stringify(f))); + Log::get_instance()->message("strip.type", ll_debug, lc_context) + << "Magic says '" << f << "' is '" << result << "'"; + return result; + } + else + return ""; } void diff --git a/paludis/stripper.hh b/paludis/stripper.hh index f97b1ae3d..ca1d90462 100644 --- a/paludis/stripper.hh +++ b/paludis/stripper.hh @@ -26,6 +26,7 @@ #include <paludis/util/pimp.hh> #include <paludis/util/fs_path.hh> #include <paludis/util/named_value.hh> +#include <paludis/util/exception.hh> namespace paludis { @@ -45,6 +46,13 @@ namespace paludis NamedValue<n::strip, bool> strip; }; + class PALUDIS_VISIBLE StripperError : + public Exception + { + public: + StripperError(const std::string &) throw (); + }; + class PALUDIS_VISIBLE Stripper : private Pimp<Stripper> { diff --git a/paludis/stripper_extras.cc b/paludis/stripper_extras.cc new file mode 100644 index 000000000..6ffc45b29 --- /dev/null +++ b/paludis/stripper_extras.cc @@ -0,0 +1,73 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 2010 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/stripper_extras.hh> +#include <paludis/stripper.hh> +#include <magic.h> + +#include "config.h" + +using namespace paludis; + +struct PaludisStripperExtras +{ + magic_t magic; +}; + +extern "C" +PaludisStripperExtras * +paludis_stripper_extras_init() +{ + auto extras(new PaludisStripperExtras); + extras->magic = magic_open(MAGIC_NONE); + + if (! extras->magic) + throw StripperError("magic_open returned null"); + + if (-1 == magic_load(extras->magic, NULL)) + throw StripperError("magic_load returned error"); + + return extras; +} + +extern "C" +const std::string +paludis_stripper_extras_lookup(PaludisStripperExtras * const extras, const std::string & path) +{ + auto result(magic_file(extras->magic, path.c_str())); + if (! result) + { + result = magic_error(extras->magic); + if (result) + return "(error) " + std::string(result); + else + return "(no error)"; + } + + return std::string(result); +} + +extern "C" +void +paludis_stripper_extras_cleanup(PaludisStripperExtras * const extras) +{ + magic_close(extras->magic); + delete extras; +} + diff --git a/paludis/stripper_extras.hh b/paludis/stripper_extras.hh new file mode 100644 index 000000000..a39f92107 --- /dev/null +++ b/paludis/stripper_extras.hh @@ -0,0 +1,32 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 2010 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 + */ + +#ifndef PALUDIS_GUARD_PALUDIS_STRIPPER_EXTRAS_HH +#define PALUDIS_GUARD_PALUDIS_STRIPPER_EXTRAS_HH 1 + +#include <paludis/util/attributes.hh> +#include <string> + +struct PaludisStripperExtras; + +extern "C" PaludisStripperExtras * paludis_stripper_extras_init() PALUDIS_VISIBLE PALUDIS_ATTRIBUTE((warn_unused_result)); +extern "C" const std::string paludis_stripper_extras_lookup(PaludisStripperExtras * const, const std::string &) PALUDIS_VISIBLE; +extern "C" void paludis_stripper_extras_cleanup(PaludisStripperExtras * const) PALUDIS_VISIBLE; + +#endif |