From 2b8ffb145e7d88ac2564c973395d847d22fec9e5 Mon Sep 17 00:00:00 2001 From: Olly Betts Date: Wed, 30 Nov 2016 19:35:20 +1300 Subject: [PATCH] Support reading UUIDs from /proc/sys/kernel/random/uuid Especially useful when building for Android, as it avoids having to cross-build a UUID library. (cherry picked from commit 2d4b56b3bcda3006a8d2a4f234a06ae6784e0432) --- xapian-core/INSTALL | 7 +-- xapian-core/common/Makefile.mk | 6 +++ xapian-core/common/proc_uuid.cc | 97 +++++++++++++++++++++++++++++++++++++++++ xapian-core/common/proc_uuid.h | 37 ++++++++++++++++ xapian-core/common/safeuuid.h | 10 +++-- xapian-core/configure.ac | 17 +++++++- 6 files changed, 167 insertions(+), 7 deletions(-) create mode 100644 xapian-core/common/proc_uuid.cc create mode 100644 xapian-core/common/proc_uuid.h diff --git a/xapian-core/INSTALL b/xapian-core/INSTALL index 0fbbdcfd3..f06aaf791 100644 --- a/xapian-core/INSTALL +++ b/xapian-core/INSTALL @@ -23,9 +23,10 @@ deflateInit2 (which Xapian uses) and decompression is supposed to be about 20% faster than with 1.1.x, but it's pretty unlikely you'll have an older version installed these days. -Xapian 1.1.0 and higher also requires a library which can generate UUIDs. -On FreeBSD, NetBSD, and Microsoft Windows, Xapian makes use of built-in UUID -APIs. On other platforms, you need to install libuuid which you can find in +Xapian also requires a way to generate UUIDs. On FreeBSD, NetBSD, and +Microsoft Windows, Xapian makes use of built-in UUID APIs. On Linux and +Android, Xapian 1.4.2 and higher can read UUIDs from a special file under +/proc. Otherwise you need to install libuuid which you can find in util-linux-ng (http://userweb.kernel.org/~kzak/util-linux-ng/). On Debian and Ubuntu, the package to install is uuid-dev, while on Fedora, it is libuuid-devel (on older Fedora versions you instead need e2fsprogs-devel). diff --git a/xapian-core/common/Makefile.mk b/xapian-core/common/Makefile.mk index 54149d5fe..5eec1a0c2 100644 --- a/xapian-core/common/Makefile.mk +++ b/xapian-core/common/Makefile.mk @@ -22,6 +22,7 @@ noinst_HEADERS +=\ common/pack.h\ common/posixy_wrapper.h\ common/pretty.h\ + common/proc_uuid.h\ common/realtime.h\ common/remoteprotocol.h\ common/replicate_utils.h\ @@ -79,6 +80,11 @@ lib_src +=\ libxapian_la_LDFLAGS += -lrpcrt4 endif +if USE_PROC_FOR_UUID +lib_src +=\ + common/proc_uuid.cc +endif + noinst_LTLIBRARIES += libgetopt.la libgetopt_la_SOURCES =\ diff --git a/xapian-core/common/proc_uuid.cc b/xapian-core/common/proc_uuid.cc new file mode 100644 index 000000000..3aef5d34c --- /dev/null +++ b/xapian-core/common/proc_uuid.cc @@ -0,0 +1,97 @@ +/** @file proc_uuid.cc + * @brief Generate UUIDs by reading from a pseudo-file under /proc + * + * Especially useful when building for Android, as it avoids having to + * cross-build a UUID library. + */ +/* Copyright (C) 2008 Lemur Consulting Ltd + * Copyright (C) 2013,2015,2016 Olly Betts + * + * 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 2 of the License, 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, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include + +#include "proc_uuid.h" + +#include "xapian/error.h" + +#include +#include "stringutils.h" + +#include +#include "safesysstat.h" +#include "safefcntl.h" +#include "safeunistd.h" + +using namespace std; + +/// The size of a UUID in bytes. +const size_t UUID_SIZE = 16; + +/// The size of a UUID string in bytes (not including trailing '\0'). +const size_t UUID_STRING_SIZE = 36; + +void +uuid_generate(uuid_t uu) +{ + char buf[37]; + int fd = open("/proc/sys/kernel/random/uuid", O_RDONLY); + if (rare(fd == -1)) { + throw Xapian::DatabaseCreateError("Opening UUID generator failed", errno); + } + if (read(fd, buf, 36) != 36) { + close(fd); + throw Xapian::DatabaseCreateError("Generating UUID failed"); + } + close(fd); + buf[36] = '\0'; + uuid_parse(buf, uu); +} + +int +uuid_parse(const char * in, uuid_t uu) +{ + for (unsigned i = 0; i != UUID_SIZE; ++i) { + uu[i] = hex_digit(in[0]) << 4 | hex_digit(in[1]); + in += ((0x2a8 >> i) & 1) | 2; + } + return 0; +} + +void uuid_unparse_lower(const uuid_t uu, char * out) +{ + for (unsigned i = 0; i != UUID_SIZE; ++i) { + sprintf(out, "%02x", uu[i]); + out += 2; + if ((0x2a8 >> i) & 1) + *out++ = '-'; + } +} + +void uuid_clear(uuid_t uu) +{ + memset(uu, 0, UUID_SIZE); +} + +int uuid_is_null(const uuid_t uu) +{ + unsigned i = 0; + while (i < UUID_SIZE) { + if (uu[i++]) + return 0; + } + return 1; +} diff --git a/xapian-core/common/proc_uuid.h b/xapian-core/common/proc_uuid.h new file mode 100644 index 000000000..e37ae723f --- /dev/null +++ b/xapian-core/common/proc_uuid.h @@ -0,0 +1,37 @@ +/* @file proc_uuid.h + * @brief Provide UUID functions compatible with libuuid from util-linux-ng. + */ +/* Copyright 2008 Lemur Consulting Ltd + * Copyright 2016 Olly Betts + * + * 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 2 of the + * License, 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, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef XAPIAN_INCLUDED_PROC_UUID_H +#define XAPIAN_INCLUDED_PROC_UUID_H + +typedef unsigned char uuid_t[16]; + +void uuid_generate(uuid_t uu); + +int uuid_parse(const char * in, uuid_t uu); + +void uuid_unparse_lower(const uuid_t uu, char * out); + +void uuid_clear(uuid_t uu); + +int uuid_is_null(const uuid_t uu); + +#endif /* XAPIAN_INCLUDED_PROC_UUID_H */ diff --git a/xapian-core/common/safeuuid.h b/xapian-core/common/safeuuid.h index a63e3368c..6be7f1730 100644 --- a/xapian-core/common/safeuuid.h +++ b/xapian-core/common/safeuuid.h @@ -1,8 +1,8 @@ /** @file safeuuid.h - * @brief #include , with alternative implementation for windows. + * @brief #include , with alternative implementations. */ /* Copyright (C) 2008 Lemur Consulting Ltd - * Copyright (C) 2009,2010,2013 Olly Betts + * Copyright (C) 2009,2010,2013,2016 Olly Betts * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as @@ -51,7 +51,7 @@ inline void uuid_unparse_lower(uuid_t uu, char *out) { } # endif -#else +#elif defined HAVE_UUID_H // UUID API on FreeBSD, NetBSD and AIX. @@ -148,6 +148,10 @@ uuid_is_null(const uuid_t_ uu) // Hide incompatible uuid_t from . # define uuid_t uuid_t_ +#elif defined USE_PROC_FOR_UUID +# include "common/proc_uuid.h" +#else +# error Do not know how to generate UUIDs #endif #endif // XAPIAN_INCLUDED_SAFEUUID_H diff --git a/xapian-core/configure.ac b/xapian-core/configure.ac index 307c83e7f..fdb683a66 100644 --- a/xapian-core/configure.ac +++ b/xapian-core/configure.ac @@ -743,6 +743,7 @@ XAPIAN_BACKEND_ENABLE([glass]) XAPIAN_BACKEND_ENABLE([inmemory]) XAPIAN_BACKEND_ENABLE([remote]) +use_proc_for_uuid=0 use_win32_uuid_api=0 case $enable_backend_chert$enable_backend_glass in *yes*) @@ -796,7 +797,20 @@ case $enable_backend_chert$enable_backend_glass in AC_MSG_ERROR([uuid.h found, but uuid_create() not found. You probably wants to install libuuid from util-linux-ng or e2fsprogs (you may need to install the uuid-dev, libuuid-devel or e2fsprogs-devel package)]) ]) ], [ - AC_MSG_ERROR([Neither uuid/uuid.h nor uuid.h found - required for chert and glass (you may need to install the uuid-dev, libuuid-devel or e2fsprogs-devel package)]) + dnl Especially useful for Android. + AC_MSG_CHECKING([if host platform supports /proc/sys/kernel/random/uuid]) + case $host_os in + linux*) + use_proc_for_uuid=1 + AC_DEFINE([USE_PROC_FOR_UUID], [1], + [Define to 1 to read UUID from '/proc/sys/kernel/random/uuid']) + AC_MSG_RESULT([yes]) + ;; + *) + AC_MSG_RESULT([no]) + AC_MSG_ERROR([Failed to find a way to generate UUIDs, required for chert and glass backends (you may need to install the uuid-dev, libuuid-devel or e2fsprogs-devel package)]) + ;; + esac ], [ ]) ], [ ]) ;; @@ -812,6 +826,7 @@ case $enable_backend_chert$enable_backend_glass in LIBS=$SAVE_LIBS ;; esac +AM_CONDITIONAL([USE_PROC_FOR_UUID], [test "$use_proc_for_uuid" = 1]) AM_CONDITIONAL([USE_WIN32_UUID_API], [test "$use_win32_uuid_api" = 1]) REMOTE_LIBS= -- 2.11.4.GIT