Coverage Report

Created: 2025-11-24 06:58

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/gdbm/src/gdbmload.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 <sys/types.h>
21
# include <pwd.h>
22
# include <grp.h>
23
24
struct datbuf
25
{
26
  unsigned char *buffer;
27
  size_t size;
28
};
29
30
struct dump_file
31
{
32
  FILE *fp;
33
  size_t line;
34
35
  char *linebuf;
36
  size_t lbsize;
37
  size_t lblevel;
38
39
  char *buffer;
40
  size_t bufsize;
41
  size_t buflevel;
42
43
  size_t parmc;
44
45
  struct datbuf data[2];
46
  char *header;
47
};
48
49
static void
50
dump_file_free (struct dump_file *file)
51
0
{
52
0
  free (file->linebuf);
53
0
  free (file->buffer);
54
0
  free (file->data[0].buffer);
55
0
  free (file->data[1].buffer);
56
0
  free (file->header);
57
0
}
58
59
static const char *
60
getparm (const char *buf, const char *parm)
61
0
{
62
0
  if (!buf)
63
0
    return NULL;
64
0
  while (*buf)
65
0
    {
66
0
      const char *p;
67
0
      for (p = parm; *p == *buf; p++, buf++)
68
0
  ;
69
0
      if (*p == 0 && *buf == '=')
70
0
  return buf + 1;
71
0
      buf += strlen (buf) + 1;
72
0
    }
73
0
  return NULL;
74
0
}
75
76
static int
77
get_dump_line (struct dump_file *file, size_t *nread)
78
0
{
79
0
  char buf[80];
80
81
0
  if (file->lblevel == 0)
82
0
    {
83
0
      while (fgets (buf, sizeof buf, file->fp))
84
0
  {
85
0
    size_t n = strlen (buf);
86
87
0
    if (n > 0 && buf[n-1] == '\n')
88
0
      {
89
0
        file->line++;
90
0
        --n;
91
0
      }
92
93
0
    if (n + 1 + file->lblevel > file->lbsize)
94
0
      {
95
0
        size_t s = ((file->lblevel + n + _GDBM_MAX_DUMP_LINE_LEN)
96
0
        / _GDBM_MAX_DUMP_LINE_LEN)
97
0
        * _GDBM_MAX_DUMP_LINE_LEN;
98
0
        char *newp = realloc (file->linebuf, s);
99
0
        if (!newp)
100
0
    return GDBM_MALLOC_ERROR;
101
0
        file->linebuf = newp;
102
0
        file->lbsize = s;
103
0
      }
104
105
0
    memcpy (file->linebuf + file->lblevel, buf, n);
106
0
    file->lblevel += n;
107
0
    if (buf[n])
108
0
      {
109
0
        file->linebuf[file->lblevel] = 0;
110
0
        break;
111
0
      }
112
0
  }
113
0
    }
114
0
  if (ferror (file->fp))
115
0
    return GDBM_FILE_READ_ERROR;
116
0
  if ((*nread = file->lblevel) == 0)
117
0
    return GDBM_FILE_EOF;
118
0
  return GDBM_NO_ERROR;
119
0
}
120
121
static int
122
get_data (struct dump_file *file)
123
0
{
124
0
  size_t n;
125
0
  int rc;
126
127
0
  file->buflevel = 0;
128
0
  file->parmc = 0;
129
130
0
  while ((rc = get_dump_line (file, &n)) == GDBM_NO_ERROR &&
131
0
   file->linebuf[0] == '#')
132
0
    ;
133
0
  if (rc != GDBM_NO_ERROR)
134
0
    return rc;
135
136
0
  do
137
0
    {
138
0
      if (file->linebuf[0] == '#')
139
0
  return GDBM_NO_ERROR;
140
0
      if (n + file->buflevel > file->bufsize)
141
0
  {
142
0
    size_t s = ((file->buflevel + n + _GDBM_MAX_DUMP_LINE_LEN - 1)
143
0
          / _GDBM_MAX_DUMP_LINE_LEN)
144
0
          * _GDBM_MAX_DUMP_LINE_LEN;
145
0
    char *newp = realloc (file->buffer, s);
146
0
    if (!newp)
147
0
      return GDBM_MALLOC_ERROR;
148
0
    file->buffer = newp;
149
0
    file->bufsize = s;
150
0
  }
151
0
      memcpy (file->buffer + file->buflevel, file->linebuf, n);
152
0
      file->buflevel += n;
153
0
      file->lblevel = 0;
154
0
    }
155
0
  while ((rc = get_dump_line (file, &n)) == GDBM_NO_ERROR);
156
157
0
  if (rc == GDBM_FILE_EOF && file->buflevel > 0)
158
0
    rc = GDBM_NO_ERROR;
159
0
  return rc;
160
0
}
161
162
static int
163
get_parms (struct dump_file *file)
164
0
{
165
0
  size_t n;
166
0
  int rc;
167
0
  static char len_pfx[] = "len=";
168
0
  static size_t len_pfx_len = sizeof (len_pfx) - 1;
169
0
  static char count_pfx[] = "count=";
170
0
  static size_t count_pfx_len = sizeof (count_pfx) - 1;
171
0
  int len_seen = 0;
172
173
0
  file->buflevel = 0;
174
0
  file->parmc = 0;
175
0
  while ((rc = get_dump_line (file, &n)) == GDBM_NO_ERROR)
176
0
    {
177
0
      char *p;
178
179
0
      p = file->linebuf;
180
0
      if (*p != '#')
181
0
  break;
182
0
      if (*++p != ':')
183
0
  {
184
0
    file->lblevel = 0;
185
0
    if (file->parmc)
186
0
      break;
187
0
    else
188
0
      continue;
189
0
  }
190
0
      if (--n == 0)
191
0
  {
192
0
    file->lblevel = 0;
193
0
    continue;
194
0
  }
195
196
0
      if (n + 1 + file->buflevel > file->bufsize)
197
0
  {
198
0
    size_t s = ((file->buflevel + n + _GDBM_MAX_DUMP_LINE_LEN)
199
0
          / _GDBM_MAX_DUMP_LINE_LEN)
200
0
          * _GDBM_MAX_DUMP_LINE_LEN;
201
0
    char *newp = realloc (file->buffer, s);
202
0
    if (!newp)
203
0
      return GDBM_MALLOC_ERROR;
204
0
    file->buffer = newp;
205
0
    file->bufsize = s;
206
0
  }
207
208
0
      while (*p)
209
0
  {
210
0
    p++;
211
0
    while (*p == ' ' || *p == '\t')
212
0
      p++;
213
0
    if (*p)
214
0
      {
215
        /*
216
         * Version 1.1 of ASCII dumps (produced by gdbm <= 1.26),
217
         * had no provisions for zero-length data, so that the
218
         * parameter "#:len=0" was followed immediately by next
219
         * parameter block.  Three cases can be distinguished:
220
         *
221
         *   1. Zero-length key
222
         *         #:len=0
223
         *         #:len=N
224
         *         [base64]
225
         *   2. Zero-length data:
226
         *         #:len=N
227
         *         #:len=0
228
         *         #:len=M
229
         *         ....
230
         *   3. Zero length data at the end of the file:
231
         *         #:len=N
232
         *         #:len=0
233
         *         #:count=M
234
         *
235
         * Additionally, version 1.18 didn't output "count" parameter
236
         * in the last case.
237
         *
238
         * The following conditional handles these cases:
239
         */
240
0
        if (strncmp (p, len_pfx, len_pfx_len) == 0)
241
0
    {
242
0
      if (len_seen)
243
0
        {
244
0
          if (p > file->linebuf + 2)
245
0
      {
246
0
        size_t len = strlen (p);
247
0
        memmove (file->linebuf + 2, p, len + 1);
248
0
        file->lblevel = len + 2;
249
0
      }
250
0
          goto end;
251
0
        }
252
0
      else
253
0
        len_seen = 1;
254
0
    }
255
0
        else if (len_seen && strncmp (p, count_pfx, count_pfx_len) == 0)
256
0
    goto end;
257
258
0
        while (*p && *p != '=')
259
0
    file->buffer[file->buflevel++] = *p++;
260
261
0
        if (*p == '=')
262
0
    {
263
0
      file->buffer[file->buflevel++] = *p++;
264
0
      if (*p == '"')
265
0
        {
266
0
          p++;
267
0
          while (*p && *p != '"')
268
0
      file->buffer[file->buflevel++] = *p++;
269
270
0
          if (*p == '"')
271
0
      p++;
272
0
        }
273
0
      else
274
0
        {
275
0
          while (!(*p == 0 || *p == ','))
276
0
      file->buffer[file->buflevel++] = *p++;
277
0
        }
278
0
      file->parmc++;
279
0
      file->buffer[file->buflevel++] = 0;
280
0
    }
281
0
        else
282
0
    return GDBM_MALFORMED_DATA;
283
0
      }
284
0
    else
285
0
      break;
286
0
  }
287
0
      file->lblevel = 0;
288
0
    }
289
0
 end:
290
0
  if (rc == GDBM_FILE_EOF && file->buflevel > 0)
291
0
    rc = GDBM_NO_ERROR;
292
0
  if (file->buffer)
293
0
    file->buffer[file->buflevel] = 0;
294
295
0
  return rc;
296
0
}
297
298
static int
299
get_num (const char *param, const char *name, size_t *retval)
300
0
{
301
0
  unsigned long n;
302
0
  const char *p = getparm (param, name);
303
0
  char *end;
304
305
0
  if (!p)
306
0
    return GDBM_ITEM_NOT_FOUND;
307
308
0
  errno = 0;
309
0
  n = strtoul (p, &end, 10);
310
0
  if (*end == 0 && errno == 0)
311
0
    {
312
0
      *retval = n;
313
0
      return 0;
314
0
    }
315
316
0
  return GDBM_MALFORMED_DATA;
317
0
}
318
319
static inline int
320
get_len (const char *param, size_t *plen)
321
0
{
322
0
  return get_num (param, "len", plen);
323
0
}
324
325
static int
326
read_record (struct dump_file *file, int n, datum *dat)
327
0
{
328
0
  int rc;
329
0
  size_t len, consumed_size, decoded_size;
330
331
0
  rc = get_parms (file);
332
0
  if (rc)
333
0
    return rc;
334
0
  if (file->parmc == 0)
335
0
    return GDBM_ITEM_NOT_FOUND;
336
337
0
  rc = get_len (file->buffer, &len);
338
0
  if (rc)
339
0
    return rc;
340
0
  dat->dsize = len; /* FIXME: data type mismatch */
341
0
  if (len > 0)
342
0
    {
343
0
      rc = get_data (file);
344
0
      if (rc)
345
0
  return rc;
346
347
0
      rc = _gdbm_base64_decode ((unsigned char *)file->buffer, file->buflevel,
348
0
        &file->data[n].buffer, &file->data[n].size,
349
0
        &consumed_size, &decoded_size);
350
0
      if (rc)
351
0
  return rc;
352
0
      if (consumed_size != file->buflevel || decoded_size != len)
353
0
  return GDBM_MALFORMED_DATA;
354
0
      dat->dptr = (void*) file->data[n].buffer;
355
0
    }
356
0
  else
357
0
    {
358
0
      dat->dptr = "";
359
0
    }
360
0
  return 0;
361
0
}
362
363
0
#define META_UID  0x01
364
0
#define META_GID  0x02
365
0
#define META_MODE 0x04
366
367
static int
368
_set_gdbm_meta_info (GDBM_FILE dbf, char *param, int meta_mask)
369
0
{
370
0
  unsigned long n;
371
0
  uid_t owner_uid;
372
0
  uid_t owner_gid;
373
0
  mode_t mode;
374
0
  int meta_flags = 0;
375
0
  const char *p;
376
0
  char *end;
377
378
0
  if (!(meta_mask & GDBM_META_MASK_OWNER))
379
0
    {
380
0
      p = getparm (param, "user");
381
0
      if (p)
382
0
  {
383
0
    struct passwd *pw = getpwnam (p);
384
0
    if (pw)
385
0
      {
386
0
        owner_uid = pw->pw_uid;
387
0
        meta_flags |= META_UID;
388
0
      }
389
0
  }
390
391
0
      if (!(meta_flags & META_UID) && (p = getparm (param, "uid")))
392
0
  {
393
0
    errno = 0;
394
0
    n = strtoul (p, &end, 10);
395
0
    if (*end == 0 && errno == 0)
396
0
      {
397
0
        owner_uid = n;
398
0
        meta_flags |= META_UID;
399
0
      }
400
0
  }
401
402
0
      p = getparm (param, "group");
403
0
      if (p)
404
0
  {
405
0
    struct group *gr = getgrnam (p);
406
0
    if (gr)
407
0
      {
408
0
        owner_gid = gr->gr_gid;
409
0
        meta_flags |= META_GID;
410
0
      }
411
0
  }
412
0
      if (!(meta_flags & META_GID) && (p = getparm (param, "gid")))
413
0
  {
414
0
    errno = 0;
415
0
    n = strtoul (p, &end, 10);
416
0
    if (*end == 0 && errno == 0)
417
0
      {
418
0
        owner_gid = n;
419
0
        meta_flags |= META_GID;
420
0
      }
421
0
  }
422
0
    }
423
424
0
  if (!(meta_mask & GDBM_META_MASK_MODE))
425
0
    {
426
0
      p = getparm (param, "mode");
427
0
      if (p)
428
0
  {
429
0
    errno = 0;
430
0
    n = strtoul (p, &end, 8);
431
0
    if (*end == 0 && errno == 0)
432
0
      {
433
0
        mode = n & 0777;
434
0
        meta_flags |= META_MODE;
435
0
      }
436
0
  }
437
0
    }
438
439
0
  if (meta_flags)
440
0
    {
441
0
      int fd = gdbm_fdesc (dbf);
442
0
      if (getuid () == 0 && (meta_flags & (META_UID|META_GID)))
443
0
  {
444
0
    if ((meta_flags & (META_UID|META_GID)) != (META_UID|META_GID))
445
0
      {
446
0
        struct stat st;
447
0
        if (fstat (fd, &st))
448
0
    {
449
0
      GDBM_SET_ERRNO (dbf, GDBM_FILE_STAT_ERROR, FALSE);
450
0
      return 1;
451
0
    }
452
0
        if (!(meta_flags & META_UID))
453
0
    owner_uid = st.st_uid;
454
0
        if (!(meta_flags & META_GID))
455
0
    owner_gid = st.st_gid;
456
0
      }
457
0
    if (fchown (fd, owner_uid, owner_gid))
458
0
      {
459
0
        GDBM_SET_ERRNO (dbf, GDBM_ERR_FILE_OWNER, FALSE);
460
0
        return 1;
461
0
      }
462
0
  }
463
0
      if ((meta_flags & META_MODE) && fchmod (fd, mode))
464
0
  {
465
0
    GDBM_SET_ERRNO (dbf, GDBM_ERR_FILE_OWNER, FALSE);
466
0
    return 1;
467
0
  }
468
0
    }
469
0
  return 0;
470
0
}
471
472
int
473
_gdbm_str2fmt (char const *str)
474
6.74k
{
475
6.74k
  if (strcmp (str, "numsync") == 0)
476
0
    return GDBM_NUMSYNC;
477
6.74k
  if (strcmp (str, "standard") == 0)
478
6.74k
    return 0;
479
0
  return -1;
480
6.74k
}
481
482
static int
483
_gdbm_load_file (struct dump_file *file, GDBM_FILE dbf, GDBM_FILE *ofp,
484
     int mode, int replace, int meta_mask)
485
0
{
486
0
  int rc;
487
0
  GDBM_FILE tmp = NULL;
488
0
  int format = 0;
489
0
  const char *p;
490
0
  size_t count = 0;
491
492
0
  rc = get_parms (file);
493
0
  if (rc)
494
0
    return rc;
495
496
0
  if (file->parmc)
497
0
    {
498
0
      file->header = file->buffer;
499
0
      file->buffer = NULL;
500
0
      file->bufsize = file->buflevel = 0;
501
0
    }
502
0
  else
503
0
    return GDBM_MALFORMED_DATA;
504
505
0
  if ((p = getparm (file->header, "format")) != NULL)
506
0
    {
507
0
      int n = _gdbm_str2fmt (p);
508
0
      if (n != -1)
509
0
  format = n;
510
      /* FIXME: other values silently ignored */
511
0
    }
512
513
0
  if (!dbf)
514
0
    {
515
0
      const char *filename = getparm (file->header, "file");
516
517
0
      if (!filename)
518
0
  return GDBM_NO_DBNAME;
519
520
0
      tmp = gdbm_open (filename, 0, mode | format, 0600, NULL);
521
0
      if (!tmp)
522
0
  return gdbm_errno;
523
0
      dbf = tmp;
524
0
    }
525
526
0
  if (format)
527
0
    {
528
      /*
529
       * If the database is already in the requested format, the call to
530
       * gdbm_convert will return 0 immediately.
531
       */
532
0
      if (gdbm_convert (dbf, format))
533
0
  {
534
0
    rc = gdbm_errno;
535
0
    if (tmp)
536
0
      gdbm_close (tmp);
537
0
    return rc;
538
0
  }
539
0
    }
540
541
0
  while (1)
542
0
    {
543
0
      datum key, content;
544
0
      rc = read_record (file, 0, &key);
545
0
      if (rc)
546
0
  {
547
0
    if (rc == GDBM_ITEM_NOT_FOUND)
548
0
      {
549
0
        size_t n;
550
551
0
        if (feof (file->fp))
552
    /* Dumps created by version 1.18 lacked final parameter block.
553
     */
554
0
    rc = GDBM_NO_ERROR;
555
0
        else if (get_num (file->buffer, "count", &n) == 0 && n == count)
556
0
    rc = GDBM_NO_ERROR;
557
0
        else
558
0
    rc = GDBM_MALFORMED_DATA;
559
0
      }
560
0
    break;
561
0
  }
562
563
0
      rc = read_record (file, 1, &content);
564
0
      if (rc)
565
0
  break;
566
567
0
      if (gdbm_store (dbf, key, content, replace))
568
0
  {
569
0
    rc = gdbm_errno;
570
0
    break;
571
0
  }
572
0
      count++;
573
0
    }
574
575
0
  if (rc == 0)
576
0
    {
577
0
      rc = _set_gdbm_meta_info (dbf, file->header, meta_mask);
578
0
      *ofp = dbf;
579
0
    }
580
0
  else if (tmp)
581
0
    gdbm_close (tmp);
582
583
0
  return rc;
584
0
}
585
586
static int
587
read_bdb_header (struct dump_file *file)
588
0
{
589
0
  char buf[256];
590
591
0
  file->line = 1;
592
0
  if (!fgets (buf, sizeof (buf), file->fp))
593
0
    return -1;
594
0
  if (strcmp (buf, "VERSION=3\n"))
595
0
    return -1;
596
0
  while (fgets (buf, sizeof (buf), file->fp))
597
0
    {
598
0
      ++file->line;
599
0
      if (strcmp (buf, "HEADER=END\n") == 0)
600
0
  return 0;
601
0
    }
602
0
  return -1;
603
0
}
604
605
static int
606
c2x (int c)
607
0
{
608
0
  static char xdig[] = "0123456789abcdef";
609
0
  char *p = strchr (xdig, c);
610
0
  if (!p)
611
0
    return -1;
612
0
  return p - xdig;
613
0
}
614
615
0
#define DINCR 128
616
617
static int
618
xdatum_read (FILE *fp, datum *d, size_t *pdmax)
619
0
{
620
0
  int c;
621
0
  size_t dmax = *pdmax;
622
623
0
  d->dsize = 0;
624
0
  while ((c = fgetc (fp)) != EOF && c != '\n')
625
0
    {
626
0
      int t, n;
627
628
0
      t = c2x (c);
629
0
      if (t == -1)
630
0
  return EOF;
631
0
      t <<= 4;
632
633
0
      if ((c = fgetc (fp)) == EOF)
634
0
  break;
635
636
0
      n = c2x (c);
637
0
      if (n == -1)
638
0
  return EOF;
639
0
      t += n;
640
641
0
      if (d->dsize == dmax)
642
0
  {
643
0
    char *np = realloc (d->dptr, dmax + DINCR);
644
0
    if (!np)
645
0
      return GDBM_MALLOC_ERROR;
646
0
    d->dptr = np;
647
0
    dmax += DINCR;
648
0
  }
649
0
      d->dptr[d->dsize++] = t;
650
0
    }
651
0
  *pdmax = dmax;
652
0
  if (c == '\n')
653
0
    return 0;
654
0
  return c;
655
0
}
656
657
static int
658
gdbm_load_bdb_dump (struct dump_file *file, GDBM_FILE dbf, int replace)
659
0
{
660
0
  datum xd[2];
661
0
  size_t xs[2];
662
0
  int rc, c;
663
0
  int i;
664
665
0
  if (read_bdb_header (file))
666
0
    return -1;
667
0
  memset (&xd, 0, sizeof (xd));
668
0
  xs[0] = xs[1] = 0;
669
0
  i = 0;
670
0
  rc = 0;
671
0
  while ((c = fgetc (file->fp)) == ' ')
672
0
    {
673
0
      rc = xdatum_read (file->fp, &xd[i], &xs[i]);
674
0
      if (rc)
675
0
  break;
676
0
      ++file->line;
677
678
0
      if (i == 1)
679
0
  {
680
0
    if (gdbm_store (dbf, xd[0], xd[1], replace))
681
0
      return gdbm_errno;
682
0
  }
683
0
      i = !i;
684
0
    }
685
  /* FIXME: Read "DATA=END" */
686
0
  free (xd[0].dptr);
687
0
  free (xd[1].dptr);
688
0
  if (rc == 0 && i)
689
0
    rc = EOF;
690
691
0
  return rc;
692
0
}
693
694
int
695
gdbm_load_from_file_ext (GDBM_FILE *pdbf, FILE *fp,
696
       int mode, int replace,
697
       int meta_mask,
698
       unsigned long *line)
699
0
{
700
0
  struct dump_file df;
701
0
  int rc;
702
703
0
  if (!pdbf || !fp || (mode & GDBM_OPENMASK) == GDBM_READER)
704
0
    {
705
0
      GDBM_SET_ERRNO (NULL, GDBM_ERR_USAGE, FALSE);
706
0
      return -1;
707
0
    }
708
709
  /* Guess input file format */
710
0
  rc = fgetc (fp);
711
0
  ungetc (rc, fp);
712
0
  if (rc == '!')
713
0
    {
714
0
      if (line)
715
0
  *line = 0;
716
0
      if (!*pdbf)
717
0
  {
718
0
    GDBM_SET_ERRNO (NULL, GDBM_NO_DBNAME, FALSE);
719
0
    return -1;
720
0
  }
721
0
      if (gdbm_import_from_file (*pdbf, fp, replace) == -1)
722
0
  return -1;
723
0
      return 0;
724
0
    }
725
726
0
  memset (&df, 0, sizeof df);
727
0
  df.fp = fp;
728
729
0
  if (rc == 'V')
730
0
    {
731
0
      if (!*pdbf)
732
0
  {
733
0
    GDBM_SET_ERRNO (NULL, GDBM_NO_DBNAME, FALSE);
734
0
    return -1;
735
0
  }
736
0
      rc = gdbm_load_bdb_dump (&df, *pdbf, replace);
737
0
    }
738
0
  else
739
0
    rc = _gdbm_load_file (&df, *pdbf, pdbf, mode, replace, meta_mask);
740
0
  dump_file_free (&df);
741
0
  if (rc)
742
0
    {
743
0
      if (line)
744
0
  *line = df.line;
745
0
      GDBM_SET_ERRNO (NULL, rc, FALSE);
746
0
      return -1;
747
0
    }
748
0
  return 0;
749
0
}
750
751
int
752
gdbm_load_from_file (GDBM_FILE *pdbf, FILE *fp, int replace,
753
         int meta_mask,
754
         unsigned long *line)
755
0
{
756
0
  return gdbm_load_from_file_ext (pdbf, fp,
757
0
          replace ? GDBM_WRCREAT : GDBM_NEWDB,
758
0
          replace,
759
0
          meta_mask,
760
0
          line);
761
0
}
762
763
int
764
gdbm_load (GDBM_FILE *pdbf, const char *filename, int replace,
765
     int meta_mask,
766
     unsigned long *line)
767
0
{
768
0
  FILE *fp;
769
0
  int rc;
770
771
0
  fp = fopen (filename, "r");
772
0
  if (!fp)
773
0
    {
774
0
      GDBM_SET_ERRNO (NULL, GDBM_FILE_OPEN_ERROR, FALSE);
775
0
      return -1;
776
0
    }
777
0
  rc = gdbm_load_from_file (pdbf, fp, replace, meta_mask, line);
778
0
  fclose (fp);
779
0
  return rc;
780
0
}