]>
Commit | Line | Data |
---|---|---|
823f0fd1 DB |
1 | /* |
2 | * Copyright (C) 2012 Davidlohr Bueso <dave@gnu.org> | |
3 | * | |
4 | * This program is free software; you can redistribute it and/or modify | |
5 | * it under the terms of the GNU General Public License as published by | |
6 | * the Free Software Foundation; either version 2 of the License, or | |
7 | * (at your option) any later version. | |
8 | * | |
9 | * This program is distributed in the hope that it will be useful, | |
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
12 | * GNU General Public License for more details. | |
13 | * | |
14 | * You should have received a copy of the GNU General Public License along | |
15 | * with this program; if not, write to the Free Software Foundation, Inc., | |
16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | |
17 | */ | |
18 | ||
19 | #include <errno.h> | |
20 | #include <string.h> | |
21 | #include <stdlib.h> | |
22 | #include <unistd.h> | |
559d921e | 23 | #include <ctype.h> |
e53ced85 DB |
24 | #ifdef HAVE_LIBBLKID |
25 | #include <blkid.h> | |
26 | #endif | |
823f0fd1 | 27 | |
e53ced85 DB |
28 | #include "nls.h" |
29 | #include "blkdev.h" | |
823f0fd1 DB |
30 | #include "common.h" |
31 | #include "fdisk.h" | |
32 | ||
a71601af KZ |
33 | #include "fdiskdoslabel.h" |
34 | #include "fdisksunlabel.h" | |
35 | ||
f7b1f75e DB |
36 | int fdisk_debug_mask; |
37 | ||
b8855c86 | 38 | /* |
4477d73f | 39 | * Label probing functions. |
b8855c86 DB |
40 | */ |
41 | static const struct fdisk_label *labels[] = | |
42 | { | |
766d5156 | 43 | &gpt_label, |
b8855c86 | 44 | &dos_label, |
b8855c86 | 45 | &sun_label, |
79c8a145 | 46 | &sgi_label, |
b8855c86 | 47 | &aix_label, |
79c8a145 | 48 | &bsd_label, |
b8855c86 DB |
49 | &mac_label, |
50 | }; | |
51 | ||
61c4cb85 | 52 | |
b8855c86 DB |
53 | static int __probe_labels(struct fdisk_context *cxt) |
54 | { | |
48f2fdbf | 55 | size_t i; |
b8855c86 | 56 | |
ff5775bd | 57 | cxt->disklabel = FDISK_DISKLABEL_ANY; |
b8855c86 DB |
58 | |
59 | for (i = 0; i < ARRAY_SIZE(labels); i++) { | |
441afd48 | 60 | if (!labels[i]->probe || labels[i]->probe(cxt) != 1) |
79c8a145 DB |
61 | continue; |
62 | ||
63 | cxt->label = labels[i]; | |
64 | ||
61c4cb85 | 65 | DBG(LABEL, dbgprint("detected a %s label", cxt->label->name)); |
79c8a145 | 66 | return 0; |
b8855c86 DB |
67 | } |
68 | ||
79c8a145 | 69 | return 1; /* not found */ |
b8855c86 DB |
70 | } |
71 | ||
a71601af | 72 | /** |
639f1d56 | 73 | * fdisk_create_disklabel: |
a71601af | 74 | * @cxt: fdisk context |
639f1d56 | 75 | * @name: label name |
a71601af | 76 | * |
639f1d56 DB |
77 | * Creates a new disk label of type @name. If @name is NULL, then it |
78 | * will create a default system label type, either SUN or DOS. | |
a71601af | 79 | * |
639f1d56 | 80 | * Returns 0 on success, otherwise, a corresponding error. |
a71601af | 81 | */ |
639f1d56 | 82 | int fdisk_create_disklabel(struct fdisk_context *cxt, const char *name) |
a71601af KZ |
83 | { |
84 | if (!cxt) | |
85 | return -EINVAL; | |
ed21ffd3 | 86 | |
639f1d56 | 87 | cxt->label = NULL; |
ed21ffd3 | 88 | |
639f1d56 DB |
89 | if (!name) { /* use default label creation */ |
90 | #ifdef __sparc__ | |
91 | cxt->label = &sun_label; | |
a71601af | 92 | #else |
639f1d56 | 93 | cxt->label = &dos_label; |
a71601af | 94 | #endif |
639f1d56 DB |
95 | } else { |
96 | size_t i; | |
97 | ||
98 | for (i = 0; i < ARRAY_SIZE(labels); i++) { | |
99 | if (strcmp(name, labels[i]->name) != 0) | |
100 | continue; | |
101 | ||
102 | cxt->label = labels[i]; | |
103 | DBG(LABEL, dbgprint("changing to %s label\n", cxt->label->name)); | |
104 | break; | |
105 | } | |
106 | } | |
107 | ||
108 | if (!cxt->label) | |
109 | return -EINVAL; | |
441afd48 KZ |
110 | if (!cxt->label->create) |
111 | return -ENOSYS; | |
639f1d56 | 112 | |
cf3808e4 KZ |
113 | fdisk_reset_alignment(cxt); |
114 | ||
639f1d56 | 115 | return cxt->label->create(cxt); |
a71601af KZ |
116 | } |
117 | ||
823f0fd1 DB |
118 | /** |
119 | * fdisk_new_context: | |
537187be | 120 | * @fname: path to the device to be handled |
25b529fe DB |
121 | * @readonly: how to open the device |
122 | * | |
123 | * If the @readonly flag is set to false, fdisk will attempt to open | |
124 | * the device with read-write mode and will fallback to read-only if | |
125 | * unsuccessful. | |
823f0fd1 | 126 | * |
537187be | 127 | * Returns: newly allocated fdisk context or NULL upon failure. |
823f0fd1 | 128 | */ |
7657d3e2 | 129 | struct fdisk_context *fdisk_new_context_from_filename(const char *fname, int readonly) |
823f0fd1 DB |
130 | { |
131 | int fd, errsv = 0; | |
132 | struct fdisk_context *cxt = NULL; | |
133 | ||
95f9f309 KZ |
134 | DBG(CONTEXT, dbgprint("initializing context for %s", fname)); |
135 | ||
7657d3e2 | 136 | if (readonly == 1 || (fd = open(fname, O_RDWR)) < 0) { |
823f0fd1 DB |
137 | if ((fd = open(fname, O_RDONLY)) < 0) |
138 | return NULL; | |
7657d3e2 | 139 | readonly = 1; |
f7b1f75e | 140 | } |
823f0fd1 DB |
141 | |
142 | cxt = calloc(1, sizeof(*cxt)); | |
143 | if (!cxt) | |
144 | goto fail; | |
145 | ||
146 | cxt->dev_fd = fd; | |
147 | cxt->dev_path = strdup(fname); | |
148 | if (!cxt->dev_path) | |
149 | goto fail; | |
618882d6 | 150 | |
aa42788d KZ |
151 | fdisk_discover_topology(cxt); |
152 | fdisk_discover_geometry(cxt); | |
823f0fd1 | 153 | |
3eb78aa7 KZ |
154 | if (fdisk_read_firstsector(cxt) < 0) |
155 | goto fail; | |
156 | ||
9a5e29e9 KZ |
157 | /* detect labels and apply labes specific stuff (e.g geomery) |
158 | * to the context */ | |
b8855c86 DB |
159 | __probe_labels(cxt); |
160 | ||
cf3808e4 | 161 | fdisk_reset_alignment(cxt); |
9a5e29e9 | 162 | |
2b1a43cf KZ |
163 | DBG(CONTEXT, dbgprint("context %p initialized for %s [%s]", |
164 | cxt, fname, | |
165 | readonly ? "READ-ONLY" : "READ-WRITE")); | |
823f0fd1 DB |
166 | return cxt; |
167 | fail: | |
168 | errsv = errno; | |
169 | fdisk_free_context(cxt); | |
170 | errno = errsv; | |
7657d3e2 KZ |
171 | |
172 | DBG(CONTEXT, dbgprint("failed to initialize context for %s: %m", fname)); | |
823f0fd1 DB |
173 | return NULL; |
174 | } | |
175 | ||
176 | /** | |
177 | * fdisk_free_context: | |
178 | * @cxt: fdisk context | |
179 | * | |
180 | * Deallocates context struct. | |
181 | */ | |
182 | void fdisk_free_context(struct fdisk_context *cxt) | |
183 | { | |
184 | if (!cxt) | |
185 | return; | |
186 | ||
2b1a43cf | 187 | DBG(CONTEXT, dbgprint("freeing context %p for %s", cxt, cxt->dev_path)); |
823f0fd1 DB |
188 | close(cxt->dev_fd); |
189 | free(cxt->dev_path); | |
67987b47 | 190 | free(cxt->firstsector); |
823f0fd1 DB |
191 | free(cxt); |
192 | } | |
559d921e | 193 | |
559d921e | 194 | |
2b1a43cf | 195 |