]>
Commit | Line | Data |
---|---|---|
823f0fd1 | 1 | |
f4be9e2b | 2 | #include "fdiskP.h" |
f7b1f75e | 3 | |
4e0e8253 | 4 | struct fdisk_context *fdisk_new_context(void) |
0c5d095e KZ |
5 | { |
6 | struct fdisk_context *cxt; | |
0c5d095e KZ |
7 | |
8 | cxt = calloc(1, sizeof(*cxt)); | |
9 | if (!cxt) | |
10 | return NULL; | |
11 | ||
4e0e8253 KZ |
12 | DBG(LABEL, dbgprint("new context %p allocated", cxt)); |
13 | cxt->dev_fd = -1; | |
14 | ||
0c5d095e KZ |
15 | /* |
16 | * Allocate label specific structs. | |
17 | * | |
18 | * This is necessary (for example) to store label specific | |
19 | * context setting. | |
20 | */ | |
21 | cxt->labels[ cxt->nlabels++ ] = fdisk_new_gpt_label(cxt); | |
22 | cxt->labels[ cxt->nlabels++ ] = fdisk_new_dos_label(cxt); | |
b4fb2a61 | 23 | cxt->labels[ cxt->nlabels++ ] = fdisk_new_bsd_label(cxt); |
0c5d095e KZ |
24 | cxt->labels[ cxt->nlabels++ ] = fdisk_new_sgi_label(cxt); |
25 | cxt->labels[ cxt->nlabels++ ] = fdisk_new_sun_label(cxt); | |
26 | ||
0c5d095e KZ |
27 | return cxt; |
28 | } | |
29 | ||
01b20713 KZ |
30 | /* only BSD is supported now */ |
31 | struct fdisk_context *fdisk_new_nested_context(struct fdisk_context *parent, | |
32 | const char *name) | |
33 | { | |
34 | struct fdisk_context *cxt; | |
8a9256f9 | 35 | struct fdisk_label *lb = NULL; |
01b20713 KZ |
36 | |
37 | assert(parent); | |
01b20713 KZ |
38 | |
39 | cxt = calloc(1, sizeof(*cxt)); | |
40 | if (!cxt) | |
41 | return NULL; | |
42 | ||
43 | DBG(LABEL, dbgprint("new context %p allocated", cxt)); | |
44 | cxt->dev_fd = parent->dev_fd; | |
45 | cxt->parent = parent; | |
46 | ||
47 | cxt->io_size = parent->io_size; | |
48 | cxt->optimal_io_size = parent->optimal_io_size; | |
49 | cxt->min_io_size = parent->min_io_size; | |
50 | cxt->phy_sector_size = parent->phy_sector_size; | |
51 | cxt->sector_size = parent->sector_size; | |
52 | cxt->alignment_offset = parent->alignment_offset; | |
53 | cxt->grain = parent->grain; | |
54 | cxt->first_lba = parent->first_lba; | |
55 | cxt->total_sectors = parent->total_sectors; | |
56 | ||
b720e0d7 KZ |
57 | cxt->ask_cb = parent->ask_cb; |
58 | cxt->ask_data = parent->ask_data; | |
59 | ||
01b20713 KZ |
60 | cxt->geom = parent->geom; |
61 | ||
8a9256f9 KZ |
62 | if (name && strcmp(name, "bsd") == 0) |
63 | lb = cxt->labels[ cxt->nlabels++ ] = fdisk_new_bsd_label(cxt); | |
64 | ||
65 | if (lb) { | |
66 | DBG(LABEL, dbgprint("probing for nested %s", lb->name)); | |
67 | ||
68 | cxt->label = lb; | |
69 | ||
70 | if (lb->op->probe(cxt) == 1) | |
71 | __fdisk_context_switch_label(cxt, lb); | |
72 | else { | |
73 | DBG(LABEL, dbgprint("not found %s label", lb->name)); | |
74 | if (lb->op->deinit) | |
75 | lb->op->deinit(lb); | |
76 | cxt->label = NULL; | |
77 | } | |
78 | } | |
01b20713 KZ |
79 | |
80 | return cxt; | |
81 | } | |
82 | ||
83 | ||
852ce62b KZ |
84 | /* |
85 | * Returns the current label if no name specified. | |
86 | */ | |
0c5d095e KZ |
87 | struct fdisk_label *fdisk_context_get_label(struct fdisk_context *cxt, const char *name) |
88 | { | |
89 | size_t i; | |
90 | ||
91 | assert(cxt); | |
92 | ||
852ce62b KZ |
93 | if (!name) |
94 | return cxt->label; | |
95 | ||
0c5d095e | 96 | for (i = 0; i < cxt->nlabels; i++) |
7ab242ec KZ |
97 | if (cxt->labels[i] |
98 | && strcmp(cxt->labels[i]->name, name) == 0) | |
0c5d095e KZ |
99 | return cxt->labels[i]; |
100 | ||
101 | DBG(LABEL, dbgprint("failed to found %s label driver\n", name)); | |
102 | return NULL; | |
103 | } | |
104 | ||
53b422ab KZ |
105 | int __fdisk_context_switch_label(struct fdisk_context *cxt, |
106 | struct fdisk_label *lb) | |
107 | { | |
108 | if (!lb) | |
109 | return -EINVAL; | |
110 | cxt->label = lb; | |
111 | DBG(LABEL, dbgprint("--> switching context to %s!", lb->name)); | |
112 | return 0; | |
113 | } | |
114 | ||
115 | int fdisk_context_switch_label(struct fdisk_context *cxt, const char *name) | |
116 | { | |
117 | return __fdisk_context_switch_label(cxt, | |
118 | fdisk_context_get_label(cxt, name)); | |
119 | } | |
120 | ||
121 | ||
4e0e8253 KZ |
122 | static void reset_context(struct fdisk_context *cxt) |
123 | { | |
7845ca8d | 124 | size_t i; |
4e0e8253 | 125 | |
1653f0b0 | 126 | DBG(CONTEXT, dbgprint("*** resetting context %p", cxt)); |
0559e742 KZ |
127 | |
128 | /* reset drives' private data */ | |
129 | for (i = 0; i < cxt->nlabels; i++) | |
130 | fdisk_deinit_label(cxt->labels[i]); | |
4e0e8253 | 131 | |
4e0e8253 | 132 | /* free device specific stuff */ |
01b20713 | 133 | if (!cxt->parent && cxt->dev_fd > -1) |
4e0e8253 KZ |
134 | close(cxt->dev_fd); |
135 | free(cxt->dev_path); | |
136 | free(cxt->firstsector); | |
137 | ||
4e0e8253 KZ |
138 | /* initialize */ |
139 | cxt->dev_fd = -1; | |
7845ca8d KZ |
140 | cxt->dev_path = NULL; |
141 | cxt->firstsector = NULL; | |
142 | ||
1653f0b0 | 143 | fdisk_zeroize_device_properties(cxt); |
7845ca8d KZ |
144 | |
145 | cxt->label = NULL; | |
4e0e8253 KZ |
146 | } |
147 | ||
823f0fd1 | 148 | /** |
4e0e8253 | 149 | * fdisk_context_assign_device: |
537187be | 150 | * @fname: path to the device to be handled |
25b529fe DB |
151 | * @readonly: how to open the device |
152 | * | |
153 | * If the @readonly flag is set to false, fdisk will attempt to open | |
154 | * the device with read-write mode and will fallback to read-only if | |
155 | * unsuccessful. | |
823f0fd1 | 156 | * |
58c41e15 | 157 | * Returns: 0 on success, < 0 on error. |
823f0fd1 | 158 | */ |
4e0e8253 KZ |
159 | int fdisk_context_assign_device(struct fdisk_context *cxt, |
160 | const char *fname, int readonly) | |
823f0fd1 | 161 | { |
4e0e8253 | 162 | int fd; |
823f0fd1 | 163 | |
4e0e8253 KZ |
164 | DBG(CONTEXT, dbgprint("assigning device %s", fname)); |
165 | assert(cxt); | |
166 | ||
167 | reset_context(cxt); | |
95f9f309 | 168 | |
065070f2 KZ |
169 | if (readonly == 1 || (fd = open(fname, O_RDWR|O_CLOEXEC)) < 0) { |
170 | if ((fd = open(fname, O_RDONLY|O_CLOEXEC)) < 0) | |
4e0e8253 | 171 | return -errno; |
7657d3e2 | 172 | readonly = 1; |
f7b1f75e | 173 | } |
823f0fd1 | 174 | |
823f0fd1 DB |
175 | cxt->dev_fd = fd; |
176 | cxt->dev_path = strdup(fname); | |
177 | if (!cxt->dev_path) | |
178 | goto fail; | |
618882d6 | 179 | |
aa42788d KZ |
180 | fdisk_discover_topology(cxt); |
181 | fdisk_discover_geometry(cxt); | |
823f0fd1 | 182 | |
3eb78aa7 KZ |
183 | if (fdisk_read_firstsector(cxt) < 0) |
184 | goto fail; | |
185 | ||
9a5e29e9 KZ |
186 | /* detect labels and apply labes specific stuff (e.g geomery) |
187 | * to the context */ | |
7ce10975 | 188 | fdisk_probe_labels(cxt); |
1653f0b0 KZ |
189 | |
190 | /* let's apply user geometry *after* label prober | |
191 | * to make it possible to override in-label setting */ | |
192 | fdisk_apply_user_device_properties(cxt); | |
9a5e29e9 | 193 | |
2b1a43cf KZ |
194 | DBG(CONTEXT, dbgprint("context %p initialized for %s [%s]", |
195 | cxt, fname, | |
196 | readonly ? "READ-ONLY" : "READ-WRITE")); | |
4e0e8253 | 197 | return 0; |
823f0fd1 | 198 | fail: |
4e0e8253 KZ |
199 | DBG(CONTEXT, dbgprint("failed to assign device")); |
200 | return -errno; | |
823f0fd1 DB |
201 | } |
202 | ||
203 | /** | |
204 | * fdisk_free_context: | |
205 | * @cxt: fdisk context | |
206 | * | |
207 | * Deallocates context struct. | |
208 | */ | |
209 | void fdisk_free_context(struct fdisk_context *cxt) | |
210 | { | |
0c5d095e KZ |
211 | int i; |
212 | ||
823f0fd1 DB |
213 | if (!cxt) |
214 | return; | |
215 | ||
2b1a43cf | 216 | DBG(CONTEXT, dbgprint("freeing context %p for %s", cxt, cxt->dev_path)); |
4e0e8253 | 217 | reset_context(cxt); |
0c5d095e KZ |
218 | |
219 | /* deallocate label's private stuff */ | |
220 | for (i = 0; i < cxt->nlabels; i++) { | |
221 | if (!cxt->labels[i]) | |
222 | continue; | |
223 | if (cxt->labels[i]->op->free) | |
224 | cxt->labels[i]->op->free(cxt->labels[i]); | |
225 | else | |
226 | free(cxt->labels[i]); | |
227 | } | |
228 | ||
823f0fd1 DB |
229 | free(cxt); |
230 | } | |
7845ca8d KZ |
231 | |
232 | /** | |
233 | * fdisk_context_set_ask: | |
234 | * @cxt: context | |
235 | * @ask_cb: callback | |
236 | * @data: callback data | |
237 | * | |
58c41e15 | 238 | * Returns: 0 on success, < 0 on error. |
7845ca8d KZ |
239 | */ |
240 | int fdisk_context_set_ask(struct fdisk_context *cxt, | |
241 | int (*ask_cb)(struct fdisk_context *, struct fdisk_ask *, void *), | |
242 | void *data) | |
243 | { | |
244 | assert(cxt); | |
245 | ||
246 | cxt->ask_cb = ask_cb; | |
247 | cxt->ask_data = data; | |
248 | return 0; | |
249 | } | |
cb7ce873 | 250 | |
a5c1b0fa KZ |
251 | /** |
252 | * fdisk_context_enable_details: | |
253 | * cxt: context | |
254 | * enable: true/flase | |
255 | * | |
256 | * Enables or disables "details" display mode. | |
257 | * | |
258 | * Returns: 0 on success, < 0 on error. | |
259 | */ | |
260 | int fdisk_context_enable_details(struct fdisk_context *cxt, int enable) | |
261 | { | |
262 | assert(cxt); | |
263 | cxt->display_details = enable ? 1 : 0; | |
264 | return 0; | |
265 | } | |
266 | ||
267 | int fdisk_context_display_details(struct fdisk_context *cxt) | |
268 | { | |
269 | assert(cxt); | |
270 | return cxt->display_details == 1; | |
271 | } | |
cb7ce873 | 272 | |
c10937dc KZ |
273 | /** |
274 | * fdisk_context_enable_listonly: | |
275 | * cxt: context | |
276 | * enable: true/flase | |
277 | * | |
278 | * Just list partition only, don't care about another details, mistakes, ... | |
279 | * | |
280 | * Returns: 0 on success, < 0 on error. | |
281 | */ | |
282 | int fdisk_context_enable_listonly(struct fdisk_context *cxt, int enable) | |
283 | { | |
284 | assert(cxt); | |
285 | cxt->listonly = enable ? 1 : 0; | |
286 | return 0; | |
287 | } | |
288 | ||
289 | int fdisk_context_listonly(struct fdisk_context *cxt) | |
290 | { | |
291 | assert(cxt); | |
292 | return cxt->listonly == 1; | |
293 | } | |
294 | ||
295 | ||
cb7ce873 KZ |
296 | /* |
297 | * @str: "cylinder" or "sector". | |
298 | * | |
299 | * This is pure shit, unfortunately for example Sun addresses begin of the | |
300 | * partition by cylinders... | |
301 | */ | |
302 | int fdisk_context_set_unit(struct fdisk_context *cxt, const char *str) | |
303 | { | |
304 | assert(cxt); | |
305 | ||
306 | cxt->display_in_cyl_units = 0; | |
307 | ||
308 | if (!str) | |
309 | return 0; | |
310 | ||
311 | if (strcmp(str, "cylinder") == 0 || strcmp(str, "cylinders") == 0) | |
312 | cxt->display_in_cyl_units = 1; | |
313 | ||
314 | else if (strcmp(str, "sector") == 0 || strcmp(str, "sectors") == 0) | |
315 | cxt->display_in_cyl_units = 0; | |
316 | ||
317 | DBG(CONTEXT, dbgprint("display unit: %s", fdisk_context_get_unit(cxt, 0))); | |
318 | return 0; | |
319 | } | |
320 | ||
321 | const char *fdisk_context_get_unit(struct fdisk_context *cxt, int n) | |
322 | { | |
323 | assert(cxt); | |
324 | ||
325 | if (fdisk_context_use_cylinders(cxt)) | |
326 | return P_("cylinder", "cylinders", n); | |
327 | return P_("sector", "sectors", n); | |
328 | } | |
329 | ||
330 | /* Returns 1 if user wants to display in cylinders. */ | |
331 | int fdisk_context_use_cylinders(struct fdisk_context *cxt) | |
332 | { | |
333 | assert(cxt); | |
334 | return cxt->display_in_cyl_units == 1; | |
335 | } | |
336 | ||
337 | /* Returns number of "units" per sector, default is 1 if display unit is sector. | |
338 | */ | |
339 | unsigned int fdisk_context_get_units_per_sector(struct fdisk_context *cxt) | |
340 | { | |
341 | assert(cxt); | |
342 | ||
343 | if (fdisk_context_use_cylinders(cxt)) { | |
344 | assert(cxt->geom.heads); | |
345 | return cxt->geom.heads * cxt->geom.sectors; | |
346 | } | |
347 | return 1; | |
348 | } |