g13: Re-factor high level create code.
[gnupg.git] / g13 / backend.c
1 /* backend.c - Dispatcher to the various backends.
2  * Copyright (C) 2009 Free Software Foundation, Inc.
3  *
4  * This file is part of GnuPG.
5  *
6  * GnuPG 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 of the License, or
9  * (at your option) any later version.
10  *
11  * GnuPG 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 this program; if not, see <http://www.gnu.org/licenses/>.
18  */
19
20 #include <config.h>
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <errno.h>
25 #include <unistd.h>
26 #include <sys/stat.h>
27
28 #include "g13.h"
29 #include "i18n.h"
30 #include "keyblob.h"
31 #include "backend.h"
32 #include "be-encfs.h"
33 #include "be-truecrypt.h"
34
35
36 static gpg_error_t
37 no_such_backend (int conttype)
38 {
39   log_error ("invalid backend %d given - this is most likely a bug\n",
40              conttype);
41   return gpg_error (GPG_ERR_INTERNAL);
42 }
43
44
45 /* Parse NAME and return the corresponding content type.  If the name
46    is not known, a error message is printed and zero returned.  If
47    NAME is NULL the supported backend types are listed and 0 is
48    returned. */
49 int
50 be_parse_conttype_name (const char *name)
51 {
52   static struct { const char *name; int conttype; } names[] = {
53     { "encfs",    CONTTYPE_ENCFS },
54     { "dm-crypt", CONTTYPE_DM_CRYPT }
55   };
56   int i;
57
58   if (!name)
59     {
60       log_info ("Known backend types:\n");
61       for (i=0; i < DIM (names); i++)
62         log_info ("    %s\n", names[i].name);
63       return 0;
64     }
65
66   for (i=0; i < DIM (names); i++)
67     {
68       if (!strcmp (names[i].name, name))
69         return names[i].conttype;
70     }
71
72   log_error ("invalid backend type '%s' given\n", name);
73   return 0;
74 }
75
76
77 /* Return true if CONTTYPE is supported by us.  */
78 int
79 be_is_supported_conttype (int conttype)
80 {
81   switch (conttype)
82     {
83     case CONTTYPE_ENCFS:
84       return 1;
85
86     default:
87       return 0;
88     }
89 }
90
91
92 /* Create a lock file for the container FNAME and store the lock at
93  * R_LOCK and return 0.  On error return an error code and store NULL
94  * at R_LOCK.  */
95 gpg_error_t
96 be_take_lock_for_create (ctrl_t ctrl, const char *fname, dotlock_t *r_lock)
97 {
98   gpg_error_t err;
99   dotlock_t lock = NULL;
100   struct stat sb;
101
102   *r_lock = NULL;
103
104   /* A DM-crypt container requires special treatment by using the
105      syshelper fucntions.  */
106   if (ctrl->conttype == CONTTYPE_DM_CRYPT)
107     {
108       /*  */
109       err = gpg_error (GPG_ERR_NOT_IMPLEMENTED);
110       goto leave;
111     }
112
113
114   /* A quick check to see that no container with that name already
115      exists.  */
116   if (!access (fname, F_OK))
117     {
118       err = gpg_error (GPG_ERR_EEXIST);
119       goto leave;
120     }
121
122   /* Take a lock and proceed with the creation.  If there is a lock we
123      immediately return an error because for creation it does not make
124      sense to wait.  */
125   lock = dotlock_create (fname, 0);
126   if (!lock)
127     {
128       err = gpg_error_from_syserror ();
129       goto leave;
130     }
131   if (dotlock_take (lock, 0))
132     {
133       err = gpg_error_from_syserror ();
134       goto leave;
135     }
136
137   /* Check again that the file does not exist.  */
138   err = stat (fname, &sb)? 0 : gpg_error (GPG_ERR_EEXIST);
139
140  leave:
141   if (!err)
142     {
143       *r_lock = lock;
144       lock = NULL;
145     }
146   dotlock_destroy (lock);
147   return err;
148 }
149
150
151 /* If the backend requires a separate file or directory for the
152    container, return its name by computing it from FNAME which gives
153    the g13 filename.  The new file name is allocated and stored at
154    R_NAME, if this is expected to be a directory true is stored at
155    R_ISDIR.  If no detached name is expected or an error occurs NULL
156    is stored at R_NAME. The function returns 0 on success or an error
157    code.  */
158 gpg_error_t
159 be_get_detached_name (int conttype, const char *fname,
160                       char **r_name, int *r_isdir)
161 {
162   *r_name = NULL;
163   *r_isdir = 0;
164   switch (conttype)
165     {
166     case CONTTYPE_ENCFS:
167       return be_encfs_get_detached_name (fname, r_name, r_isdir);
168
169     case CONTTYPE_DM_CRYPT:
170       return 0;
171
172     default:
173       return no_such_backend (conttype);
174     }
175 }
176
177
178 gpg_error_t
179 be_create_new_keys (int conttype, membuf_t *mb)
180 {
181   switch (conttype)
182     {
183     case CONTTYPE_ENCFS:
184       return be_encfs_create_new_keys (mb);
185
186     case CONTTYPE_TRUECRYPT:
187       return be_truecrypt_create_new_keys (mb);
188
189     default:
190       return no_such_backend (conttype);
191     }
192 }
193
194
195 /*  Dispatcher to the backend's create function.  */
196 gpg_error_t
197 be_create_container (ctrl_t ctrl, int conttype,
198                      const char *fname, int fd, tupledesc_t tuples,
199                      unsigned int *r_id)
200 {
201   (void)fd;  /* Not yet used.  */
202
203   switch (conttype)
204     {
205     case CONTTYPE_ENCFS:
206       return be_encfs_create_container (ctrl, fname, tuples, r_id);
207
208     default:
209       return no_such_backend (conttype);
210     }
211 }
212
213
214 /*  Dispatcher to the backend's mount function.  */
215 gpg_error_t
216 be_mount_container (ctrl_t ctrl, int conttype,
217                     const char *fname,  const char *mountpoint,
218                     tupledesc_t tuples, unsigned int *r_id)
219 {
220   switch (conttype)
221     {
222     case CONTTYPE_ENCFS:
223       return be_encfs_mount_container (ctrl, fname, mountpoint, tuples, r_id);
224
225     default:
226       return no_such_backend (conttype);
227     }
228 }