]> git.ipfire.org Git - thirdparty/util-linux.git/blob - libfdisk/src/wipe.c
53099fd44473e995d7f894a19441805024cc5803
[thirdparty/util-linux.git] / libfdisk / src / wipe.c
1 #include "c.h"
2 #include "strutils.h"
3
4 #ifdef HAVE_LIBBLKID
5 # include <blkid.h>
6 #endif
7
8 #include "fdiskP.h"
9
10 struct fdisk_wipe {
11 struct list_head wipes;
12 uint64_t start; /* sectors */
13 uint64_t size; /* sectors */
14 };
15
16 static struct fdisk_wipe *fdisk_get_wipe_area(
17 struct fdisk_context *cxt,
18 uint64_t start,
19 uint64_t size)
20 {
21 struct list_head *p;
22
23 if (cxt == NULL || list_empty(&cxt->wipes))
24 return NULL;
25
26 list_for_each(p, &cxt->wipes) {
27 struct fdisk_wipe *wp = list_entry(p, struct fdisk_wipe, wipes);
28 if (wp->start == start && wp->size == size)
29 return wp;
30 }
31 return NULL;
32 }
33
34 void fdisk_free_wipe_areas(struct fdisk_context *cxt)
35 {
36 while (!list_empty(&cxt->wipes)) {
37 struct fdisk_wipe *wp = list_entry(cxt->wipes.next,
38 struct fdisk_wipe, wipes);
39 DBG(WIPE, ul_debugobj(wp, "free [start=%ju, size=%ju]",
40 (uintmax_t) wp->start, (uintmax_t) wp->size));
41 list_del(&wp->wipes);
42 free(wp);
43 }
44 }
45
46 int fdisk_has_wipe_area(struct fdisk_context *cxt,
47 uint64_t start,
48 uint64_t size)
49 {
50 return fdisk_get_wipe_area(cxt, start, size) != NULL;
51 }
52
53 /* Add/remove new wiping area
54 *
55 * Returns: <0 on error, or old area setting (1: enabled, 0: disabled)
56 */
57 int fdisk_set_wipe_area(struct fdisk_context *cxt,
58 uint64_t start,
59 uint64_t size,
60 int enable)
61 {
62 struct fdisk_wipe *wp;
63
64 if (FDISK_IS_UNDEF(start) || FDISK_IS_UNDEF(size))
65 return -EINVAL;
66
67 wp = fdisk_get_wipe_area(cxt, start, size);
68
69 /* disable */
70 if (!enable) {
71 if (wp) {
72 DBG(WIPE, ul_debugobj(wp, "disable [start=%ju, size=%ju]",
73 (uintmax_t) start, (uintmax_t) size));
74 list_del(&wp->wipes);
75 free(wp);
76 return 1;
77 }
78 DBG(WIPE, ul_debug("not requested"));
79 return 0;
80 }
81
82 /* enable */
83 if (wp)
84 return 1; /* already enabled */
85
86 wp = calloc(1, sizeof(*wp));
87 if (!wp)
88 return -ENOMEM;
89
90 DBG(WIPE, ul_debugobj(wp, "enable [start=%ju, size=%ju]",
91 (uintmax_t) start, (uintmax_t) size));
92
93 INIT_LIST_HEAD(&wp->wipes);
94 wp->start = start;
95 wp->size = size;
96 list_add_tail(&wp->wipes, &cxt->wipes);
97
98 return 0;
99 }
100
101 #ifndef HAVE_LIBBLKID
102 int fdisk_do_wipe(struct fdisk_context *cxt __attribute__((__unused__)))
103 {
104 return 0;
105 }
106 #else
107 int fdisk_do_wipe(struct fdisk_context *cxt)
108 {
109 struct list_head *p;
110 blkid_probe pr;
111 int rc;
112
113 assert(cxt);
114 assert(cxt->dev_fd >= 0);
115
116 if (list_empty(&cxt->wipes))
117 return 0;
118
119 pr = blkid_new_probe();
120 if (!pr)
121 return -ENOMEM;
122
123 list_for_each(p, &cxt->wipes) {
124 struct fdisk_wipe *wp = list_entry(p, struct fdisk_wipe, wipes);
125 blkid_loff_t start = (blkid_loff_t) wp->start * cxt->sector_size,
126 size = (blkid_loff_t) wp->size * cxt->sector_size;
127
128 DBG(WIPE, ul_debugobj(wp, "initialize libblkid prober [start=%ju, size=%ju]",
129 (uintmax_t) start, (uintmax_t) size));
130
131 rc = blkid_probe_set_device(pr, cxt->dev_fd, start, size);
132 if (rc) {
133 DBG(WIPE, ul_debugobj(wp, "blkid_probe_set_device() failed [rc=%d]", rc));
134 return rc;
135 }
136
137 blkid_probe_enable_superblocks(pr, 1);
138 blkid_probe_set_superblocks_flags(pr, BLKID_SUBLKS_MAGIC |
139 BLKID_SUBLKS_BADCSUM);
140 blkid_probe_enable_partitions(pr, 1);
141 blkid_probe_set_partitions_flags(pr, BLKID_PARTS_MAGIC |
142 BLKID_PARTS_FORCE_GPT);
143
144 while (blkid_do_probe(pr) == 0) {
145 DBG(WIPE, ul_debugobj(wp, " wiping..."));
146 blkid_do_wipe(pr, FALSE);
147 }
148 }
149
150 blkid_free_probe(pr);
151 return 0;
152 }
153 #endif
154
155
156 /*
157 * Please don't call this function if there is already a PT.
158 *
159 * Returns: 0 if nothing found, < 0 on error, 1 if found a signature
160 */
161 #ifndef HAVE_LIBBLKID
162 int fdisk_check_collisions(struct fdisk_context *cxt __attribute__((__unused__)))
163 {
164 return 0;
165 }
166 #else
167 int fdisk_check_collisions(struct fdisk_context *cxt)
168 {
169 int rc = 0;
170 blkid_probe pr;
171
172 assert(cxt);
173 assert(cxt->dev_fd >= 0);
174
175 DBG(WIPE, ul_debugobj(cxt, "wipe check: initialize libblkid prober"));
176
177 pr = blkid_new_probe();
178 if (!pr)
179 return -ENOMEM;
180 rc = blkid_probe_set_device(pr, cxt->dev_fd, 0, 0);
181 if (rc)
182 return rc;
183
184 cxt->pt_collision = 0;
185 free(cxt->collision);
186 cxt->collision = NULL;
187
188 blkid_probe_enable_superblocks(pr, 1);
189 blkid_probe_set_superblocks_flags(pr, BLKID_SUBLKS_TYPE |
190 BLKID_SUBLKS_BADCSUM);
191 blkid_probe_enable_partitions(pr, 1);
192 blkid_probe_set_partitions_flags(pr, BLKID_PARTS_FORCE_GPT);
193
194 /* we care about the first found FS/raid, so don't call blkid_do_probe()
195 * in loop or don't use blkid_do_fullprobe() ... */
196 rc = blkid_do_probe(pr);
197 if (rc == 0) {
198 const char *name = NULL;
199
200 if (blkid_probe_lookup_value(pr, "TYPE", &name, 0) == 0)
201 cxt->collision = strdup(name);
202 else if (blkid_probe_lookup_value(pr, "PTTYPE", &name, 0) == 0) {
203 cxt->collision = strdup(name);
204 cxt->pt_collision = 1;
205 }
206
207 if (name && !cxt->collision)
208 rc = -ENOMEM;
209 }
210
211 blkid_free_probe(pr);
212 return rc < 0 ? rc : cxt->collision ? 1 : 0;
213 }
214 #endif