203
210
ext_index, /* the prime extended partition */
204
211
listing = 0, /* no aborts for fdisk -l */
205
212
nowarn = 0, /* no warnings for fdisk -l/-s */
206
dos_compatible_flag = ~0,
213
dos_compatible_flag = 0, /* disabled by default */
208
215
partitions = 4; /* maximum partition + 1 */
216
223
unsigned int heads,
218
225
sector_size = DEFAULT_SECTOR_SIZE,
220
226
user_set_sector_size = 0,
221
227
units_per_sector = 1,
222
display_in_cyl_units = 1;
228
display_in_cyl_units = 0;
224
unsigned long long total_number_of_sectors; /* (!) 512-byte sectors */
230
unsigned long long total_number_of_sectors; /* in logical sectors */
225
231
unsigned long grain = DEFAULT_SECTOR_SIZE,
226
232
io_size = DEFAULT_SECTOR_SIZE,
227
233
min_io_size = DEFAULT_SECTOR_SIZE,
240
246
jmp_buf listingbuf;
248
static void __attribute__ ((__noreturn__)) usage(FILE *out)
250
fprintf(out, _("Usage:\n"
251
" %1$s [options] <disk> change partition table\n"
252
" %1$s [options] -l <disk> list partition table(s)\n"
253
" %1$s -s <partition> give partition size(s) in blocks\n"
255
" -b <size> sector size (512, 1024, 2048 or 4096)\n"
256
" -c[=<mode>] compatible mode: 'dos' or 'nondos' (default)\n"
257
" -h print this help text\n"
258
" -u[=<unit>] display units: 'cylinders' or 'sectors' (default)\n"
259
" -v print program version\n"
260
" -C <number> specify the number of cylinders\n"
261
" -H <number> specify the number of heads\n"
262
" -S <number> specify the number of sectors per track\n"
263
"\n"), program_invocation_short_name);
264
exit(out == stderr ? EXIT_FAILURE : EXIT_SUCCESS);
242
267
void fatal(enum failure why) {
243
char error[LINE_LENGTH],
245
int rc = EXIT_FAILURE;
255
case usage: message = _(
257
" fdisk [options] <disk> change partition table\n"
258
" fdisk [options] -l <disk> list partition table(s)\n"
259
" fdisk -s <partition> give partition size(s) in blocks\n"
261
" -b <size> sector size (512, 1024, 2048 or 4096)\n"
262
" -c switch off DOS-compatible mode\n"
264
" -u <size> give sizes in sectors instead of cylinders\n"
265
" -v print version\n"
266
" -C <number> specify the number of cylinders\n"
267
" -H <number> specify the number of heads\n"
268
" -S <number> specify the number of sectors per track\n"
271
275
case unable_to_open:
272
snprintf(error, sizeof(error),
273
_("Unable to open %s\n"), disk_device);
276
err(EXIT_FAILURE, _("unable to open %s"), disk_device);
275
278
case unable_to_read:
276
snprintf(error, sizeof(error),
277
_("Unable to read %s\n"), disk_device);
279
err(EXIT_FAILURE, _("unable to read %s"), disk_device);
279
281
case unable_to_seek:
280
snprintf(error, sizeof(error),
281
_("Unable to seek on %s\n"),disk_device);
282
err(EXIT_FAILURE, _("unable to seek on %s"), disk_device);
283
284
case unable_to_write:
284
snprintf(error, sizeof(error),
285
_("Unable to write %s\n"), disk_device);
285
err(EXIT_FAILURE, _("unable to write %s"), disk_device);
287
287
case ioctl_error:
288
snprintf(error, sizeof(error),
289
_("BLKGETSIZE ioctl failed on %s\n"),
293
message = _("Unable to allocate any more memory\n");
288
err(EXIT_FAILURE, _("BLKGETSIZE ioctl failed on %s"), disk_device);
296
message = _("Fatal error\n");
291
err(EXIT_FAILURE, _("fatal error"));
300
fputs(message, stderr);
328
319
struct pte *pe = &ptes[pno];
330
321
pe->offset = offset;
331
pe->sectorbuffer = malloc(sector_size);
332
if (!pe->sectorbuffer)
333
fatal(out_of_memory);
322
pe->sectorbuffer = xmalloc(sector_size);
334
323
read_sector(fd, offset, pe->sectorbuffer);
336
325
pe->part_table = pe->ext_pointer = NULL;
571
printf("%c%2x %-15.15s", i ? ' ' : '\n',
572
sys[next].type, _(sys[next].name));
573
next = last[i++] + done;
560
#define NAME_WIDTH 15
561
char name[NAME_WIDTH * MB_LEN_MAX];
562
size_t width = NAME_WIDTH;
564
printf("%c%2x ", i ? ' ' : '\n', sys[next].type);
565
size_t ret = mbsalign(_(sys[next].name), name, sizeof(name),
566
&width, MBS_ALIGN_LEFT, 0);
567
if (ret == (size_t)-1 || ret >= sizeof(name))
568
printf("%-15.15s", _(sys[next].name));
572
next = last[i++] + done;
574
573
if (i > 3 || next >= last[i]) {
647
646
lba_is_aligned(unsigned long long lba)
649
648
unsigned int granularity = max(phy_sector_size, min_io_size);
650
unsigned long long offset = (lba << 9) & (granularity - 1);
649
unsigned long long offset = (lba * sector_size) & (granularity - 1);
652
651
return !((granularity + alignment_offset - offset) & (granularity - 1));
753
752
if (display_in_cyl_units && cyl_units)
754
753
units_per_sector = cyl_units;
756
units_per_sector = 1; /* in sectors */
755
units_per_sector = 1; /* in sectors */
760
759
warn_limits(void) {
761
760
if (total_number_of_sectors > UINT_MAX && !nowarn) {
762
int giga = (total_number_of_sectors << 9) / 1000000000;
761
unsigned long long bytes = total_number_of_sectors * sector_size;
762
int giga = bytes / 1000000000;
763
763
int hectogiga = (giga + 50) / 100;
765
765
fprintf(stderr, _("\n"
768
768
"larger than (%llu bytes) for %d-byte sectors. Use parted(1) and GUID \n"
769
769
"partition table format (GPT).\n\n"),
770
770
hectogiga / 10, hectogiga % 10,
771
total_number_of_sectors << 9,
772
772
(unsigned long long ) UINT_MAX * sector_size,
785
785
"the physical sector size. Aligning to a physical sector (or optimal\n"
786
786
"I/O) size boundary is recommended, or performance may be impacted.\n"));
788
if (dos_compatible_flag) {
788
if (dos_compatible_flag)
789
789
fprintf(stderr, _("\n"
790
790
"WARNING: DOS-compatible mode is deprecated. It's strongly recommended to\n"
791
" switch off the mode (command 'c')"));
793
if (display_in_cyl_units)
794
fprintf(stderr, _(" and change display units to\n"
795
" sectors (command 'u').\n"));
797
fprintf(stderr, ".\n");
799
} else if (display_in_cyl_units)
791
" switch off the mode (with command 'c')."));
793
if (display_in_cyl_units)
800
794
fprintf(stderr, _("\n"
801
795
"WARNING: cylinders as display units are deprecated. Use command 'u' to\n"
802
796
" change units to sectors.\n"));
1116
1111
get_geometry(int fd, struct geom *g) {
1117
unsigned long long llcyls;
1112
unsigned long long llcyls, nsects = 0;
1119
1114
get_topology(fd);
1120
sector_factor = sector_size / 512;
1121
1115
guess_device_type(fd);
1122
1116
heads = cylinders = sectors = 0;
1123
1117
kern_heads = kern_sectors = 0;
1133
1127
pt_sectors ? pt_sectors :
1134
1128
kern_sectors ? kern_sectors : 63;
1136
if (blkdev_get_sectors(fd, &total_number_of_sectors) == -1)
1137
total_number_of_sectors = 0;
1130
/* get number of 512-byte sectors, and convert it the real sectors */
1131
if (blkdev_get_sectors(fd, &nsects) == 0)
1132
total_number_of_sectors = (nsects / (sector_size >> 9));
1139
1134
update_sector_offset();
1141
llcyls = total_number_of_sectors / (heads * sectors * sector_factor);
1136
llcyls = total_number_of_sectors / (heads * sectors);
1142
1137
cylinders = llcyls;
1143
1138
if (cylinders != llcyls) /* truncated? */
1144
1139
cylinders = ~0;
1205
1198
if (what == create_empty_dos)
1206
1199
goto got_dos_table; /* skip reading disk */
1208
if ((fd = open(disk_device, type_open)) < 0) {
1209
if ((fd = open(disk_device, O_RDONLY)) < 0) {
1210
if (what == try_only)
1212
fatal(unable_to_open);
1214
printf(_("You will not be able to write "
1215
"the partition table.\n"));
1201
if (what != try_only) {
1202
if ((fd = open(disk_device, type_open)) < 0) {
1203
if ((fd = open(disk_device, O_RDONLY)) < 0)
1204
fatal(unable_to_open);
1206
printf(_("You will not be able to write "
1207
"the partition table.\n"));
1218
1211
if (512 != read(fd, MBRbuffer, 512)) {
1302
static int is_partition_table_changed(void)
1306
for (i = 0; i < partitions; i++)
1307
if (ptes[i].changed)
1312
static void maybe_exit(int rc, int *asked)
1314
char line[LINE_LENGTH];
1320
if (is_partition_table_changed() || MBRbuffer_changed) {
1321
fprintf(stderr, _("Do you really want to quit? "));
1323
if (!fgets(line, LINE_LENGTH, stdin) || rpmatch(line) == 1)
1309
1331
/* read line; return 0 or first char */
1333
read_line(int *asked)
1313
static int got_eof = 0;
1315
1335
line_ptr = line_buffer;
1316
1336
if (!fgets(line_buffer, LINE_LENGTH, stdin)) {
1318
got_eof++; /* user typed ^D ? */
1321
fprintf(stderr, _("\ngot EOF thrice - exiting..\n"));
1337
maybe_exit(1, asked);
1326
1342
while (*line_ptr && !isgraph(*line_ptr))
1328
1344
return *line_ptr;
1514
get_partition(int warn, int max) {
1535
get_partition_dflt(int warn, int max, int dflt) {
1515
1536
struct pte *pe;
1518
i = read_int(1, 0, max, 0, _("Partition number")) - 1;
1539
i = read_int(1, dflt, max, 0, _("Partition number")) - 1;
1557
get_partition(int warn, int max) {
1558
return get_partition_dflt(warn, max, 0);
1536
1562
get_existing_partition(int warn, int max) {
1562
1588
get_nonexisting_partition(int warn, int max) {
1566
1593
for (i = 0; i < max; i++) {
1567
1594
struct pte *pe = &ptes[i];
1568
1595
struct partition *p = pe->part_table;
1570
1597
if (p && is_cleared_partition(p)) {
1572
1600
goto not_unique;
1597
1626
display_in_cyl_units = !display_in_cyl_units;
1598
1627
update_units();
1599
printf(_("Changing display/entry units to %s\n"),
1629
if (display_in_cyl_units)
1630
printf(_("Changing display/entry units to cylinders (DEPRECATED!)\n"));
1632
printf(_("Changing display/entry units to sectors\n"));
1617
1649
toggle_dos_compatibility_flag(void) {
1618
1650
dos_compatible_flag = ~dos_compatible_flag;
1619
1651
if (dos_compatible_flag)
1620
printf(_("DOS Compatibility flag is set\n"));
1652
printf(_("DOS Compatibility flag is set (DEPRECATED!)\n"));
1622
1654
printf(_("DOS Compatibility flag is not set\n"));
1785
1817
* Lubkin Oct. 1991). */
1788
long2chs(ulong ls, unsigned int *c, unsigned int *h, unsigned int *s) {
1820
long2chs(unsigned long ls, unsigned int *c, unsigned int *h, unsigned int *s) {
1789
1821
int spc = heads * sectors;
1878
1910
disk_device, megabytes, bytes);
1880
1912
long hectomega = (megabytes + 50) / 100;
1881
printf(_("\nDisk %s: %ld.%ld GB, %lld bytes\n"),
1913
printf(_("\nDisk %s: %ld.%ld GB, %llu bytes\n"),
1882
1914
disk_device, hectomega / 10, hectomega % 10, bytes);
1884
1916
printf(_("%d heads, %llu sectors/track, %d cylinders"),
1885
1917
heads, sectors, cylinders);
1886
1918
if (units_per_sector == 1)
1887
printf(_(", total %llu sectors"),
1888
total_number_of_sectors / sector_factor);
1919
printf(_(", total %llu sectors"), total_number_of_sectors);
1890
1921
printf(_("Units = %s of %d * %d = %d bytes\n"),
1891
1922
str_units(PLURAL),
2196
2227
unsigned long long total = 1;
2197
unsigned long long n_sectors = (total_number_of_sectors / sector_factor);
2228
unsigned long long n_sectors = total_number_of_sectors;
2198
2229
unsigned long long first[partitions], last[partitions];
2199
2230
struct partition *p;
2425
2456
pen->ext_pointer = p;
2426
2457
pe4->offset = extended_offset = start;
2427
if (!(pe4->sectorbuffer = calloc(1, sector_size)))
2428
fatal(out_of_memory);
2458
pe4->sectorbuffer = xcalloc(1, sector_size);
2429
2459
pe4->part_table = pt_offset(pe4->sectorbuffer, 0);
2430
2460
pe4->ext_pointer = pe4->part_table + 1;
2431
2461
pe4->changed = 1;
2438
2468
if (partitions > 5 || ptes[4].part_table->sys_ind) {
2439
2469
struct pte *pe = &ptes[partitions];
2441
if (!(pe->sectorbuffer = calloc(1, sector_size)))
2442
fatal(out_of_memory);
2471
pe->sectorbuffer = xcalloc(1, sector_size);
2443
2472
pe->part_table = pt_offset(pe->sectorbuffer, 0);
2444
2473
pe->ext_pointer = pe->part_table + 1;
2445
2474
pe->offset = 0;
2539
2568
if (dos_label) {
2541
if (ptes[i].changed)
2542
ptes[3].changed = 1;
2543
for (i = 3; i < partitions; i++) {
2569
/* MBR (primary partitions) */
2570
if (!MBRbuffer_changed) {
2571
for (i = 0; i < 4; i++)
2572
if (ptes[i].changed)
2573
MBRbuffer_changed = 1;
2575
if (MBRbuffer_changed) {
2576
write_part_table_flag(MBRbuffer);
2577
write_sector(fd, 0, MBRbuffer);
2579
/* EBR (logical partitions) */
2580
for (i = 4; i < partitions; i++) {
2544
2581
struct pte *pe = &ptes[i];
2546
2583
if (pe->changed) {
2651
2689
printf(_("Partition %d has no data area\n"), i + 1);
2654
first = get_partition_start(pe);
2655
new = read_int(first, first, first + get_nr_sects(p) - 1, first,
2693
/* the default start is at the second sector of the disk or at the
2694
* second sector of the extended partition
2696
free_start = pe->offset ? pe->offset + 1 : 1;
2698
curr_start = get_partition_start(pe);
2700
/* look for a free space before the current start of the partition */
2701
for (x = 0; x < partitions; x++) {
2703
struct pte *prev_pe = &ptes[x];
2704
struct partition *prev_p = prev_pe->part_table;
2708
end = get_partition_start(prev_pe) + get_nr_sects(prev_p);
2710
if (!is_cleared_partition(prev_p) &&
2711
end > free_start && end <= curr_start)
2715
last = get_partition_start(pe) + get_nr_sects(p) - 1;
2717
new = read_int(free_start, curr_start, last, free_start,
2656
2718
_("New beginning of data")) - pe->offset;
2658
2720
if (new != get_nr_sects(p)) {
2659
first = get_nr_sects(p) + get_start_sect(p) - new;
2660
set_nr_sects(p, first);
2721
unsigned int sects = get_nr_sects(p) + get_start_sect(p) - new;
2722
set_nr_sects(p, sects);
2661
2723
set_start_sect(p, new);
2662
2724
pe->changed = 1;
2846
2908
unsigned long long sz;
2848
procpt = fopen(PROC_PARTITIONS, "r");
2910
procpt = fopen(_PATH_PROC_PARTITIONS, "r");
2849
2911
if (procpt == NULL) {
2850
fprintf(stderr, _("cannot open %s\n"), PROC_PARTITIONS);
2912
fprintf(stderr, _("cannot open %s\n"), _PATH_PROC_PARTITIONS);
2856
2918
&ma, &mi, &sz, ptname) != 4)
2858
2920
snprintf(devname, sizeof(devname), "/dev/%s", ptname);
2859
if (is_whole_disk(devname))
2921
if (is_whole_disk(devname)) {
2922
char *cn = canonicalize_path(devname);
2862
2929
fclose(procpt);
2881
2948
bindtextdomain(PACKAGE, LOCALEDIR);
2882
2949
textdomain(PACKAGE);
2884
while ((c = getopt(argc, argv, "b:cC:hH:lsS:uvV")) != -1) {
2951
while ((c = getopt(argc, argv, "b:c::C:hH:lsS:u::vV")) != -1) {
2887
2954
/* Ugly: this sector size is really per device,
2899
2966
user_cylinders = atoi(optarg);
2902
dos_compatible_flag = 0;
2969
dos_compatible_flag = 0; /* default */
2971
if (optarg && !strcmp(optarg, "=dos"))
2972
dos_compatible_flag = ~0;
2973
else if (optarg && strcmp(optarg, "=nondos"))
2908
2980
user_heads = atoi(optarg);
2924
display_in_cyl_units = 0;
2996
display_in_cyl_units = 0; /* default */
2997
if (optarg && strcmp(optarg, "=cylinders") == 0)
2998
display_in_cyl_units = !display_in_cyl_units;
2999
else if (optarg && strcmp(optarg, "=sectors"))
2928
3004
printf("fdisk (%s)\n", PACKAGE_STRING);