Coverage Report

Created: 2026-09-03 06:39

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/gdbm/src/gdbmerrno.c
Line
Count
Source
1
/* gdbmerrno.c - convert gdbm errors into English. */
2
3
/* This file is part of GDBM, the GNU data base manager.
4
   Copyright (C) 1993-2025 Free Software Foundation, Inc.
5
6
   GDBM is free software; you can redistribute it and/or modify
7
   it under the terms of the GNU General Public License as published by
8
   the Free Software Foundation; either version 3, or (at your option)
9
   any later version.
10
11
   GDBM is distributed in the hope that it will be useful,
12
   but WITHOUT ANY WARRANTY; without even the implied warranty of
13
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
   GNU General Public License for more details.
15
16
   You should have received a copy of the GNU General Public License
17
   along with GDBM. If not, see <http://www.gnu.org/licenses/>.   */
18
19
/* Include system configuration before all else. */
20
#include "autoconf.h"
21
22
#include "gdbmdefs.h"
23
24
/* The dbm error number is placed in the variable GDBM_ERRNO. */
25
static GDBM_THREAD_LOCAL gdbm_error gdbm_errno_storage = GDBM_NO_ERROR;
26
27
int *
28
gdbm_errno_location (void)
29
11.6M
{
30
11.6M
  return &gdbm_errno_storage;
31
11.6M
}
32
33
/* Store error code EC in the database structure DBF and in the
34
   global variable gdbm_error. 
35
*/
36
void
37
gdbm_set_errno (GDBM_FILE dbf, gdbm_error ec, int fatal)
38
11.3M
{
39
11.3M
  if (dbf)
40
11.3M
    {
41
11.3M
      free (dbf->last_errstr);
42
11.3M
      dbf->last_errstr = NULL;
43
      
44
11.3M
      dbf->last_error = ec;
45
11.3M
      if (gdbm_syserr[ec])
46
898
  dbf->last_syserror = errno;
47
11.3M
      else
48
11.3M
  dbf->last_syserror = 0;
49
11.3M
      dbf->need_recovery = fatal;
50
11.3M
    }
51
11.3M
  gdbm_errno = ec;
52
11.3M
}
53
54
/* Retrieve last error code for the database DBF. */
55
gdbm_error
56
gdbm_last_errno (GDBM_FILE dbf)
57
3.27M
{
58
3.27M
  if (!dbf)
59
0
    {
60
0
      errno = EINVAL;
61
0
      return -1;
62
0
    }
63
3.27M
  return dbf->last_error;
64
3.27M
}
65
66
int
67
gdbm_last_syserr (GDBM_FILE dbf)
68
3.67k
{
69
3.67k
  if (!dbf)
70
0
    {
71
0
      errno = EINVAL;
72
0
      return -1;
73
0
    }
74
3.67k
  return dbf->last_syserror;
75
3.67k
}
76
77
int
78
gdbm_needs_recovery (GDBM_FILE dbf)
79
0
{
80
0
  if (!dbf)
81
0
    return 0;
82
0
  return dbf->need_recovery;
83
0
}
84
85
/* Clear error state for the database DBF. */
86
void
87
gdbm_clear_error (GDBM_FILE dbf)
88
14.5k
{
89
14.5k
  if (dbf)
90
14.5k
    {
91
14.5k
      dbf->last_error = GDBM_NO_ERROR;
92
14.5k
      dbf->last_syserror = 0;
93
14.5k
      free (dbf->last_errstr);
94
14.5k
      dbf->last_errstr = NULL;
95
14.5k
    }
96
14.5k
}
97
98
/* this is not static so that applications may access the array if they
99
   like. */
100
101
const char * const gdbm_errlist[_GDBM_MAX_ERRNO+1] = {
102
  [GDBM_NO_ERROR]               = N_("No error"),
103
  [GDBM_MALLOC_ERROR]           = N_("Malloc error"),
104
  [GDBM_BLOCK_SIZE_ERROR]       = N_("Block size error"),
105
  [GDBM_FILE_OPEN_ERROR]        = N_("File open error"),
106
  [GDBM_FILE_WRITE_ERROR]       = N_("File write error"),
107
  [GDBM_FILE_SEEK_ERROR]        = N_("File seek error"),
108
  [GDBM_FILE_READ_ERROR]        = N_("File read error"),
109
  [GDBM_BAD_MAGIC_NUMBER]       = N_("Bad magic number"),
110
  [GDBM_EMPTY_DATABASE]         = N_("Empty database"),
111
  [GDBM_CANT_BE_READER]         = N_("Can't be reader"),
112
  [GDBM_CANT_BE_WRITER]         = N_("Can't be writer"),
113
  [GDBM_READER_CANT_DELETE]     = N_("Reader can't delete"),
114
  [GDBM_READER_CANT_STORE]      = N_("Reader can't store"),
115
  [GDBM_READER_CANT_REORGANIZE] = N_("Reader can't reorganize"),
116
  [GDBM_UNKNOWN_ERROR]          = N_("Should not happen: unused error code"),
117
  [GDBM_ITEM_NOT_FOUND]         = N_("Item not found"),
118
  [GDBM_REORGANIZE_FAILED]      = N_("Reorganize failed"),
119
  [GDBM_CANNOT_REPLACE]         = N_("Cannot replace"),
120
  [GDBM_MALFORMED_DATA]         = N_("Malformed data"),
121
  [GDBM_OPT_ALREADY_SET]        = N_("Option already set"),
122
  [GDBM_OPT_BADVAL]             = N_("Bad option value"),
123
  [GDBM_BYTE_SWAPPED]           = N_("Byte-swapped file"),
124
  [GDBM_BAD_FILE_OFFSET]        = N_("File header assumes wrong off_t size"),
125
  [GDBM_BAD_OPEN_FLAGS]         = N_("Bad file flags"),
126
  [GDBM_FILE_STAT_ERROR]        = N_("Cannot stat file"),
127
  [GDBM_FILE_EOF]               = N_("Unexpected end of file"),
128
  [GDBM_NO_DBNAME]              = N_("Database name not given"),
129
  [GDBM_ERR_FILE_OWNER]         = N_("Failed to restore file owner"),
130
  [GDBM_ERR_FILE_MODE]          = N_("Failed to restore file mode"),
131
  [GDBM_NEED_RECOVERY]          = N_("Database needs recovery"),
132
  [GDBM_BACKUP_FAILED]          = N_("Failed to create backup copy"),
133
  [GDBM_DIR_OVERFLOW]           = N_("Bucket directory overflow"),
134
  [GDBM_BAD_BUCKET]             = N_("Malformed bucket header"),
135
  [GDBM_BAD_HEADER]             = N_("Malformed database file header"),
136
  /* TRANSLATORS: avail_block is a field name. Don't translate it. */
137
  [GDBM_BAD_AVAIL]              = N_("Malformed avail_block"),
138
  [GDBM_BAD_HASH_TABLE]         = N_("Malformed hash table"),
139
  [GDBM_BAD_DIR_ENTRY]          = N_("Invalid directory entry"),
140
  [GDBM_FILE_CLOSE_ERROR]       = N_("Error closing file"),
141
  [GDBM_FILE_SYNC_ERROR]        = N_("Error synchronizing file"),
142
  [GDBM_FILE_TRUNCATE_ERROR]    = N_("Error truncating file"),
143
  [GDBM_BUCKET_CACHE_CORRUPTED] = N_("Bucket cache corrupted"),
144
  [GDBM_BAD_HASH_ENTRY]         = N_("Malformed bucket hash entry"),
145
  [GDBM_ERR_SNAPSHOT_CLONE]     = N_("Reflink failed"),
146
  [GDBM_ERR_REALPATH]           = N_("Failed to resolve real path name"),
147
  [GDBM_ERR_USAGE]              = N_("Function usage error"),
148
};
149
150
const char *
151
gdbm_strerror (gdbm_error error)
152
144k
{
153
144k
  if (error < _GDBM_MIN_ERRNO || error > _GDBM_MAX_ERRNO)
154
0
    error = GDBM_UNKNOWN_ERROR;
155
144k
  return gettext (gdbm_errlist[error]);
156
144k
}
157
158
char const *
159
gdbm_db_strerror (GDBM_FILE dbf)
160
143k
{
161
143k
  if (!dbf->last_errstr)
162
143k
    {
163
143k
      char const *errstr = gdbm_strerror (dbf->last_error);
164
165
143k
      if (dbf->last_syserror)
166
268
  {
167
268
    char const *syserrstr = strerror (dbf->last_syserror);
168
268
    size_t len = strlen (errstr) + strlen (syserrstr) + 2;
169
268
    dbf->last_errstr = malloc (len + 1);
170
268
    if (!dbf->last_errstr)
171
0
      return errstr;
172
173
268
    strcpy (dbf->last_errstr, errstr);
174
268
    strcat (dbf->last_errstr, ": ");
175
268
    strcat (dbf->last_errstr, syserrstr);
176
268
  }
177
143k
      else
178
143k
  return errstr;
179
143k
    }
180
268
  return dbf->last_errstr;
181
143k
}
182
183
int const gdbm_syserr[_GDBM_MAX_ERRNO+1] = {
184
  [GDBM_FILE_OPEN_ERROR]        = 1,
185
  [GDBM_FILE_WRITE_ERROR]       = 1,
186
  [GDBM_FILE_SEEK_ERROR]        = 1,
187
  [GDBM_FILE_READ_ERROR]        = 1,
188
  [GDBM_FILE_STAT_ERROR]        = 1,
189
  [GDBM_BACKUP_FAILED]          = 1,
190
  [GDBM_FILE_CLOSE_ERROR]       = 1,
191
  [GDBM_FILE_SYNC_ERROR]        = 1,
192
  [GDBM_FILE_TRUNCATE_ERROR]    = 1,
193
  [GDBM_ERR_SNAPSHOT_CLONE]     = 1,
194
  [GDBM_ERR_REALPATH]           = 1,
195
  [GDBM_ERR_USAGE]              = 1
196
};
197
198
/* Returns true if system errno value is meaningful for GDBM error
199
   code N. */
200
int
201
gdbm_check_syserr (gdbm_error n)
202
963
{
203
963
  if (n >= _GDBM_MIN_ERRNO && n <= _GDBM_MAX_ERRNO)
204
963
    return gdbm_syserr[n];
205
0
  return 0;
206
963
}