LCOV - code coverage report
Current view: top level - backends - uuids.cc (source / functions) Hit Total Coverage
Test: Test Coverage for xapian-core 7028d852e609 Lines: 19 19 100.0 %
Date: 2019-02-17 14:59:59 Functions: 3 3 100.0 %
Branches: 11 16 68.8 %

           Branch data     Line data    Source code
       1                 :            : /** @file uuids.cc
       2                 :            :  * @brief Class for handling UUIDs
       3                 :            :  */
       4                 :            : /* Copyright (C) 2008 Lemur Consulting Ltd
       5                 :            :  * Copyright (C) 2013,2015,2016,2017,2018 Olly Betts
       6                 :            :  *
       7                 :            :  * This program is free software; you can redistribute it and/or modify
       8                 :            :  * it under the terms of the GNU General Public License as published by
       9                 :            :  * the Free Software Foundation; either version 2 of the License, or
      10                 :            :  * (at your option) any later version.
      11                 :            :  *
      12                 :            :  * This program is distributed in the hope that it will be useful,
      13                 :            :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      14                 :            :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      15                 :            :  * GNU General Public License for more details.
      16                 :            :  *
      17                 :            :  * You should have received a copy of the GNU General Public License
      18                 :            :  * along with this program; if not, write to the Free Software
      19                 :            :  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
      20                 :            :  */
      21                 :            : 
      22                 :            : #include <config.h>
      23                 :            : 
      24                 :            : #include "uuids.h"
      25                 :            : 
      26                 :            : #include "xapian/error.h"
      27                 :            : 
      28                 :            : #include <cerrno>
      29                 :            : #include <cstring>
      30                 :            : #include "stringutils.h"
      31                 :            : 
      32                 :            : #include <sys/types.h>
      33                 :            : #include "safefcntl.h"
      34                 :            : #include "safeunistd.h"
      35                 :            : 
      36                 :            : #ifdef USE_PROC_FOR_UUID
      37                 :            : # include "safesysstat.h"
      38                 :            : #elif defined HAVE_UUID_UUID_H
      39                 :            : # include <exception>
      40                 :            : # include <uuid/uuid.h>
      41                 :            : #elif defined HAVE_UUID_H
      42                 :            : // UUID API on FreeBSD, NetBSD and AIX.
      43                 :            : # include <arpa/inet.h> // For htonl() and htons().
      44                 :            : # include <exception>
      45                 :            : # include <uuid.h>
      46                 :            : #elif defined USE_WIN32_UUID_API
      47                 :            : # include "safewindows.h"
      48                 :            : # include <rpc.h>
      49                 :            : # ifdef __WIN32__
      50                 :            : #  include "safewinsock2.h" // For htonl() and htons().
      51                 :            : # else
      52                 :            : // Cygwin:
      53                 :            : #  include <arpa/inet.h> // For htonl() and htons().
      54                 :            : # endif
      55                 :            : #endif
      56                 :            : 
      57                 :            : using namespace std;
      58                 :            : 
      59                 :            : /// Bit-mask to determine where to put hyphens in the string representation.
      60                 :            : static constexpr unsigned UUID_GAP_MASK = 0x2a8;
      61                 :            : 
      62                 :            : void
      63                 :       1287 : Uuid::generate()
      64                 :            : {
      65                 :            : #ifdef USE_PROC_FOR_UUID
      66                 :            :     char buf[STRING_SIZE];
      67                 :            :     int fd = open("/proc/sys/kernel/random/uuid", O_RDONLY);
      68                 :            :     if (rare(fd == -1)) {
      69                 :            :         throw Xapian::DatabaseCreateError("Opening UUID generator failed", errno);
      70                 :            :     }
      71                 :            :     bool failed = (read(fd, buf, STRING_SIZE) != STRING_SIZE);
      72                 :            :     close(fd);
      73                 :            :     if (failed) {
      74                 :            :         throw Xapian::DatabaseCreateError("Generating UUID failed");
      75                 :            :     }
      76                 :            :     parse(buf);
      77                 :            : #elif defined HAVE_UUID_UUID_H
      78                 :            :     uuid_t uu;
      79         [ +  - ]:       1287 :     uuid_generate(uu);
      80                 :       1287 :     memcpy(uuid_data, &uu, BINARY_SIZE);
      81                 :            : #elif defined HAVE_UUID_H
      82                 :            :     uuid_t uu;
      83                 :            :     uint32_t status;
      84                 :            :     uuid_create(&uu, &status);
      85                 :            :     if (status != uuid_s_ok) {
      86                 :            :         // Can only be uuid_s_no_memory it seems.
      87                 :            :         throw std::bad_alloc();
      88                 :            :     }
      89                 :            :     uu.time_low = htonl(uu.time_low);
      90                 :            :     uu.time_mid = htons(uu.time_mid);
      91                 :            :     uu.time_hi_and_version = htons(uu.time_hi_and_version);
      92                 :            :     memcpy(uuid_data, &uu, BINARY_SIZE);
      93                 :            : #elif defined USE_WIN32_UUID_API
      94                 :            :     UUID uuid;
      95                 :            :     if (rare(UuidCreate(&uuid) != RPC_S_OK)) {
      96                 :            :         // Throw a DatabaseCreateError, since we can't make a UUID.  The
      97                 :            :         // windows API documentation is a bit unclear about the situations in
      98                 :            :         // which this can happen.
      99                 :            :         throw Xapian::DatabaseCreateError("Cannot create UUID");
     100                 :            :     }
     101                 :            :     uuid.Data1 = htonl(uuid.Data1);
     102                 :            :     uuid.Data2 = htons(uuid.Data2);
     103                 :            :     uuid.Data3 = htons(uuid.Data3);
     104                 :            :     memcpy(uuid_data, &uuid, BINARY_SIZE);
     105                 :            : #else
     106                 :            : # error Do not know how to generate UUIDs
     107                 :            : #endif
     108                 :       1287 : }
     109                 :            : 
     110                 :            : void
     111                 :          2 : Uuid::parse(const char* in)
     112                 :            : {
     113         [ +  + ]:         34 :     for (unsigned i = 0; i != BINARY_SIZE; ++i) {
     114                 :         32 :         uuid_data[i] = hex_digit(in[0]) << 4 | hex_digit(in[1]);
     115                 :         32 :         in += ((UUID_GAP_MASK >> i) & 1) | 2;
     116                 :            :     }
     117                 :          2 : }
     118                 :            : 
     119                 :            : string
     120                 :       1339 : Uuid::to_string() const
     121                 :            : {
     122                 :       1339 :     string result;
     123         [ +  - ]:       1339 :     result.reserve(STRING_SIZE);
     124         [ +  + ]:      22763 :     for (unsigned i = 0; i != BINARY_SIZE; ++i) {
     125                 :      21424 :         unsigned char ch = uuid_data[i];
     126         [ +  - ]:      21424 :         result += "0123456789abcdef"[ch >> 4];
     127         [ +  - ]:      21424 :         result += "0123456789abcdef"[ch & 0x0f];
     128         [ +  + ]:      21424 :         if ((UUID_GAP_MASK >> i) & 1)
     129         [ +  - ]:       5356 :            result += '-';
     130                 :            :     }
     131                 :       1339 :     return result;
     132                 :            : }

Generated by: LCOV version 1.11