Imported Upstream version 2.6.1
[platform/upstream/cryptsetup.git] / tests / unit-wipe.c
1 /*
2  * unit test helper for crypt_wipe API call
3  *
4  * Copyright (C) 2022-2023 Milan Broz
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version.
10  *
11  * This program 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, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19  */
20
21 #include <errno.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <stdbool.h>
25 #include <string.h>
26 #include <sys/stat.h>
27
28 #include "libcryptsetup.h"
29
30 const char *test_file;
31 uint64_t test_offset, test_length, test_block;
32 uint32_t flags;
33 crypt_wipe_pattern pattern;
34
35 static void usage(void)
36 {
37         fprintf(stderr, "Use:\tunit-wipe file/device zero|random|special offset length bsize [no-dio].\n");
38 }
39
40 static bool parse_u64(const char *arg, uint64_t *u64)
41 {
42         unsigned long long ull;
43         char *end;
44
45         ull = strtoull(arg, &end, 10);
46         if (*end || !*arg || errno == ERANGE)
47                 return false;
48
49         if (ull % 512)
50                 return false;
51
52         *u64 = ull;
53         return true;
54 }
55
56 static bool parse_input_params(int argc, char **argv)
57 {
58         struct stat st;
59
60         if (argc < 6 || argc > 7) {
61                 usage();
62                 return false;
63         }
64
65         if (stat(argv[1], &st)) {
66                 fprintf(stderr, "File/device %s is missing?\n", argv[1]);
67                 return false;
68         }
69         test_file = argv[1];
70
71         if (!strcmp(argv[2], "random"))
72                 pattern = CRYPT_WIPE_RANDOM;
73         else if (!strcmp(argv[2], "zero"))
74                 pattern = CRYPT_WIPE_ZERO;
75         else if (!strcmp(argv[2], "special"))
76                 pattern = CRYPT_WIPE_SPECIAL;
77         else {
78                 fprintf(stderr, "Wrong pattern specification.\n");
79                 return false;
80         }
81
82         if (!parse_u64(argv[3], &test_offset)) {
83                 fprintf(stderr, "Wrong offset specification.\n");
84                 return false;
85         }
86
87         if (!parse_u64(argv[4], &test_length)) {
88                 fprintf(stderr, "Wrong length specification.\n");
89                 return false;
90         }
91
92         if (!parse_u64(argv[5], &test_block)) {
93                 fprintf(stderr, "Wrong block length specification.\n");
94                 return false;
95         }
96
97         if (argc > 6) {
98                 if (!strcmp(argv[6], "no-dio"))
99                         flags = CRYPT_WIPE_NO_DIRECT_IO;
100                 else {
101                         fprintf(stderr, "Wrong flags specification.\n");
102                         return false;
103                 }
104         }
105
106         return true;
107 }
108
109 int main(int argc, char **argv)
110 {
111         struct crypt_device *cd;
112         int r;
113
114 #ifndef NO_CRYPTSETUP_PATH
115         if (getenv("CRYPTSETUP_PATH")) {
116                 printf("Cannot run this test with CRYPTSETUP_PATH set.\n");
117                 exit(77);
118         }
119 #endif
120
121         if (!parse_input_params(argc, argv))
122                 return EXIT_FAILURE;
123
124         r = crypt_init(&cd, NULL);
125         if (r < 0) {
126                 fprintf(stderr, "Context init failure %i.\n", r);
127                 return EXIT_FAILURE;
128         }
129
130         r = crypt_wipe(cd, test_file, pattern, test_offset, test_length,
131                        test_block, flags, NULL, NULL);
132         crypt_free(cd);
133
134         if (r)
135                 fprintf(stderr, "Failure %i\n", r);
136
137         return r == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
138 }