1/*
2 * Copyright (c) 2015-2016, Intel Corporation
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
6 *
7 * * Redistributions of source code must retain the above copyright notice,
8 * this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of Intel Corporation nor the names of its contributors
13 * may be used to endorse or promote products derived from this software
14 * without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 * POSSIBILITY OF SUCH DAMAGE.
27 */
28
29#include "database_util.h"
30
31#include "hs_common.h"
32
33#include <cassert>
34#include <cstdlib>
35#include <cstring>
36#include <fstream>
37#include <iostream>
38
39#if defined(HAVE_MMAP)
40#include <sys/mman.h> // for mmap
41#include <unistd.h> // for close
42#include <sys/fcntl.h>
43#include <sys/stat.h>
44#endif
45
46using namespace std;
47
48bool saveDatabase(const hs_database_t *db, const char *filename, bool verbose) {
49 assert(db);
50 assert(filename);
51
52 if (verbose) {
53 cout << "Saving database to: " << filename << endl;
54 }
55
56 char *bytes = nullptr;
57 size_t length = 0;
58 hs_error_t err = hs_serialize_database(db, &bytes, &length);
59 if (err != HS_SUCCESS) {
60 return false;
61 }
62
63 assert(bytes);
64 assert(length > 0);
65
66 ofstream out(filename, ios::binary);
67 out.write(bytes, length);
68 out.close();
69
70 ::free(bytes);
71
72 return true;
73}
74
75hs_database_t * loadDatabase(const char *filename, bool verbose) {
76 assert(filename);
77
78 if (verbose) {
79 cout << "Loading database from: " << filename << endl;
80 }
81
82 char *bytes = nullptr;
83
84#if defined(HAVE_MMAP)
85 // Use mmap to read the file
86 int fd = open(filename, O_RDONLY);
87 if (fd < 0) {
88 return nullptr;
89 }
90 struct stat st;
91 if (fstat(fd, &st) < 0) {
92 close(fd);
93 return nullptr;
94 }
95 size_t len = st.st_size;
96
97 bytes = (char *)mmap(nullptr, len, PROT_READ, MAP_SHARED, fd, 0);
98 if (bytes == MAP_FAILED) {
99 cout << "mmap failed" << endl;
100 close(fd);
101 return nullptr;
102 }
103#else
104 // Fall back on stream IO
105 ifstream is;
106 is.open(filename, ios::in | ios::binary);
107 if (!is.is_open()) {
108 return nullptr;
109 }
110 is.seekg(0, ios::end);
111 size_t len = is.tellg();
112 if (verbose) {
113 cout << "Reading " << len << " bytes" << endl;
114 }
115 is.seekg(0, ios::beg);
116 bytes = new char[len];
117 is.read(bytes, len);
118 is.close();
119#endif
120
121 assert(bytes);
122
123 if (verbose) {
124 char *info = nullptr;
125 hs_error_t err = hs_serialized_database_info(bytes, len, &info);
126 if (err) {
127 cout << "Unable to decode serialized database info: " << err
128 << endl;
129 } else if (info) {
130 cout << "Serialized database info: " << info << endl;
131 std::free(info);
132 } else {
133 cout << "Unable to decode serialized database info." << endl;
134 }
135 }
136
137 hs_database_t *db = nullptr;
138 hs_error_t err = hs_deserialize_database(bytes, len, &db);
139
140#if defined(HAVE_MMAP)
141 munmap(bytes, len);
142 close(fd);
143#else
144 delete [] bytes;
145#endif
146
147 if (err != HS_SUCCESS) {
148 cout << "hs_deserialize_database call failed: " << err << endl;
149 return nullptr;
150 }
151
152 assert(db);
153
154 return db;
155}
156