add changelog
[platform/upstream/gdbm.git] / src / gdbmdump.c
1 /* This file is part of GDBM, the GNU data base manager.
2    Copyright (C) 2011, 2013 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 {
28   int rc;
29   size_t len;
30   unsigned char *p;
31   
32   fprintf (fp, "#:len=%lu\n", (unsigned long) dat->dsize);
33   rc = _gdbm_base64_encode ((unsigned char*) dat->dptr, dat->dsize,
34                             bufptr, bufsize, &len);
35   if (rc)
36     return rc;
37   
38   p = *bufptr;
39   while (len)
40     {
41       size_t n = len;
42       if (n > _GDBM_MAX_DUMP_LINE_LEN)
43         n = _GDBM_MAX_DUMP_LINE_LEN;
44       if (fwrite (p, n, 1, fp) != 1)
45         return GDBM_FILE_WRITE_ERROR;
46       fputc ('\n', fp);
47       len -= n;
48       p += n;
49     }
50   return 0;
51 }
52
53 int
54 _gdbm_dump_ascii (GDBM_FILE dbf, FILE *fp)
55 {
56   time_t t;
57   int fd;
58   struct stat st;
59   struct passwd *pw;
60   struct group *gr;
61   datum key;
62   size_t count = 0;
63   unsigned char *buffer = NULL;
64   size_t bufsize = 0;
65   int rc;
66
67   fd = gdbm_fdesc (dbf);
68   if (fstat (fd, &st))
69     return GDBM_FILE_STAT_ERROR;
70
71   /* Print header */
72   time (&t);
73   fprintf (fp, "# GDBM dump file created by %s on %s",
74            gdbm_version, ctime (&t));
75   fprintf (fp, "#:version=1.0\n");
76
77   fprintf (fp, "#:file=%s\n", dbf->name);
78   fprintf (fp, "#:uid=%lu,", (unsigned long) st.st_uid);
79   pw = getpwuid (st.st_uid);
80   if (pw)
81     fprintf (fp, "user=%s,", pw->pw_name);
82   fprintf (fp, "gid=%lu,", (unsigned long) st.st_gid);
83   gr = getgrgid (st.st_gid);
84   if (gr)
85     fprintf (fp, "group=%s,", gr->gr_name);
86   fprintf (fp, "mode=%03o\n", st.st_mode & 0777);
87   fprintf (fp, "# End of header\n");
88   
89   key = gdbm_firstkey (dbf);
90
91   while (key.dptr)
92     {
93       datum nextkey;
94       datum data = gdbm_fetch (dbf, key);
95       if (data.dptr)
96         {
97           if ((rc = print_datum (&key, &buffer, &bufsize, fp)) ||
98               (rc = print_datum (&data, &buffer, &bufsize, fp)))
99             {
100               free (key.dptr);
101               free (data.dptr);
102               gdbm_errno = rc;
103               break;
104             }
105         }
106       nextkey = gdbm_nextkey (dbf, key);
107       free (key.dptr);
108       free (data.dptr);
109       key = nextkey;
110       count++;
111     }
112
113   if (rc == 0)
114     {
115       /* FIXME: Something like that won't hurt, although load does not
116          use it currently. */
117       fprintf (fp, "#:count=%lu\n", (unsigned long) count);
118       fprintf (fp, "# End of data\n");
119     }
120   free (buffer);
121
122   
123   return rc ? -1 : 0;
124 }
125
126 int
127 gdbm_dump_to_file (GDBM_FILE dbf, FILE *fp, int format)
128 {
129   int rc;
130   
131   switch (format)
132     {
133     case GDBM_DUMP_FMT_BINARY:
134       rc = gdbm_export_to_file (dbf, fp) == -1;
135       break;
136
137     case GDBM_DUMP_FMT_ASCII:
138       rc = _gdbm_dump_ascii (dbf, fp);
139       break;
140
141     default:
142       return EINVAL;
143     }
144   
145   if (rc == 0 && ferror (fp))
146     rc = gdbm_errno = GDBM_FILE_WRITE_ERROR;
147
148   return rc;
149 }
150
151 int
152 gdbm_dump (GDBM_FILE dbf, const char *filename, int fmt, int open_flags,
153            int mode)
154 {
155   int nfd, rc;
156   FILE *fp;
157   
158   /* Only support GDBM_WCREAT or GDBM_NEWDB */
159   switch (open_flags)
160     {
161     case GDBM_WRCREAT:
162       nfd = open (filename, O_WRONLY | O_CREAT | O_EXCL, mode);
163       if (nfd == -1)
164         {
165           gdbm_errno = GDBM_FILE_OPEN_ERROR;
166           return -1;
167         }
168       break;
169     case GDBM_NEWDB:
170       nfd = open (filename, O_WRONLY | O_CREAT | O_TRUNC, mode);
171       if (nfd == -1)
172         {
173           gdbm_errno = GDBM_FILE_OPEN_ERROR;
174           return -1;
175         }
176       break;
177     default:
178       gdbm_errno = GDBM_BAD_OPEN_FLAGS;
179       return -1;
180   }
181
182   fp = fdopen (nfd, "w");
183   if (!fp)
184     {
185       close (nfd);
186       gdbm_errno = GDBM_FILE_OPEN_ERROR;
187       return -1;
188     }
189   rc = gdbm_dump_to_file (dbf, fp, fmt);
190   fclose (fp);
191   return rc;
192 }
193
194
195