aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAvatar Ciaran McCreesh <ciaran.mccreesh@googlemail.com> 2010-11-25 17:38:25 +0000
committerAvatar Ciaran McCreesh <ciaran.mccreesh@googlemail.com> 2010-11-25 17:38:25 +0000
commit4b361a649a3c620ff323710e598121a2fff03667 (patch)
treea896ce9279ab996ea54c2eb0dc16a423ebf4080e
parent9c9ff3fd4b60a97b261d343ddf49d43fc439cef8 (diff)
downloadpaludis-4b361a649a3c620ff323710e598121a2fff03667.tar.gz
paludis-4b361a649a3c620ff323710e598121a2fff03667.tar.xz
Use libmagic rather than file for stripping
-rw-r--r--paludis/Makefile.am.m49
-rw-r--r--paludis/stripper.cc118
-rw-r--r--paludis/stripper.hh8
-rw-r--r--paludis/stripper_extras.cc73
-rw-r--r--paludis/stripper_extras.hh32
5 files changed, 230 insertions, 10 deletions
diff --git a/paludis/Makefile.am.m4 b/paludis/Makefile.am.m4
index 3d6ca60..3264762 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 320d7a8..c77e562 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 f97b1ae..ca1d904 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 0000000..6ffc45b
--- /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 0000000..a39f921
--- /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