Imported Upstream version 1.11
[platform/upstream/gdbm.git] / src / gdbm_load.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 "gdbm.h"
19 # include "gdbmapp.h"
20 # include "gdbmdefs.h"
21 # include <pwd.h>
22 # include <grp.h>
23
24 int replace = 0;
25 int meta_mask = 0;
26 int no_meta_option;
27
28 int mode;
29 uid_t owner_uid;
30 gid_t owner_gid;
31
32 char *parseopt_program_doc = "load a GDBM database from a file";
33 char *parseopt_program_args = "FILE [DB_FILE]";
34 struct gdbm_option optab[] = {
35   { 'r', "replace", NULL, N_("replace records in the existing database") },
36   { 'm', "mode", N_("MODE"), N_("set file mode") },
37   { 'u', "user", N_("NAME|UID[:NAME|GID]"), N_("set file owner") },
38   { 'n', "no-meta", NULL, N_("do not attempt to set file meta-data") },
39   { 'M', "mmap", NULL, N_("use memory mapping") },
40   { 'c', "cache-size", N_("NUM"), N_("set the cache size") },
41   { 'b', "block-size", N_("NUM"), N_("set the block size") },
42   { 0 }
43 };
44
45 static int
46 set_meta_info (GDBM_FILE dbf)
47 {
48   if (meta_mask)
49     {
50       int fd = gdbm_fdesc (dbf);
51
52       if (meta_mask & GDBM_META_MASK_OWNER)
53         {
54           if (fchown (fd, owner_uid, owner_gid))
55             {
56               gdbm_errno = GDBM_ERR_FILE_OWNER;
57               return 1;
58             }
59         }
60       if ((meta_mask & GDBM_META_MASK_MODE) && fchmod (fd, mode))
61         {
62           gdbm_errno = GDBM_ERR_FILE_OWNER;
63           return 1;
64         }
65     }
66   return 0;
67 }
68
69 static int
70 get_int (const char *arg)
71 {
72   char *p;
73   long n;
74  
75   errno = 0;
76   n = strtol (arg, &p, 0);
77   if (*p)
78     {
79       error (_("invalid number: %s"), arg);
80       exit (EXIT_USAGE);
81     }
82   if (errno)
83     {
84       error (_("invalid number: %s: %s"), arg, strerror (errno));
85       exit (EXIT_USAGE);
86     }
87   return n;
88 }
89
90 int
91 main (int argc, char **argv)
92 {
93   GDBM_FILE dbf = NULL;
94   int rc, opt;
95   char *dbname, *filename;
96   FILE *fp;
97   unsigned long err_line, n;
98   char *end;
99   int oflags = GDBM_NEWDB|GDBM_NOMMAP;
100   int cache_size = 0;
101   int block_size = 0;
102   
103 #ifdef HAVE_SETLOCALE
104   setlocale (LC_ALL, "");
105 #endif
106   bindtextdomain (PACKAGE, LOCALEDIR);
107   textdomain (PACKAGE);
108
109   set_progname (argv[0]);
110
111   for (opt = parseopt_first (argc, argv, optab);
112        opt != EOF;
113        opt = parseopt_next ())
114     {
115     switch (opt)
116       {
117       case 'b':
118         block_size = get_int (optarg);
119         break;
120         
121       case 'c':
122         cache_size = get_int (optarg);
123         break;
124
125       case 'm':
126         {
127           errno = 0;
128           n = strtoul (optarg, &end, 8);
129           if (*end == 0 && errno == 0)
130             {
131               mode = n & 0777;
132               meta_mask |= GDBM_META_MASK_MODE;
133             }
134           else
135             {
136               error ("%s", _("invalid octal number"));
137               exit (EXIT_USAGE);
138             }
139         }
140         break;
141
142       case 'u':
143         {
144           size_t len;
145           struct passwd *pw;
146           
147           len = strcspn (optarg, ".:");
148           if (optarg[len])
149             optarg[len++] = 0;
150           pw = getpwnam (optarg);
151           if (pw)
152             owner_uid = pw->pw_uid;
153           else
154             {
155               errno = 0;
156               n = strtoul (optarg, &end, 10);
157               if (*end == 0 && errno == 0)
158                 owner_uid = n;
159               else
160                 {
161                   error (_("invalid user name: %s"), optarg);
162                   exit (EXIT_USAGE);
163                 }
164             }
165           
166           if (optarg[len])
167             {
168               char *grname = optarg + len;
169               struct group *gr = getgrnam (grname);
170               if (gr)
171                 owner_gid = gr->gr_gid;
172               else
173                 {
174                   errno = 0;
175                   n = strtoul (grname, &end, 10);
176                   if (*end == 0 && errno == 0)
177                     owner_gid = n;
178                   else
179                     {
180                       error (_("invalid group name: %s"), grname);
181                       exit (EXIT_USAGE);
182                     }
183                 }
184             }
185           else
186             {
187               if (!pw)
188                 {
189                   pw = getpwuid (owner_uid);
190                   if (!pw)
191                     {
192                       error (_("no such UID: %lu"), (unsigned long)owner_uid);
193                       exit (EXIT_USAGE);
194                     }
195                 }
196               owner_gid = pw->pw_gid;
197             }
198           meta_mask |= GDBM_META_MASK_OWNER;
199         }
200         break;
201           
202       case 'r':
203         replace = 1;
204         break;
205
206       case 'n':
207         no_meta_option = 1;
208         break;
209
210       case 'M':
211         oflags &= ~GDBM_NOMMAP;
212         break;
213         
214       default:
215         error (_("unknown option"));
216         exit (EXIT_USAGE);
217       }
218     }
219
220   argc -= optind;
221   argv += optind;
222   
223   if (argc == 0)
224     {
225       parseopt_print_help ();
226       exit (EXIT_OK);
227     }
228
229   if (argc > 2)
230     {
231       error (_("too many arguments; try `%s -h' for more info"), progname);
232       exit (EXIT_USAGE);
233     }
234   
235   filename = argv[0];
236   if (argc == 2)
237     dbname = argv[1];
238   else
239     dbname = NULL;
240
241   if (strcmp (filename, "-") == 0)
242     {
243       filename = "<stdin>";
244       fp = stdin;
245     }
246   else
247     {
248       fp = fopen (filename, "r");
249       if (!fp)
250         {
251           sys_perror (errno, _("cannot open %s"), filename);
252           exit (EXIT_FATAL);
253         }
254     }
255   
256   if (dbname)
257     {
258       dbf = gdbm_open (dbname, block_size, oflags, 0600, NULL);
259       if (!dbf)
260         {
261           gdbm_perror (_("gdbm_open failed"));
262           exit (EXIT_FATAL);
263         }
264
265       if (cache_size &&
266           gdbm_setopt (dbf, GDBM_SETCACHESIZE, &cache_size, sizeof (int)) == -1)
267         error (_("gdbm_setopt failed: %s"), gdbm_strerror (gdbm_errno));
268     }
269   
270   rc = gdbm_load_from_file (&dbf, fp, replace,
271                             no_meta_option ?
272                               (GDBM_META_MASK_MODE | GDBM_META_MASK_OWNER) :
273                               meta_mask,
274                             &err_line);
275   if (rc)
276     {
277       switch (gdbm_errno)
278         {
279         case GDBM_ERR_FILE_OWNER:
280         case GDBM_ERR_FILE_MODE:
281           error (_("error restoring metadata: %s (%s)"),
282                  gdbm_strerror (gdbm_errno), strerror (errno));
283           rc = EXIT_MILD;
284           break;
285           
286         default:
287           if (err_line)
288             gdbm_perror ("%s:%lu", filename, err_line);
289           else
290             gdbm_perror (_("cannot load from %s"), filename);
291           rc = EXIT_FATAL;
292         }
293     }
294
295   if (dbf)
296     {
297       if (!no_meta_option && set_meta_info (dbf))
298         {
299           error (_("error restoring metadata: %s (%s)"),
300                  gdbm_strerror (gdbm_errno), strerror (errno));
301           rc = EXIT_MILD;
302         }
303       
304       if (!dbname)
305         {
306           if (gdbm_setopt (dbf, GDBM_GETDBNAME, &dbname, sizeof (dbname)))
307             gdbm_perror (_("gdbm_setopt failed"));
308           else
309             {
310               printf ("%s: created %s\n", progname, dbname);
311               free (dbname);
312             }
313         }
314       gdbm_close (dbf);
315     }
316   exit (rc);
317 }