Fix some extended compile warning.
[platform/upstream/cryptsetup.git] / src / utils_tools.c
1 /*
2  * cryptsetup - setup cryptographic volumes for dm-crypt
3  *
4  * Copyright (C) 2004, Christophe Saout <christophe@saout.de>
5  * Copyright (C) 2004-2007, Clemens Fruhwirth <clemens@endorphin.org>
6  * Copyright (C) 2009-2012, Red Hat, Inc. All rights reserved.
7  * Copyright (C) 2009-2012, Milan Broz
8  *
9  * This program is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU General Public License
11  * as published by the Free Software Foundation; either version 2
12  * of the License, or (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22  */
23
24 #include "cryptsetup.h"
25 #include <signal.h>
26
27 int opt_verbose = 0;
28 int opt_debug = 0;
29 int opt_batch_mode = 0;
30
31 /* interrupt handling */
32 volatile int quit = 0;
33 static int signals_blocked = 0;
34
35 static void int_handler(int sig __attribute__((__unused__)))
36 {
37         quit++;
38 }
39
40 int tools_signals_blocked(void)
41 {
42         return signals_blocked;
43 }
44
45 void set_int_block(int block)
46 {
47         sigset_t signals_open;
48
49         log_dbg("%slocking interruption on signal.", block ? "B" : "Unb");
50
51         sigemptyset(&signals_open);
52         sigaddset(&signals_open, SIGINT);
53         sigaddset(&signals_open, SIGTERM);
54         sigprocmask(block ? SIG_SETMASK : SIG_UNBLOCK, &signals_open, NULL);
55         signals_blocked = block;
56         quit = 0;
57 }
58
59 void set_int_handler(int block)
60 {
61         struct sigaction sigaction_open;
62
63         log_dbg("Installing SIGINT/SIGTERM handler.");
64         memset(&sigaction_open, 0, sizeof(struct sigaction));
65         sigaction_open.sa_handler = int_handler;
66         sigaction(SIGINT, &sigaction_open, 0);
67         sigaction(SIGTERM, &sigaction_open, 0);
68         set_int_block(block);
69 }
70
71 void check_signal(int *r)
72 {
73         if (quit && !*r)
74                 *r = -EINTR;
75 }
76
77 __attribute__((format(printf, 5, 6)))
78 void clogger(struct crypt_device *cd, int level, const char *file, int line,
79              const char *format, ...)
80 {
81         va_list argp;
82         char *target = NULL;
83
84         va_start(argp, format);
85
86         if (vasprintf(&target, format, argp) > 0) {
87                 if (level >= 0) {
88                         crypt_log(cd, level, target);
89 #ifdef CRYPT_DEBUG
90                 } else if (opt_debug)
91                         printf("# %s:%d %s\n", file ?: "?", line, target);
92 #else
93                 } else if (opt_debug)
94                         printf("# %s\n", target);
95 #endif
96         }
97
98         va_end(argp);
99         free(target);
100 }
101
102 void tool_log(int level, const char *msg, void *usrptr __attribute__((unused)))
103 {
104         switch(level) {
105
106         case CRYPT_LOG_NORMAL:
107                 fputs(msg, stdout);
108                 break;
109         case CRYPT_LOG_VERBOSE:
110                 if (opt_verbose)
111                         fputs(msg, stdout);
112                 break;
113         case CRYPT_LOG_ERROR:
114                 fputs(msg, stderr);
115                 break;
116         case CRYPT_LOG_DEBUG:
117                 if (opt_debug)
118                         printf("# %s\n", msg);
119                 break;
120         default:
121                 fprintf(stderr, "Internal error on logging class for msg: %s", msg);
122                 break;
123         }
124 }
125
126 void quiet_log(int level, const char *msg, void *usrptr)
127 {
128         if (!opt_verbose && (level == CRYPT_LOG_ERROR || level == CRYPT_LOG_NORMAL))
129                 level = CRYPT_LOG_VERBOSE;
130         tool_log(level, msg, usrptr);
131 }
132
133 int yesDialog(const char *msg, void *usrptr __attribute__((unused)))
134 {
135         char *answer = NULL;
136         size_t size = 0;
137         int r = 1, block;
138
139         block = tools_signals_blocked();
140         if (block)
141                 set_int_block(0);
142
143         if(isatty(STDIN_FILENO) && !opt_batch_mode) {
144                 log_std("\nWARNING!\n========\n");
145                 log_std("%s\n\nAre you sure? (Type uppercase yes): ", msg);
146                 if(getline(&answer, &size, stdin) == -1) {
147                         r = 0;
148                         /* Aborted by signal */
149                         if (!quit)
150                                 log_err(_("Error reading response from terminal.\n"));
151                         else
152                                 log_dbg("Query interrupted on signal.");
153                 } else if(strcmp(answer, "YES\n"))
154                         r = 0;
155         }
156
157         if (block && !quit)
158                 set_int_block(1);
159
160         free(answer);
161         return r;
162 }
163
164 void show_status(int errcode)
165 {
166         char error[256], *error_;
167
168         if(!opt_verbose)
169                 return;
170
171         if(!errcode) {
172                 log_std(_("Command successful.\n"));
173                 return;
174         }
175
176         crypt_get_error(error, sizeof(error));
177
178         if (!error[0]) {
179                 error_ = strerror_r(-errcode, error, sizeof(error));
180                 if (error_ != error) {
181                         strncpy(error, error_, sizeof(error));
182                         error[sizeof(error) - 1] = '\0';
183                 }
184         }
185
186         log_err(_("Command failed with code %i"), -errcode);
187         if (*error)
188                 log_err(": %s\n", error);
189         else
190                 log_err(".\n");
191 }
192
193 const char *uuid_or_device(const char *spec)
194 {
195         static char device[PATH_MAX];
196         char s, *ptr;
197         int i = 0, uuid_len = 5;
198
199         /* Check if it is correct UUID=<LUKS_UUID> format */
200         if (spec && !strncmp(spec, "UUID=", uuid_len)) {
201                 strcpy(device, "/dev/disk/by-uuid/");
202                 ptr = &device[strlen(device)];
203                 i = uuid_len;
204                 while ((s = spec[i++]) && i < PATH_MAX) {
205                         if (!isxdigit(s) && s != '-')
206                                 return spec; /* Bail it out */
207                         if (isalpha(s))
208                                 s = tolower(s);
209                         *ptr++ = s;
210                 }
211                 *ptr = '\0';
212                 return device;
213         }
214
215         return spec;
216 }
217
218 __attribute__ ((noreturn)) void usage(poptContext popt_context,
219                                              int exitcode, const char *error,
220                                              const char *more)
221 {
222         poptPrintUsage(popt_context, stderr, 0);
223         if (error)
224                 log_err("%s: %s\n", more, error);
225         poptFreeContext(popt_context);
226         exit(exitcode);
227 }
228
229 void dbg_version_and_cmd(int argc, const char **argv)
230 {
231         int i;
232
233         log_std("# %s %s processing \"", PACKAGE_NAME, PACKAGE_VERSION);
234         for (i = 0; i < argc; i++) {
235                 if (i)
236                         log_std(" ");
237                 log_std("%s", argv[i]);
238         }
239         log_std("\"\n");
240 }
241
242 /* Translate exit code to simple codes */
243 int translate_errno(int r)
244 {
245         switch (r) {
246         case 0:         r = EXIT_SUCCESS; break;
247         case -EEXIST:
248         case -EBUSY:    r = 5; break;
249         case -ENOTBLK:
250         case -ENODEV:   r = 4; break;
251         case -ENOMEM:   r = 3; break;
252         case -EPERM:    r = 2; break;
253         case -EINVAL:
254         case -ENOENT:
255         case -ENOSYS:
256         default:        r = EXIT_FAILURE;
257         }
258         return r;
259 }