2 * Copyright (C) 2010-2011 Red Hat Inc.
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
41 #include "ignore-value.h"
44 #include "guestfs-internal.h"
46 #if defined(HAVE_PCRE) && defined(HAVE_HIVEX) && defined(DB_DUMP)
48 static unsigned char *convert_hex_to_binary (guestfs_h *g, const char *hex, size_t hexlen, size_t *binlen_rtn);
50 /* This helper function is specialized to just reading the hash-format
51 * output from db_dump/db4_dump. It's just enough to support the RPM
52 * database format. Note that the filename must not contain any shell
53 * characters (this is guaranteed by the caller).
56 guestfs___read_db_dump (guestfs_h *g,
57 const char *dumpfile, void *opaque,
58 guestfs___db_dump_callback callback)
60 #define cmd_len (strlen (dumpfile) + 64)
66 unsigned char *key = NULL, *value = NULL;
67 size_t keylen, valuelen;
70 snprintf (cmd, cmd_len, DB_DUMP " -k '%s'", dumpfile);
72 debug (g, "read_db_dump command: %s", cmd);
74 pp = popen (cmd, "r");
76 perrorf (g, "popen: %s", cmd);
80 /* Ignore everything to end-of-header marker. */
81 while ((linelen = getline (&line, &len, pp)) != -1) {
82 if (STRPREFIX (line, "HEADER=END"))
87 error (g, _("unexpected end of output from db_dump command before end of header"));
91 /* Now read the key, value pairs. They are prefixed with a space and
92 * printed as hex strings, so convert those strings to binary. Pass
93 * the strings up to the callback function.
95 while ((linelen = getline (&line, &len, pp)) != -1) {
96 if (STRPREFIX (line, "DATA=END"))
99 if (linelen < 1 || line[0] != ' ') {
100 error (g, _("unexpected line from db_dump command, no space prefix"));
104 if ((key = convert_hex_to_binary (g, &line[1], linelen-1,
108 if ((linelen = getline (&line, &len, pp)) == -1)
111 if (linelen < 1 || line[0] != ' ') {
112 error (g, _("unexpected line from db_dump command, no space prefix"));
116 if ((value = convert_hex_to_binary (g, &line[1], linelen-1,
120 if (callback (g, key, keylen, value, valuelen, opaque) == -1)
129 error (g, _("unexpected end of output from db_dump command before end of data"));
133 /* Catch errors from the db_dump command. */
134 if (pclose (pp) != 0) {
135 perrorf (g, "pclose: %s", cmd);
155 convert_hex_octet (const char *h)
161 r = (h[0] - 'a' + 10) << 4;
164 r = (h[0] - 'A' + 10) << 4;
167 r = (h[0] - '0') << 4;
175 r |= h[1] - 'a' + 10;
178 r |= h[1] - 'A' + 10;
190 static unsigned char *
191 convert_hex_to_binary (guestfs_h *g, const char *hex, size_t hexlen,
199 if (hexlen > 0 && hex[hexlen-1] == '\n')
203 bin = safe_malloc (g, binlen);
205 for (i = o = 0; i+1 < hexlen && o < binlen; i += 2, ++o) {
206 b = convert_hex_octet (&hex[i]);
210 error (g, _("unexpected non-hex digits in output of db_dump command"));
216 *binlen_rtn = binlen;
220 #endif /* defined(HAVE_PCRE) && defined(HAVE_HIVEX) && defined(DB_DUMP) */