Coverage Report

Created: 2026-08-13 06:08

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/gdbm/src/gdbmdump.c
Line
Count
Source
1
/* This file is part of GDBM, the GNU data base manager.
2
   Copyright (C) 2011-2025 Free Software Foundation, Inc.
3
4
   GDBM is free software; you can redistribute it and/or modify
5
   it under the terms of the GNU General Public License as published by
6
   the Free Software Foundation; either version 3, or (at your option)
7
   any later version.
8
9
   GDBM 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
12
   GNU General Public License for more details.
13
14
   You should have received a copy of the GNU General Public License
15
   along with GDBM. If not, see <http://www.gnu.org/licenses/>.   */
16
17
# include "autoconf.h"
18
# include "gdbmdefs.h"
19
# include "gdbm.h"
20
# include <pwd.h>
21
# include <grp.h>
22
# include <time.h>
23
24
static int
25
print_datum (datum const *dat, unsigned char **bufptr,
26
       size_t *bufsize, FILE *fp)
27
0
{
28
0
  int rc;
29
0
  size_t len;
30
0
  unsigned char *p;
31
  
32
0
  fprintf (fp, "#:len=%lu\n", (unsigned long) dat->dsize);
33
0
  rc = _gdbm_base64_encode ((unsigned char*) dat->dptr, dat->dsize,
34
0
          bufptr, bufsize, &len);
35
0
  if (rc)
36
0
    return rc;
37
  
38
0
  p = *bufptr;
39
0
  if (len == 0)
40
0
    fputs ("#\n", fp);
41
0
  else
42
0
    while (len)
43
0
      {
44
0
  size_t n = len;
45
0
  if (n > _GDBM_MAX_DUMP_LINE_LEN)
46
0
    n = _GDBM_MAX_DUMP_LINE_LEN;
47
0
  if (fwrite (p, n, 1, fp) != 1)
48
0
    return GDBM_FILE_WRITE_ERROR;
49
0
  fputc ('\n', fp);
50
0
  len -= n;
51
0
  p += n;
52
0
      }
53
0
  return 0;
54
0
}
55
56
int
57
_gdbm_dump_ascii (GDBM_FILE dbf, FILE *fp)
58
0
{
59
0
  time_t t;
60
0
  int fd;
61
0
  struct stat st;
62
0
  struct passwd *pw;
63
0
  struct group *gr;
64
0
  datum key;
65
0
  size_t count = 0;
66
0
  unsigned char *buffer = NULL;
67
0
  size_t bufsize = 0;
68
0
  int rc = 0;
69
70
0
  fd = gdbm_fdesc (dbf);
71
0
  if (fstat (fd, &st))
72
0
    return GDBM_FILE_STAT_ERROR;
73
74
  /* Print header */
75
0
  time (&t);
76
0
  fprintf (fp, "# GDBM dump file created by %s on %s",
77
0
     gdbm_version, ctime (&t));
78
0
  fprintf (fp, "#:version=1.2\n");
79
80
0
  fprintf (fp, "#:file=%s\n", dbf->name);
81
0
  fprintf (fp, "#:uid=%lu,", (unsigned long) st.st_uid);
82
0
  pw = getpwuid (st.st_uid);
83
0
  if (pw)
84
0
    fprintf (fp, "user=%s,", pw->pw_name);
85
0
  fprintf (fp, "gid=%lu,", (unsigned long) st.st_gid);
86
0
  gr = getgrgid (st.st_gid);
87
0
  if (gr)
88
0
    fprintf (fp, "group=%s,", gr->gr_name);
89
0
  fprintf (fp, "mode=%03o\n", st.st_mode & 0777);
90
0
  fprintf (fp, "#:format=%s\n", dbf->xheader ? "numsync" : "standard");
91
0
  fprintf (fp, "# End of header\n");
92
  
93
0
  key = gdbm_firstkey (dbf);
94
95
0
  while (key.dptr)
96
0
    {
97
0
      datum nextkey;
98
0
      datum data = gdbm_fetch (dbf, key);
99
0
      if (data.dptr)
100
0
  {
101
0
    if ((rc = print_datum (&key, &buffer, &bufsize, fp)) ||
102
0
        (rc = print_datum (&data, &buffer, &bufsize, fp)))
103
0
      {
104
0
        free (key.dptr);
105
0
        free (data.dptr);
106
0
        GDBM_SET_ERRNO (dbf, rc, FALSE);
107
0
        break;
108
0
      }
109
0
  }
110
0
      else
111
0
  break;
112
0
      nextkey = gdbm_nextkey (dbf, key);
113
0
      free (key.dptr);
114
0
      free (data.dptr);
115
0
      key = nextkey;
116
0
      count++;
117
0
    }
118
119
0
  fprintf (fp, "#:count=%lu\n", (unsigned long) count);
120
0
  fprintf (fp, "# End of data\n");
121
  
122
0
  if (rc == 0)
123
0
    {
124
0
      rc = gdbm_last_errno (dbf);
125
0
      if (rc == GDBM_ITEM_NOT_FOUND)
126
0
  {
127
0
    gdbm_clear_error (dbf);
128
0
    gdbm_errno = GDBM_NO_ERROR;
129
0
    rc = 0;
130
0
  }
131
0
    }
132
0
  free (buffer);
133
134
0
  return rc ? -1 : 0;
135
0
}
136
137
int
138
gdbm_dump_to_file (GDBM_FILE dbf, FILE *fp, int format)
139
0
{
140
0
  int rc;
141
  
142
  /* Return immediately if the database needs recovery */  
143
0
  GDBM_ASSERT_CONSISTENCY (dbf, -1);
144
  
145
0
  switch (format)
146
0
    {
147
0
    case GDBM_DUMP_FMT_BINARY:
148
0
      rc = gdbm_export_to_file (dbf, fp) == -1;
149
0
      break;
150
151
0
    case GDBM_DUMP_FMT_ASCII:
152
0
      rc = _gdbm_dump_ascii (dbf, fp);
153
0
      break;
154
155
0
    default:
156
0
      GDBM_SET_ERRNO (NULL, GDBM_BAD_OPEN_FLAGS, FALSE);
157
0
      return -1;
158
0
    }
159
  
160
0
  if (rc == 0 && ferror (fp))
161
0
    {
162
0
      GDBM_SET_ERRNO (NULL, GDBM_FILE_WRITE_ERROR, FALSE);
163
0
      rc = -1;
164
0
    }
165
166
0
  return rc;
167
0
}
168
169
int
170
gdbm_dump (GDBM_FILE dbf, const char *filename, int fmt, int open_flags,
171
     int mode)
172
0
{
173
0
  int nfd, rc;
174
0
  FILE *fp;
175
  
176
  /* Return immediately if the database needs recovery */  
177
0
  GDBM_ASSERT_CONSISTENCY (dbf, -1);
178
  
179
  /* Only support GDBM_WCREAT or GDBM_NEWDB */
180
0
  switch (open_flags)
181
0
    {
182
0
    case GDBM_WRCREAT:
183
0
      nfd = open (filename, O_WRONLY | O_CREAT | O_EXCL, mode);
184
0
      if (nfd == -1)
185
0
  {
186
0
    GDBM_SET_ERRNO (NULL, GDBM_FILE_OPEN_ERROR, FALSE);
187
0
    return -1;
188
0
  }
189
0
      break;
190
0
    case GDBM_NEWDB:
191
0
      nfd = open (filename, O_WRONLY | O_CREAT | O_TRUNC, mode);
192
0
      if (nfd == -1)
193
0
  {
194
0
    GDBM_SET_ERRNO (NULL, GDBM_FILE_OPEN_ERROR, FALSE);
195
0
    return -1;
196
0
  }
197
0
      break;
198
0
    default:
199
0
      GDBM_SET_ERRNO (NULL, GDBM_BAD_OPEN_FLAGS, FALSE);
200
0
      return -1;
201
0
  }
202
203
0
  fp = fdopen (nfd, "w");
204
0
  if (!fp)
205
0
    {
206
0
      close (nfd);
207
0
      GDBM_SET_ERRNO (NULL, GDBM_FILE_OPEN_ERROR, FALSE);
208
0
      return -1;
209
0
    }
210
0
  rc = gdbm_dump_to_file (dbf, fp, fmt);
211
0
  fclose (fp);
212
0
  return rc;
213
0
}
214
215
216