]> git.ipfire.org Git - thirdparty/util-linux.git/blame - libfdisk/src/context.c
fdisk: cleanup write table code
[thirdparty/util-linux.git] / libfdisk / src / context.c
CommitLineData
823f0fd1 1
f4be9e2b 2#include "fdiskP.h"
f7b1f75e 3
4e0e8253 4struct 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 */
31struct 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
87struct 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
105int __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
115int 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
122static 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
159int 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 198fail:
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 */
209void 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 */
240int 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 */
260int 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
267int 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 */
282int 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
289int 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 */
302int 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
321const 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. */
331int 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 */
339unsigned 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}