1
2 #include <inttypes.h>
3
4 #include "fdiskP.h"
5
6 /**
7 * SECTION: item
8 * @title: Labelitem
9 * @short_description: disk label items
10 *
11 * The labelitem is label specific items stored in the partition table header.
12 * The information provided by labelitems are not specific to the partitions.
13 *
14 * For example
15 *
16 * <informalexample>
17 * <programlisting>
18 * struct fdisk_labelitem *item = fdisk_new_labelitem();
19 *
20 * fdisk_get_disklabel_item(cxt, GPT_LABELITEM_ALTLBA, item);
21 * print("Backup header LBA: %ju\n", fdisk_labelitem_get_data_u64(item));
22 *
23 * fdisk_unref_labelitem(item);
24 * </programlisting>
25 * </informalexample>
26 *
27 * returns LBA of the alternative GPT header.
28 *
29 * See also fdisk_get_disklabel_item(). The IDs are generic (e.g.
30 * FDISK_LABEL_ITEM_*) and label specific ((e.g. GPT_LABELITEM_*).
31 */
32
33 /**
34 * fdisk_new_labelitem
35 *
36 * Returns: new instance.
37 * Since: 2.29
38 */
39 struct fdisk_labelitem *fdisk_new_labelitem(void)
40 {
41 struct fdisk_labelitem *li = calloc(1, sizeof(*li));
42
43 if (!li)
44 return NULL;
45
46 li->refcount = 1;
47 DBG(ITEM, ul_debugobj(li, "alloc"));
48 return li;
49 }
50
51 /**
52 * fdisk_ref_labelitem:
53 * @li: label item
54 *
55 * Increments reference counter.
56 * Since: 2.29
57 */
58 void fdisk_ref_labelitem(struct fdisk_labelitem *li)
59 {
60 if (li) {
61 /* me sure we do not use refcouting for static items */
62 assert(li->refcount > 0);
63 li->refcount++;
64 }
65 }
66
67 /**
68 * fdisk_reset_labelitem:
69 * @li: label item
70 *
71 * Zeroize data stored in the @li (does not modify anything in disk label).
72 *
73 * Returns: 0 on success, or <0 in case of error
74 * Since: 2.29
75 */
76 int fdisk_reset_labelitem(struct fdisk_labelitem *li)
77 {
78 int refcount;
79
80 if (!li)
81 return -EINVAL;
82 if (li->type == 's')
83 free(li->data.str);
84
85 refcount = li->refcount;
86 memset(li, 0, sizeof(*li));
87 li->refcount = refcount;
88 return 0;
89 }
90
91 /**
92 * fdisk_unref_labelitem:
93 * @li: label item
94 *
95 * Decrements reference counter, on zero the @li is automatically
96 * deallocated.
97 *
98 * Since: 2.29
99 */
100 void fdisk_unref_labelitem(struct fdisk_labelitem *li)
101 {
102 if (!li)
103 return;
104
105 /* me sure we do not use refcouting for static items */
106 assert(li->refcount > 0);
107
108 li->refcount--;
109 if (li->refcount <= 0) {
110 DBG(ITEM, ul_debugobj(li, "free"));
111 fdisk_reset_labelitem(li);
112 free(li);
113 }
114 }
115
116 /**
117 * fdisk_labelitem_get_name:
118 * @li: label item
119 *
120 * Returns: item name or NULL.
121 * Since: 2.29
122 */
123 const char *fdisk_labelitem_get_name(struct fdisk_labelitem *li)
124 {
125 return li ? li->name : NULL;
126 }
127
128 /**
129 * fdisk_labelitem_get_id:
130 * @li: label item
131 *
132 * Returns: item Id or <0 in case of error.
133 * Since: 2.29
134 */
135 int fdisk_labelitem_get_id(struct fdisk_labelitem *li)
136 {
137 return li ? li->id : -EINVAL;
138 }
139
140
141 /**
142 * fdisk_labelitem_get_data_u64:
143 * @li: label item
144 * @data: returns data
145 *
146 * Returns: 0 on success, <0 on error
147 * Since: 2.29
148 */
149 int fdisk_labelitem_get_data_u64(struct fdisk_labelitem *li, uint64_t *data)
150 {
151 if (!li || li->type != 'j')
152 return -EINVAL;
153
154 if (data)
155 *data = li->data.num64;
156 return 0;
157 }
158
159 /**
160 * fdisk_labelitem_get_data_string:
161 * @li: label item
162 * @data: returns data
163 *
164 * Returns: 0 on success, <0 on error.
165 * Since: 2.29
166 */
167 int fdisk_labelitem_get_data_string(struct fdisk_labelitem *li, const char **data)
168 {
169 if (!li || li->type != 's')
170 return -EINVAL;
171
172 if (data)
173 *data = li->data.str;
174 return 0;
175 }
176
177 /**
178 * fdisk_labelitem_is_string:
179 * @li: label item
180 *
181 * Returns: 0 or 1
182 * Since: 2.29
183 */
184 int fdisk_labelitem_is_string(struct fdisk_labelitem *li)
185 {
186 return li && li->type == 's';
187 }
188
189 /**
190 * fdisk_labelitem_is_number:
191 * @li: label item
192 *
193 * Returns: 0 or 1
194 * Since: 2.29
195 */
196 int fdisk_labelitem_is_number(struct fdisk_labelitem *li)
197 {
198 return li && li->type == 'j';
199 }
200
201 #ifdef TEST_PROGRAM
202 static int test_listitems(struct fdisk_test *ts, int argc, char *argv[])
203 {
204 const char *disk = argv[1];
205 struct fdisk_context *cxt;
206 struct fdisk_labelitem *item;
207 int i = 0, rc;
208
209 cxt = fdisk_new_context();
210 item = fdisk_new_labelitem();
211
212 fdisk_assign_device(cxt, disk, 1);
213
214 do {
215 rc = fdisk_get_disklabel_item(cxt, i++, item);
216 switch (rc) {
217 case 0: /* success */
218 {
219 const char *name = fdisk_labelitem_get_name(item);
220 const char *str;
221 uint64_t num;
222
223 if (fdisk_labelitem_is_string(item)
224 && fdisk_labelitem_get_data_string(item, &str) == 0)
225 printf("%s: %s\n", name, str);
226 else if (fdisk_labelitem_get_data_u64(item, &num) == 0)
227 printf("%s: %"PRIu64"\n", name, num);
228 break;
229 }
230 case 1: /* item unsupported by label -- ignore */
231 rc = 0;
232 break;
233 case 2: /* end (out of range) */
234 break;
235 default: /* error */
236 break;
237 }
238 } while (rc == 0);
239
240 fdisk_unref_labelitem(item);
241 fdisk_unref_context(cxt);
242 return rc < 0 ? rc : 0;
243 }
244
245 int main(int argc, char *argv[])
246 {
247 struct fdisk_test tss[] = {
248 { "--list-items", test_listitems, "<disk> list items" },
249 { NULL }
250 };
251
252 return fdisk_run_test(tss, argc, argv);
253 }
254
255 #endif