]>
Commit | Line | Data |
---|---|---|
5545a732 JR |
1 | - sfdisk warning for large partitions, gpt |
2 | ||
3 | --- util-linux-2.13-pre6/fdisk/fdisk.c.gpt 2005-11-24 15:30:36.000000000 +0100 | |
4 | +++ util-linux-2.13-pre6/fdisk/fdisk.c 2005-11-24 15:30:36.000000000 +0100 | |
5 | @@ -34,6 +34,8 @@ | |
6 | #include <linux/blkpg.h> | |
7 | #endif | |
8 | ||
9 | +#include "gpt.h" | |
10 | + | |
11 | static void delete_partition(int i); | |
12 | ||
13 | #define hex_val(c) ({ \ | |
14 | @@ -2400,6 +2402,14 @@ | |
15 | } | |
16 | ||
17 | static void | |
18 | +gpt_warning(char *dev) | |
19 | +{ | |
20 | + if (gpt_probe_signature_devname(dev)) | |
21 | + fprintf(stderr, _("\nWARNING: GPT (GUID Partition Table) detected on '%s'! " | |
22 | + "The util fdisk doesn't support GPT. Use GNU Parted.\n\n"), dev); | |
23 | +} | |
24 | + | |
25 | +static void | |
26 | try(char *device, int user_specified) { | |
27 | int gb; | |
28 | ||
29 | @@ -2409,6 +2419,7 @@ | |
30 | if (!user_specified) | |
31 | if (is_ide_cdrom_or_tape(device)) | |
32 | return; | |
33 | + gpt_warning(device); | |
34 | if ((fd = open(disk_device, type_open)) >= 0) { | |
35 | gb = get_boot(try_only); | |
36 | if (gb > 0) { /* I/O error */ | |
37 | @@ -2470,6 +2481,8 @@ | |
38 | printf(_("%c: unknown command\n"), c); | |
39 | } | |
40 | ||
41 | + | |
42 | + | |
43 | int | |
44 | main(int argc, char **argv) { | |
45 | int j, c; | |
46 | @@ -2574,6 +2587,7 @@ | |
47 | ||
48 | for (j = optind; j < argc; j++) { | |
49 | disk_device = argv[j]; | |
50 | + gpt_warning(disk_device); | |
51 | if ((fd = open(disk_device, type_open)) < 0) | |
52 | fatal(unable_to_open); | |
53 | if (disksize(fd, &size)) | |
54 | @@ -2594,6 +2608,7 @@ | |
55 | else | |
56 | fatal(usage2); | |
57 | ||
58 | + gpt_warning(disk_device); | |
59 | get_boot(fdisk); | |
60 | ||
61 | if (osf_label) { | |
62 | --- /dev/null 2005-11-14 15:52:26.044616250 +0100 | |
63 | +++ util-linux-2.13-pre6/fdisk/gpt.h 2005-11-24 15:30:36.000000000 +0100 | |
64 | @@ -0,0 +1,9 @@ | |
65 | + | |
66 | +#ifndef __GPT_H__ | |
67 | +#define __GPT_H__ | |
68 | + | |
69 | +extern int gpt_probe_signature_fd(int fd); | |
70 | +extern int gpt_probe_signature_devname(char *devname); | |
71 | + | |
72 | +#endif /* __GPT_H__ */ | |
73 | + | |
74 | --- util-linux-2.13-pre6/fdisk/Makefile.am.gpt 2005-10-16 14:12:52.000000000 +0200 | |
75 | +++ util-linux-2.13-pre6/fdisk/Makefile.am 2005-11-24 15:31:42.000000000 +0100 | |
76 | @@ -5,13 +5,13 @@ | |
77 | sbin_PROGRAMS = fdisk | |
78 | man_MANS = fdisk.8 | |
79 | fdisk_SOURCES = fdisk.c disksize.c fdiskbsdlabel.c fdisksgilabel.c \ | |
80 | - fdisksunlabel.c fdiskaixlabel.c i386_sys_types.c partname.c | |
81 | + fdisksunlabel.c fdiskaixlabel.c i386_sys_types.c partname.c gpt.c | |
82 | ||
83 | if !SPARC | |
84 | ||
85 | sbin_PROGRAMS += sfdisk | |
86 | man_MANS += sfdisk.8 | |
87 | -sfdisk_SOURCES = sfdisk.c disksize.c i386_sys_types.c partname.c | |
88 | +sfdisk_SOURCES = sfdisk.c disksize.c i386_sys_types.c partname.c gpt.c | |
89 | ||
90 | if USE_SLANG | |
91 | sbin_PROGRAMS += cfdisk | |
92 | --- util-linux-2.13-pre6/fdisk/fdisk.8.gpt 2005-11-24 15:30:36.000000000 +0100 | |
93 | +++ util-linux-2.13-pre6/fdisk/fdisk.8 2005-11-24 15:30:36.000000000 +0100 | |
94 | @@ -42,6 +42,11 @@ | |
95 | partition tables. | |
96 | It understands DOS type partition tables and BSD or SUN type disklabels. | |
97 | ||
98 | +.B fdisk | |
99 | +doesn't understand GUID Partition Table (GPT) and | |
100 | +it is not designed for large partitions. In particular case use more advanced GNU | |
101 | +.B parted(8). | |
102 | + | |
103 | The | |
104 | .I device | |
105 | is usually one of the following: | |
106 | --- util-linux-2.13-pre6/fdisk/sfdisk.8.gpt 2004-12-31 17:28:30.000000000 +0100 | |
107 | +++ util-linux-2.13-pre6/fdisk/sfdisk.8 2005-11-24 15:30:36.000000000 +0100 | |
108 | @@ -18,6 +18,11 @@ | |
109 | on a device, check the partitions on a device, and - very dangerous - | |
110 | repartition a device. | |
111 | ||
112 | +.B sfdisk | |
113 | +doesn't understand GUID Partition Table (GPT) and | |
114 | +it is not designed for large partitions. In particular case use more advanced GNU | |
115 | +.B parted(8). | |
116 | + | |
117 | .SS "List Sizes" | |
118 | .BI "sfdisk \-s " partition | |
119 | gives the size of | |
120 | --- /dev/null 2005-11-14 15:52:26.044616250 +0100 | |
121 | +++ util-linux-2.13-pre6/fdisk/gpt.c 2005-11-24 15:30:36.000000000 +0100 | |
122 | @@ -0,0 +1,287 @@ | |
123 | +/* | |
124 | + GPT (GUID Partition Table) signature detection. Based on libparted and | |
125 | + util-linux/partx. | |
126 | + | |
127 | + Warning: this code doesn't do all GPT checks (CRC32, Protective MBR, ..). It's | |
128 | + really GPT signature detection only. | |
129 | + | |
130 | + -- Karel Zak <kzak@redhat.com> (Jun-2-2005) | |
131 | + | |
132 | +*/ | |
133 | + | |
134 | +#include <stdio.h> | |
135 | +#include <string.h> | |
136 | +#include <stdlib.h> | |
137 | +#include <inttypes.h> | |
138 | +#include <sys/stat.h> | |
139 | +#include <sys/ioctl.h> | |
140 | +#include <sys/utsname.h> | |
141 | +#include <sys/types.h> | |
142 | +#include <fcntl.h> | |
143 | +#include <unistd.h> | |
144 | +#include <errno.h> | |
145 | +#include <linux/fs.h> | |
146 | + | |
147 | +#include "gpt.h" | |
148 | + | |
149 | +#define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c)) | |
150 | +#define SECTOR_SIZE 512 /* default */ | |
151 | + | |
152 | +#define _GET_BYTE(x, n) ( ((x) >> (8 * (n))) & 0xff ) | |
153 | + | |
154 | +#define _PED_SWAP64(x) ( (_GET_BYTE(x, 0) << 56) \ | |
155 | + + (_GET_BYTE(x, 1) << 48) \ | |
156 | + + (_GET_BYTE(x, 2) << 40) \ | |
157 | + + (_GET_BYTE(x, 3) << 32) \ | |
158 | + + (_GET_BYTE(x, 4) << 24) \ | |
159 | + + (_GET_BYTE(x, 5) << 16) \ | |
160 | + + (_GET_BYTE(x, 6) << 8) \ | |
161 | + + (_GET_BYTE(x, 7) << 0) ) | |
162 | + | |
163 | +#define PED_SWAP64(x) ((uint64_t) _PED_SWAP64( (uint64_t) (x) )) | |
164 | + | |
165 | +#if __BYTE_ORDER == __LITTLE_ENDIAN | |
166 | +# define CPU_TO_LE64(x) (x) | |
167 | +#else | |
168 | +# define CPU_TO_LE64(x) PED_SWAP64(x) | |
169 | +#endif | |
170 | + | |
171 | +#define BLKSSZGET _IO(0x12,104) /* get block device sector size */ | |
172 | +#define BLKGETLASTSECT _IO(0x12,108) /* get last sector of block device */ | |
173 | +#define BLKGETSIZE _IO(0x12,96) /* return device size */ | |
174 | +#define BLKGETSIZE64 _IOR(0x12,114,size_t) /* return device size in bytes (u64 *arg) */ | |
175 | + | |
176 | +#define GPT_HEADER_SIGNATURE 0x5452415020494645LL | |
177 | +#define GPT_PRIMARY_PARTITION_TABLE_LBA 1 | |
178 | + | |
179 | +typedef struct { | |
180 | + uint32_t time_low; | |
181 | + uint16_t time_mid; | |
182 | + uint16_t time_hi_and_version; | |
183 | + uint8_t clock_seq_hi_and_reserved; | |
184 | + uint8_t clock_seq_low; | |
185 | + uint8_t node[6]; | |
186 | +} /* __attribute__ ((packed)) */ efi_guid_t; | |
187 | +/* commented out "__attribute__ ((packed))" to work around gcc bug (fixed | |
188 | + * in gcc3.1): __attribute__ ((packed)) breaks addressing on initialized | |
189 | + * data. It turns out we don't need it in this case, so it doesn't break | |
190 | + * anything :) | |
191 | + */ | |
192 | + | |
193 | +typedef struct _GuidPartitionTableHeader_t { | |
194 | + uint64_t Signature; | |
195 | + uint32_t Revision; | |
196 | + uint32_t HeaderSize; | |
197 | + uint32_t HeaderCRC32; | |
198 | + uint32_t Reserved1; | |
199 | + uint64_t MyLBA; | |
200 | + uint64_t AlternateLBA; | |
201 | + uint64_t FirstUsableLBA; | |
202 | + uint64_t LastUsableLBA; | |
203 | + efi_guid_t DiskGUID; | |
204 | + uint64_t PartitionEntryLBA; | |
205 | + uint32_t NumberOfPartitionEntries; | |
206 | + uint32_t SizeOfPartitionEntry; | |
207 | + uint32_t PartitionEntryArrayCRC32; | |
208 | + uint8_t Reserved2[512 - 92]; | |
209 | +} __attribute__ ((packed)) GuidPartitionTableHeader_t; | |
210 | + | |
211 | +struct blkdev_ioctl_param { | |
212 | + unsigned int block; | |
213 | + size_t content_length; | |
214 | + char * block_contents; | |
215 | +}; | |
216 | + | |
217 | +static int | |
218 | +_get_linux_version (void) | |
219 | +{ | |
220 | + static int kver = -1; | |
221 | + struct utsname uts; | |
222 | + int major; | |
223 | + int minor; | |
224 | + int teeny; | |
225 | + | |
226 | + if (kver != -1) | |
227 | + return kver; | |
228 | + if (uname (&uts)) | |
229 | + return kver = 0; | |
230 | + if (sscanf (uts.release, "%u.%u.%u", &major, &minor, &teeny) != 3) | |
231 | + return kver = 0; | |
232 | + return kver = KERNEL_VERSION (major, minor, teeny); | |
233 | +} | |
234 | + | |
235 | +static unsigned int | |
236 | +_get_sector_size (int fd) | |
237 | +{ | |
238 | + unsigned int sector_size; | |
239 | + | |
240 | + if (_get_linux_version() < KERNEL_VERSION (2,3,0)) | |
241 | + return SECTOR_SIZE; | |
242 | + if (ioctl (fd, BLKSSZGET, §or_size)) | |
243 | + return SECTOR_SIZE; | |
244 | + return sector_size; | |
245 | +} | |
246 | + | |
247 | +static uint64_t | |
248 | +_get_num_sectors(int fd) | |
249 | +{ | |
250 | + int version = _get_linux_version(); | |
251 | + unsigned long size; | |
252 | + uint64_t bytes=0; | |
253 | + | |
254 | + if (version >= KERNEL_VERSION(2,5,4) || | |
255 | + (version < KERNEL_VERSION(2,5,0) && | |
256 | + version >= KERNEL_VERSION (2,4,18))) | |
257 | + { | |
258 | + if (ioctl(fd, BLKGETSIZE64, &bytes) == 0) | |
259 | + return bytes / _get_sector_size(fd); | |
260 | + } | |
261 | + if (ioctl (fd, BLKGETSIZE, &size)) | |
262 | + return 0; | |
263 | + return size; | |
264 | +} | |
265 | + | |
266 | +static uint64_t | |
267 | +last_lba(int fd) | |
268 | +{ | |
269 | + int rc; | |
270 | + uint64_t sectors = 0; | |
271 | + struct stat s; | |
272 | + | |
273 | + memset(&s, 0, sizeof (s)); | |
274 | + rc = fstat(fd, &s); | |
275 | + if (rc == -1) | |
276 | + { | |
277 | + fprintf(stderr, "last_lba() could not stat: %s\n", | |
278 | + strerror(errno)); | |
279 | + return 0; | |
280 | + } | |
281 | + if (S_ISBLK(s.st_mode)) | |
282 | + sectors = _get_num_sectors(fd); | |
283 | + else | |
284 | + { | |
285 | + fprintf(stderr, | |
286 | + "last_lba(): I don't know how to handle files with mode %x\n", | |
287 | + s.st_mode); | |
288 | + sectors = 1; | |
289 | + } | |
290 | + return sectors - 1; | |
291 | +} | |
292 | + | |
293 | +static ssize_t | |
294 | +read_lastoddsector(int fd, uint64_t lba, void *buffer, size_t count) | |
295 | +{ | |
296 | + int rc; | |
297 | + struct blkdev_ioctl_param ioctl_param; | |
298 | + | |
299 | + if (!buffer) return 0; | |
300 | + | |
301 | + ioctl_param.block = 0; /* read the last sector */ | |
302 | + ioctl_param.content_length = count; | |
303 | + ioctl_param.block_contents = buffer; | |
304 | + | |
305 | + rc = ioctl(fd, BLKGETLASTSECT, &ioctl_param); | |
306 | + if (rc == -1) perror("read failed"); | |
307 | + | |
308 | + return !rc; | |
309 | +} | |
310 | + | |
311 | +static ssize_t | |
312 | +read_lba(int fd, uint64_t lba, void *buffer, size_t bytes) | |
313 | +{ | |
314 | + int sector_size = _get_sector_size(fd); | |
315 | + off_t offset = lba * sector_size; | |
316 | + ssize_t bytesread; | |
317 | + | |
318 | + lseek(fd, offset, SEEK_SET); | |
319 | + bytesread = read(fd, buffer, bytes); | |
320 | + | |
321 | + /* Kludge. This is necessary to read/write the last | |
322 | + block of an odd-sized disk, until Linux 2.5.x kernel fixes. | |
323 | + This is only used by gpt.c, and only to read | |
324 | + one sector, so we don't have to be fancy. | |
325 | + */ | |
326 | + if (!bytesread && !(last_lba(fd) & 1) && lba == last_lba(fd)) | |
327 | + bytesread = read_lastoddsector(fd, lba, buffer, bytes); | |
328 | + return bytesread; | |
329 | +} | |
330 | + | |
331 | +static GuidPartitionTableHeader_t * | |
332 | +alloc_read_gpt_header(int fd, uint64_t lba) | |
333 | +{ | |
334 | + GuidPartitionTableHeader_t *gpt = | |
335 | + (GuidPartitionTableHeader_t *) malloc(sizeof (GuidPartitionTableHeader_t)); | |
336 | + if (!gpt) | |
337 | + return NULL; | |
338 | + memset(gpt, 0, sizeof (*gpt)); | |
339 | + if (!read_lba(fd, lba, gpt, sizeof (GuidPartitionTableHeader_t))) | |
340 | + { | |
341 | + free(gpt); | |
342 | + return NULL; | |
343 | + } | |
344 | + return gpt; | |
345 | +} | |
346 | + | |
347 | +static int | |
348 | +gpt_check_signature(int fd, uint64_t lba) | |
349 | +{ | |
350 | + GuidPartitionTableHeader_t *gpt; | |
351 | + int res=0; | |
352 | + | |
353 | + if ((gpt = alloc_read_gpt_header(fd, lba))) | |
354 | + { | |
355 | + if (gpt->Signature == CPU_TO_LE64(GPT_HEADER_SIGNATURE)) | |
356 | + res = 1; | |
357 | + free(gpt); | |
358 | + } | |
359 | + return res; | |
360 | +} | |
361 | + | |
362 | +/* returns: | |
363 | + * 0 not found GPT | |
364 | + * 1 for valid primary GPT header | |
365 | + * 2 for valid alternative GPT header | |
366 | + */ | |
367 | +int | |
368 | +gpt_probe_signature_fd(int fd) | |
369 | +{ | |
370 | + int res = 0; | |
371 | + | |
372 | + /* check primary GPT header */ | |
373 | + if (gpt_check_signature(fd, GPT_PRIMARY_PARTITION_TABLE_LBA)) | |
374 | + res = 1; | |
375 | + else | |
376 | + { | |
377 | + /* check alternative GPT header */ | |
378 | + uint64_t lastlba = last_lba(fd); | |
379 | + if (gpt_check_signature(fd, lastlba)) | |
380 | + res = 2; | |
381 | + } | |
382 | + return res; | |
383 | +} | |
384 | + | |
385 | +int | |
386 | +gpt_probe_signature_devname(char *devname) | |
387 | +{ | |
388 | + int res, fd; | |
389 | + if ((fd = open(devname, O_RDONLY)) < 0) | |
390 | + return 0; | |
391 | + res = gpt_probe_signature_fd(fd); | |
392 | + close(fd); | |
393 | + return res; | |
394 | +} | |
395 | + | |
396 | +#ifdef GPT_TEST_MAIN | |
397 | +int | |
398 | +main(int argc, char **argv) | |
399 | +{ | |
400 | + if (argc!=2) | |
401 | + { | |
402 | + fprintf(stderr, "usage: %s <dev>\n", argv[0]); | |
403 | + exit(EXIT_FAILURE); | |
404 | + } | |
405 | + if (gpt_probe_signature_devname(argv[1])) | |
406 | + printf("GPT (GUID Partition Table) detected on %s\n", argv[1]); | |
407 | + exit(EXIT_SUCCESS); | |
408 | +} | |
409 | +#endif | |
410 | --- util-linux-2.13-pre6/fdisk/sfdisk.c.gpt 2005-10-16 14:18:32.000000000 +0200 | |
411 | +++ util-linux-2.13-pre6/fdisk/sfdisk.c 2005-11-24 15:30:36.000000000 +0100 | |
412 | @@ -50,6 +50,8 @@ | |
413 | #include "nls.h" | |
414 | #include "common.h" | |
415 | ||
416 | +#include "gpt.h" | |
417 | + | |
418 | #define SIZE(a) (sizeof(a)/sizeof(a[0])) | |
419 | ||
420 | /* | |
421 | @@ -2457,6 +2459,23 @@ | |
422 | return NULL; | |
423 | } | |
424 | ||
425 | +static void | |
426 | +gpt_warning(char *dev, int warn_only) | |
427 | +{ | |
428 | + if (force) | |
429 | + warn_only = 1; | |
430 | + | |
431 | + if (gpt_probe_signature_devname(dev)) { | |
432 | + fflush(stdout); | |
433 | + fprintf(stderr, _("\nWARNING: GPT (GUID Partition Table) detected on '%s'! " | |
434 | + "The util sfdisk doesn't support GPT. Use GNU Parted.\n\n"), dev); | |
435 | + if (!warn_only) { | |
436 | + fprintf(stderr, _("Use the --force flag to overrule this check.\n")); | |
437 | + exit(1); | |
438 | + } | |
439 | + } | |
440 | +} | |
441 | + | |
442 | static void do_list(char *dev, int silent); | |
443 | static void do_size(char *dev, int silent); | |
444 | static void do_geom(char *dev, int silent); | |
445 | @@ -2602,6 +2621,7 @@ | |
446 | while ((dev = nextproc()) != NULL) { | |
447 | if (is_ide_cdrom_or_tape(dev)) | |
448 | continue; | |
449 | + gpt_warning(dev, 1); | |
450 | if (opt_out_geom) | |
451 | do_geom(dev, 1); | |
452 | if (opt_out_pt_geom) | |
453 | @@ -2629,6 +2649,7 @@ | |
454 | ||
455 | if (opt_list || opt_out_geom || opt_out_pt_geom || opt_size || verify) { | |
456 | while (optind < argc) { | |
457 | + gpt_warning(argv[optind], 1); | |
458 | if (opt_out_geom) | |
459 | do_geom(argv[optind], 0); | |
460 | if (opt_out_pt_geom) | |
461 | @@ -2657,6 +2678,7 @@ | |
462 | fatal(_("usage: sfdisk --change-id device partition-number Id\n")); | |
463 | else if (optind != argc-3 && optind != argc-2) | |
464 | fatal(_("usage: sfdisk --id device partition-number [Id]\n")); | |
465 | + gpt_warning(argv[optind], 0); | |
466 | do_change_id(argv[optind], argv[optind+1], | |
467 | (optind == argc-2) ? 0 : argv[optind+2]); | |
468 | exit(exit_status); | |
469 | @@ -2666,6 +2688,8 @@ | |
470 | fatal(_("can specify only one device (except with -l or -s)\n")); | |
471 | dev = argv[optind]; | |
472 | ||
473 | + gpt_warning(dev, 0); | |
474 | + | |
475 | if (opt_reread) | |
476 | do_reread(dev); | |
477 | else if (restore_sector_file) | |
478 | @@ -2842,6 +2866,8 @@ | |
479 | ||
480 | z = &oldp; | |
481 | ||
482 | + gpt_warning(dev, 0); | |
483 | + | |
484 | rw = (!no_write && (arg || ac > 1)); | |
485 | fd = my_open(dev, rw, 0); | |
486 | ||
487 | @@ -2943,6 +2969,8 @@ | |
488 | ||
489 | z = &oldp; | |
490 | ||
491 | + gpt_warning(dev, 0); | |
492 | + | |
493 | rw = !no_write; | |
494 | fd = my_open(dev, rw, 0); | |
495 |