Add PBKDF2 benchmark.
[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  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License
10  * version 2 as published by the Free Software Foundation.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20  */
21
22 #include "cryptsetup.h"
23
24 int opt_verbose = 0;
25 int opt_debug = 0;
26 int opt_batch_mode = 0;
27
28 __attribute__((format(printf, 5, 6)))
29 void clogger(struct crypt_device *cd, int level, const char *file, int line,
30              const char *format, ...)
31 {
32         va_list argp;
33         char *target = NULL;
34
35         va_start(argp, format);
36
37         if (vasprintf(&target, format, argp) > 0) {
38                 if (level >= 0) {
39                         crypt_log(cd, level, target);
40 #ifdef CRYPT_DEBUG
41                 } else if (opt_debug)
42                         printf("# %s:%d %s\n", file ?: "?", line, target);
43 #else
44                 } else if (opt_debug)
45                         printf("# %s\n", target);
46 #endif
47         }
48
49         va_end(argp);
50         free(target);
51 }
52
53 void tool_log(int level, const char *msg, void *usrptr __attribute__((unused)))
54 {
55         switch(level) {
56
57         case CRYPT_LOG_NORMAL:
58                 fputs(msg, stdout);
59                 break;
60         case CRYPT_LOG_VERBOSE:
61                 if (opt_verbose)
62                         fputs(msg, stdout);
63                 break;
64         case CRYPT_LOG_ERROR:
65                 fputs(msg, stderr);
66                 break;
67         case CRYPT_LOG_DEBUG:
68                 if (opt_debug)
69                         printf("# %s\n", msg);
70                 break;
71         default:
72                 fprintf(stderr, "Internal error on logging class for msg: %s", msg);
73                 break;
74         }
75 }
76
77 void quiet_log(int level, const char *msg, void *usrptr)
78 {
79         if (!opt_verbose && (level == CRYPT_LOG_ERROR || level == CRYPT_LOG_NORMAL))
80                 level = CRYPT_LOG_VERBOSE;
81         tool_log(level, msg, usrptr);
82 }
83
84 int yesDialog(const char *msg, void *usrptr __attribute__((unused)))
85 {
86         char *answer = NULL;
87         size_t size = 0;
88         int r = 1;
89
90         if(isatty(STDIN_FILENO) && !opt_batch_mode) {
91                 log_std("\nWARNING!\n========\n");
92                 log_std("%s\n\nAre you sure? (Type uppercase yes): ", msg);
93                 if(getline(&answer, &size, stdin) == -1) {
94                         perror("getline");
95                         free(answer);
96                         return 0;
97                 }
98                 if(strcmp(answer, "YES\n"))
99                         r = 0;
100                 free(answer);
101         }
102
103         return r;
104 }
105
106 void show_status(int errcode)
107 {
108         char error[256], *error_;
109
110         if(!opt_verbose)
111                 return;
112
113         if(!errcode) {
114                 log_std(_("Command successful.\n"));
115                 return;
116         }
117
118         crypt_get_error(error, sizeof(error));
119
120         if (!error[0]) {
121                 error_ = strerror_r(-errcode, error, sizeof(error));
122                 if (error_ != error) {
123                         strncpy(error, error_, sizeof(error));
124                         error[sizeof(error) - 1] = '\0';
125                 }
126         }
127
128         log_err(_("Command failed with code %i"), -errcode);
129         if (*error)
130                 log_err(": %s\n", error);
131         else
132                 log_err(".\n");
133 }
134
135 const char *uuid_or_device(const char *spec)
136 {
137         static char device[PATH_MAX];
138         char s, *ptr;
139         int i = 0, uuid_len = 5;
140
141         /* Check if it is correct UUID=<LUKS_UUID> format */
142         if (spec && !strncmp(spec, "UUID=", uuid_len)) {
143                 strcpy(device, "/dev/disk/by-uuid/");
144                 ptr = &device[strlen(device)];
145                 i = uuid_len;
146                 while ((s = spec[i++]) && i < PATH_MAX) {
147                         if (!isxdigit(s) && s != '-')
148                                 return spec; /* Bail it out */
149                         if (isalpha(s))
150                                 s = tolower(s);
151                         *ptr++ = s;
152                 }
153                 *ptr = '\0';
154                 return device;
155         }
156
157         return spec;
158 }
159
160 __attribute__ ((noreturn)) void usage(poptContext popt_context,
161                                              int exitcode, const char *error,
162                                              const char *more)
163 {
164         poptPrintUsage(popt_context, stderr, 0);
165         if (error)
166                 log_err("%s: %s\n", more, error);
167         poptFreeContext(popt_context);
168         exit(exitcode);
169 }
170
171 void dbg_version_and_cmd(int argc, const char **argv)
172 {
173         int i;
174
175         log_std("# %s %s processing \"", PACKAGE_NAME, PACKAGE_VERSION);
176         for (i = 0; i < argc; i++) {
177                 if (i)
178                         log_std(" ");
179                 log_std("%s", argv[i]);
180         }
181         log_std("\"\n");
182 }
183
184 /* Translate exit code to simple codes */
185 int translate_errno(int r)
186 {
187         switch (r) {
188         case 0:         r = EXIT_SUCCESS; break;
189         case -EEXIST:
190         case -EBUSY:    r = 5; break;
191         case -ENOTBLK:
192         case -ENODEV:   r = 4; break;
193         case -ENOMEM:   r = 3; break;
194         case -EPERM:    r = 2; break;
195         case -EINVAL:
196         case -ENOENT:
197         case -ENOSYS:
198         default:        r = EXIT_FAILURE;
199         }
200         return r;
201 }