1 /* This file is part of GDBM, the GNU data base manager.
2 Copyright (C) 2011, 2013 Free Software Foundation, Inc.
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)
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.
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/>. */
17 # include "autoconf.h"
18 # include "gdbmdefs.h"
20 # include <sys/types.h>
26 unsigned char *buffer;
45 struct datbuf data[2];
50 dump_file_free (struct dump_file *file)
54 free (file->data[0].buffer);
55 free (file->data[1].buffer);
60 getparm (const char *buf, const char *parm)
67 for (p = parm; *p == *buf; p++, buf++)
69 if (*p == 0 && *buf == '=')
71 buf += strlen (buf) + 1;
77 get_dump_line (struct dump_file *file)
81 if (file->lblevel == 0)
83 while (fgets (buf, sizeof buf, file->fp))
85 size_t n = strlen (buf);
93 if (n + 1 + file->lblevel > file->lbsize)
95 size_t s = ((file->lblevel + n + _GDBM_MAX_DUMP_LINE_LEN)
96 / _GDBM_MAX_DUMP_LINE_LEN)
97 * _GDBM_MAX_DUMP_LINE_LEN;
98 char *newp = realloc (file->linebuf, s);
100 return GDBM_MALLOC_ERROR;
101 file->linebuf = newp;
105 memcpy (file->linebuf + file->lblevel, buf, n);
109 file->linebuf[file->lblevel] = 0;
114 return file->lblevel;
118 get_data (struct dump_file *file)
125 while ((n = get_dump_line (file)))
127 if (file->linebuf[0] == '#')
129 if (n + file->buflevel > file->bufsize)
131 size_t s = ((file->buflevel + n + _GDBM_MAX_DUMP_LINE_LEN - 1)
132 / _GDBM_MAX_DUMP_LINE_LEN)
133 * _GDBM_MAX_DUMP_LINE_LEN;
134 char *newp = realloc (file->buffer, s);
136 return GDBM_MALLOC_ERROR;
140 memcpy (file->buffer + file->buflevel, file->linebuf, n);
144 return ferror (file->fp) ? GDBM_FILE_READ_ERROR : 0;
148 get_parms (struct dump_file *file)
154 while ((n = get_dump_line (file)))
161 if (n == 0 || *++p != ':')
172 if (n + 1 + file->buflevel > file->bufsize)
174 size_t s = ((file->buflevel + n + _GDBM_MAX_DUMP_LINE_LEN)
175 / _GDBM_MAX_DUMP_LINE_LEN)
176 * _GDBM_MAX_DUMP_LINE_LEN;
177 char *newp = realloc (file->buffer, s);
179 return GDBM_MALLOC_ERROR;
187 while (*p == ' ' || *p == '\t')
191 while (*p && *p != '=')
192 file->buffer[file->buflevel++] = *p++;
196 file->buffer[file->buflevel++] = *p++;
200 while (*p && *p != '"')
201 file->buffer[file->buflevel++] = *p++;
208 while (!(*p == 0 || *p == ','))
209 file->buffer[file->buflevel++] = *p++;
212 file->buffer[file->buflevel++] = 0;
215 return GDBM_ILLEGAL_DATA;
223 file->buffer[file->buflevel] = 0;
225 return ferror (file->fp) ? GDBM_FILE_READ_ERROR : 0;
229 get_len (const char *param, size_t *plen)
232 const char *p = getparm (param, "len");
236 return GDBM_ITEM_NOT_FOUND;
239 n = strtoul (p, &end, 10);
240 if (*end == 0 && errno == 0)
246 return GDBM_ILLEGAL_DATA;
250 read_record (struct dump_file *file, char *param, int n, datum *dat)
253 size_t len, consumed_size, decoded_size;
257 rc = get_parms (file);
260 if (file->parmc == 0)
261 return GDBM_ITEM_NOT_FOUND;
262 param = file->buffer;
264 rc = get_len (param, &len);
267 dat->dsize = len; /* FIXME: data type mismatch */
268 rc = get_data (file);
272 rc = _gdbm_base64_decode ((unsigned char *)file->buffer, file->buflevel,
273 &file->data[n].buffer, &file->data[n].size,
274 &consumed_size, &decoded_size);
277 if (consumed_size != file->buflevel || decoded_size != len)
278 return GDBM_ILLEGAL_DATA;
279 dat->dptr = (void*) file->data[n].buffer;
283 #define META_UID 0x01
284 #define META_GID 0x02
285 #define META_MODE 0x04
288 _set_gdbm_meta_info (GDBM_FILE dbf, char *param, int meta_mask)
299 if (!(meta_mask & GDBM_META_MASK_OWNER))
301 p = getparm (param, "user");
304 struct passwd *pw = getpwnam (p);
307 owner_uid = pw->pw_uid;
308 meta_flags |= META_UID;
312 if (!(meta_flags & META_UID) && (p = getparm (param, "uid")))
315 n = strtoul (p, &end, 10);
316 if (*end == 0 && errno == 0)
319 meta_flags |= META_UID;
323 p = getparm (param, "group");
326 struct group *gr = getgrnam (p);
329 owner_gid = gr->gr_gid;
330 meta_flags |= META_GID;
333 if (!(meta_flags & META_GID) && (p = getparm (param, "gid")))
336 n = strtoul (p, &end, 10);
337 if (*end == 0 && errno == 0)
340 meta_flags |= META_GID;
345 if (!(meta_mask & GDBM_META_MASK_MODE))
347 p = getparm (param, "mode");
351 n = strtoul (p, &end, 8);
352 if (*end == 0 && errno == 0)
355 meta_flags |= META_MODE;
362 int fd = gdbm_fdesc (dbf);
363 if (getuid () == 0 && (meta_flags & (META_UID|META_GID)))
365 if ((meta_flags & (META_UID|META_GID)) != (META_UID|META_GID))
369 if (!(meta_flags & META_UID))
370 owner_uid = st.st_uid;
371 if (!(meta_flags & META_GID))
372 owner_gid = st.st_gid;
374 if (fchown (fd, owner_uid, owner_gid))
376 gdbm_errno = GDBM_ERR_FILE_OWNER;
380 if ((meta_flags & META_MODE) && fchmod (fd, mode))
382 gdbm_errno = GDBM_ERR_FILE_OWNER;
390 _gdbm_load_file (struct dump_file *file, GDBM_FILE dbf, GDBM_FILE *ofp,
391 int replace, int meta_mask)
395 GDBM_FILE tmp = NULL;
397 rc = get_parms (file);
403 file->header = file->buffer;
405 file->bufsize = file->buflevel = 0;
408 return GDBM_ILLEGAL_DATA;
412 const char *filename = getparm (file->header, "file");
414 return GDBM_NO_DBNAME;
415 tmp = gdbm_open (filename, 0,
416 replace ? GDBM_WRCREAT : GDBM_NEWDB, 0600, NULL);
422 param = file->header;
426 rc = read_record (file, param, 0, &key);
429 if (rc == GDBM_ITEM_NOT_FOUND && feof (file->fp))
435 rc = read_record (file, NULL, 1, &content);
439 if (gdbm_store (dbf, key, content, replace))
448 rc = _set_gdbm_meta_info (dbf, file->header, meta_mask);
458 read_bdb_header (struct dump_file *file)
463 if (!fgets (buf, sizeof (buf), file->fp))
465 if (strcmp (buf, "VERSION=3\n"))
467 while (fgets (buf, sizeof (buf), file->fp))
470 if (strcmp (buf, "HEADER=END\n") == 0)
479 static char xdig[] = "0123456789abcdef";
480 char *p = strchr (xdig, c);
489 xdatum_read (FILE *fp, datum *d, size_t *pdmax)
492 size_t dmax = *pdmax;
495 while ((c = fgetc (fp)) != EOF && c != '\n')
504 if ((c = fgetc (fp)) == EOF)
512 if (d->dsize == dmax)
514 char *np = realloc (d->dptr, dmax + DINCR);
516 return GDBM_MALLOC_ERROR;
520 d->dptr[d->dsize++] = t;
529 gdbm_load_bdb_dump (struct dump_file *file, GDBM_FILE dbf, int replace)
536 if (read_bdb_header (file))
538 memset (&xd, 0, sizeof (xd));
541 while ((c = fgetc (file->fp)) == ' ')
543 rc = xdatum_read (file->fp, &xd[i], &xs[i]);
550 if (gdbm_store (dbf, xd[0], xd[1], replace))
555 //FIXME: Read "DATA=END"
565 gdbm_load_from_file (GDBM_FILE *pdbf, FILE *fp, int replace,
575 /* Guess input file format */
584 gdbm_errno = GDBM_NO_DBNAME;
587 if (gdbm_import_from_file (*pdbf, fp, replace) == -1)
592 memset (&df, 0, sizeof df);
599 gdbm_errno = GDBM_NO_DBNAME;
602 rc = gdbm_load_bdb_dump (&df, *pdbf, replace);
605 rc = _gdbm_load_file (&df, *pdbf, pdbf, replace, meta_mask);
606 dump_file_free (&df);
618 gdbm_load (GDBM_FILE *pdbf, const char *filename, int replace,
625 fp = fopen (filename, "r");
628 gdbm_errno = GDBM_FILE_OPEN_ERROR;
631 rc = gdbm_load_from_file (pdbf, fp, replace, meta_mask, line);