~ubuntu-branches/ubuntu/quantal/util-linux/quantal

« back to all changes in this revision

Viewing changes to fdisk/fdisk.c

  • Committer: Bazaar Package Importer
  • Author(s): Steve Langasek
  • Date: 2011-06-20 22:31:50 UTC
  • mfrom: (1.6.3 upstream) (4.5.1 sid)
  • Revision ID: james.westby@ubuntu.com-20110620223150-lz8wrv0946ihcz3z
Tags: 2.19.1-2ubuntu1
* Merge from Debian unstable, remaining changes:
  - Build for multiarch.
  - Add pre-depends on multiarch-support.
  - configure.ac: don't try to be clever about extracting a path name from
    $libdir to append to /usr in a way that's not overridable; instead,
    reuse the built-in configurable libexecdir.
  - Fix up the .pc.in files to know about libexecdir, so our substitutions
    don't leave us with unusable pkg-config files.
  - Install custom blkid.conf to use /dev/.blkid.tab since we don't
    expect device names to survive a reboot
  - Mention mountall(8) in fstab(5) manpages, along with its special
    options.
  - Since upstart is required in Ubuntu, the hwclock.sh init script is not
    called on startup and the hwclockfirst.sh init script is removed.
  - Drop depends on initscripts for the above.
  - Replace hwclock udev rule with an Upstart job.
  - For the case where mount is called with a directory to mount, look
    that directory up in mountall's /lib/init/fstab if we couldn't find
    it mentioned anywhere else.  This means "mount /proc", "mount /sys",
    etc. work.
  - mount.8 points to the cifs-utils package, not the obsolete smbfs one. 
* Dropped changes:
  - mount.preinst: lsb_release has been fixed in lucid and above to be
    usable without configuration, so we don't have to diverge from Debian
    here anymore.
* Changes merged upstream:
  - sfdisk support for '+' with '-N'
  - mount/umount.c: fix a segfault on umount with empty mtab entry
  - Fix arbitrary unmount with fuse security issue

Show diffs side-by-side

added added

removed removed

Lines of Context:
22
22
#include <time.h>
23
23
#include <limits.h>
24
24
 
 
25
#include "xalloc.h"
25
26
#include "nls.h"
 
27
#include "rpmatch.h"
26
28
#include "blkdev.h"
27
29
#include "common.h"
 
30
#include "mbsalign.h"
28
31
#include "fdisk.h"
29
32
#include "wholedisk.h"
 
33
#include "pathnames.h"
 
34
#include "canonicalize.h"
30
35
 
31
36
#include "fdisksunlabel.h"
32
37
#include "fdisksgilabel.h"
179
184
 */
180
185
unsigned char *MBRbuffer;
181
186
 
 
187
int MBRbuffer_changed;
 
188
 
182
189
/*
183
190
 * per partition table entry data
184
191
 *
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 */
207
214
        dos_changed = 0,
208
215
        partitions = 4;                 /* maximum partition + 1 */
209
216
 
216
223
unsigned int    heads,
217
224
        cylinders,
218
225
        sector_size = DEFAULT_SECTOR_SIZE,
219
 
        sector_factor = 1,
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;
223
229
 
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,
239
245
 
240
246
jmp_buf listingbuf;
241
247
 
 
248
static void __attribute__ ((__noreturn__)) usage(FILE *out)
 
249
{
 
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"
 
254
                       "\nOptions:\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);
 
265
}
 
266
 
242
267
void fatal(enum failure why) {
243
 
        char    error[LINE_LENGTH],
244
 
                *message = error;
245
 
        int     rc = EXIT_FAILURE;
246
268
 
247
269
        if (listing) {
248
270
                close(fd);
250
272
        }
251
273
 
252
274
        switch (why) {
253
 
                case help:
254
 
                        rc = EXIT_SUCCESS;
255
 
                case usage: message = _(
256
 
"Usage:\n"
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"
260
 
"\nOptions:\n"
261
 
" -b <size>                 sector size (512, 1024, 2048 or 4096)\n"
262
 
" -c                        switch off DOS-compatible mode\n"
263
 
" -h                        print help\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"
269
 
"\n");
270
 
                        break;
271
275
                case unable_to_open:
272
 
                        snprintf(error, sizeof(error),
273
 
                                 _("Unable to open %s\n"), disk_device);
274
 
                        break;
 
276
                        err(EXIT_FAILURE, _("unable to open %s"), disk_device);
 
277
 
275
278
                case unable_to_read:
276
 
                        snprintf(error, sizeof(error),
277
 
                                 _("Unable to read %s\n"), disk_device);
278
 
                        break;
 
279
                        err(EXIT_FAILURE, _("unable to read %s"), disk_device);
 
280
 
279
281
                case unable_to_seek:
280
 
                        snprintf(error, sizeof(error),
281
 
                                _("Unable to seek on %s\n"),disk_device);
282
 
                        break;
 
282
                        err(EXIT_FAILURE, _("unable to seek on %s"), disk_device);
 
283
 
283
284
                case unable_to_write:
284
 
                        snprintf(error, sizeof(error),
285
 
                                _("Unable to write %s\n"), disk_device);
286
 
                        break;
 
285
                        err(EXIT_FAILURE, _("unable to write %s"), disk_device);
 
286
 
287
287
                case ioctl_error:
288
 
                        snprintf(error, sizeof(error),
289
 
                                 _("BLKGETSIZE ioctl failed on %s\n"),
290
 
                                disk_device);
291
 
                        break;
292
 
                case out_of_memory:
293
 
                        message = _("Unable to allocate any more memory\n");
294
 
                        break;
 
288
                        err(EXIT_FAILURE, _("BLKGETSIZE ioctl failed on %s"), disk_device);
 
289
 
295
290
                default:
296
 
                        message = _("Fatal error\n");
 
291
                        err(EXIT_FAILURE, _("fatal error"));
297
292
        }
298
 
 
299
 
        fputc('\n', stderr);
300
 
        fputs(message, stderr);
301
 
        exit(rc);
302
293
}
303
294
 
304
295
static void
328
319
        struct pte *pe = &ptes[pno];
329
320
 
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);
335
324
        pe->changed = 0;
336
325
        pe->part_table = pe->ext_pointer = NULL;
568
557
        i = done = 0;
569
558
 
570
559
        do {
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;
 
563
 
 
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));
 
569
                else
 
570
                        fputs(name, stdout);
 
571
 
 
572
                next = last[i++] + done;
574
573
                if (i > 3 || next >= last[i]) {
575
574
                        i = 0;
576
575
                        next = ++done;
647
646
lba_is_aligned(unsigned long long lba)
648
647
{
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);
651
650
 
652
651
        return !((granularity + alignment_offset - offset) & (granularity - 1));
653
652
}
753
752
        if (display_in_cyl_units && cyl_units)
754
753
                units_per_sector = cyl_units;
755
754
        else
756
 
                units_per_sector = 1;   /* in sectors */
 
755
                units_per_sector = 1;   /* in sectors */
757
756
}
758
757
 
759
758
static void
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;
764
764
 
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,
 
771
                        bytes,
772
772
                        (unsigned long long ) UINT_MAX * sector_size,
773
773
                        sector_size);
774
774
        }
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"));
787
787
 
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')"));
792
 
 
793
 
                if (display_in_cyl_units)
794
 
                        fprintf(stderr, _(" and change display units to\n"
795
 
"         sectors (command 'u').\n"));
796
 
                else
797
 
                        fprintf(stderr, ".\n");
798
 
 
799
 
         } else if (display_in_cyl_units)
 
791
"         switch off the mode (with command 'c')."));
 
792
 
 
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"));
929
923
                return;
930
924
 
931
925
        dos_write_mbr_id(MBRbuffer, new_id);
 
926
        MBRbuffer_changed = 1;
932
927
        dos_print_mbr_id();
933
928
}
934
929
 
1114
1109
 
1115
1110
void
1116
1111
get_geometry(int fd, struct geom *g) {
1117
 
        unsigned long long llcyls;
 
1112
        unsigned long long llcyls, nsects = 0;
1118
1113
 
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;
1135
1129
 
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));
1138
1133
 
1139
1134
        update_sector_offset();
1140
1135
 
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;
1162
1157
        if (MBRbuffer)
1163
1158
                return;
1164
1159
 
1165
 
        MBRbuffer = calloc(1, MAX_SECTOR_SIZE);
1166
 
        if (!MBRbuffer)
1167
 
                fatal(out_of_memory);
 
1160
        MBRbuffer = xcalloc(1, MAX_SECTOR_SIZE);
1168
1161
}
1169
1162
 
1170
1163
void zeroize_mbr_buffer(void)
1205
1198
        if (what == create_empty_dos)
1206
1199
                goto got_dos_table;             /* skip reading disk */
1207
1200
 
1208
 
        if ((fd = open(disk_device, type_open)) < 0) {
1209
 
            if ((fd = open(disk_device, O_RDONLY)) < 0) {
1210
 
                if (what == try_only)
1211
 
                    return 1;
1212
 
                fatal(unable_to_open);
1213
 
            } else
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);
 
1205
                        else
 
1206
                                printf(_("You will not be able to write "
 
1207
                                            "the partition table.\n"));
 
1208
                }
1216
1209
        }
1217
1210
 
1218
1211
        if (512 != read(fd, MBRbuffer, 512)) {
1306
1299
        return 0;
1307
1300
}
1308
1301
 
 
1302
static int is_partition_table_changed(void)
 
1303
{
 
1304
        int i;
 
1305
 
 
1306
        for (i = 0; i < partitions; i++)
 
1307
                if (ptes[i].changed)
 
1308
                        return 1;
 
1309
        return 0;
 
1310
}
 
1311
 
 
1312
static void maybe_exit(int rc, int *asked)
 
1313
{
 
1314
        char line[LINE_LENGTH];
 
1315
 
 
1316
        putchar('\n');
 
1317
        if (asked)
 
1318
                *asked = 0;
 
1319
 
 
1320
        if (is_partition_table_changed() || MBRbuffer_changed) {
 
1321
                fprintf(stderr, _("Do you really want to quit? "));
 
1322
 
 
1323
                if (!fgets(line, LINE_LENGTH, stdin) || rpmatch(line) == 1)
 
1324
                        exit(rc);
 
1325
                if (asked)
 
1326
                        *asked = 1;
 
1327
        } else
 
1328
                exit(rc);
 
1329
}
 
1330
 
1309
1331
/* read line; return 0 or first char */
1310
1332
int
1311
 
read_line(void)
 
1333
read_line(int *asked)
1312
1334
{
1313
 
        static int got_eof = 0;
1314
 
 
1315
1335
        line_ptr = line_buffer;
1316
1336
        if (!fgets(line_buffer, LINE_LENGTH, stdin)) {
1317
 
                if (feof(stdin))
1318
 
                        got_eof++;      /* user typed ^D ? */
1319
 
                if (got_eof >= 3) {
1320
 
                        fflush(stdout);
1321
 
                        fprintf(stderr, _("\ngot EOF thrice - exiting..\n"));
1322
 
                        exit(1);
1323
 
                }
 
1337
                maybe_exit(1, asked);
1324
1338
                return 0;
1325
1339
        }
 
1340
        if (asked)
 
1341
                *asked = 0;
1326
1342
        while (*line_ptr && !isgraph(*line_ptr))
1327
1343
                line_ptr++;
1328
1344
        return *line_ptr;
1334
1350
        do {
1335
1351
                fputs(mesg, stdout);
1336
1352
                fflush (stdout);         /* requested by niles@scyld.com */
1337
 
        } while (!read_line());
 
1353
        } while (!read_line(NULL));
1338
1354
        return *line_ptr;
1339
1355
}
1340
1356
 
1341
1357
char
1342
1358
read_chars(char *mesg)
1343
1359
{
1344
 
        fputs(mesg, stdout);
1345
 
        fflush (stdout);        /* niles@scyld.com */
1346
 
        if (!read_line()) {
 
1360
        int rc, asked = 0;
 
1361
 
 
1362
        do {
 
1363
                fputs(mesg, stdout);
 
1364
                fflush (stdout);        /* niles@scyld.com */
 
1365
                rc = read_line(&asked);
 
1366
        } while (asked);
 
1367
 
 
1368
        if (!rc) {
1347
1369
                *line_ptr = '\n';
1348
1370
                line_ptr[1] = 0;
1349
1371
        }
1382
1404
 
1383
1405
        if (!ms || strlen(mesg)+100 > mslen) {
1384
1406
                mslen = strlen(mesg)+200;
1385
 
                if (!(ms = realloc(ms,mslen)))
1386
 
                        fatal(out_of_memory);
 
1407
                ms = xrealloc(ms,mslen);
1387
1408
        }
1388
1409
 
1389
1410
        if (dflt < low || dflt > high)
1511
1532
 
1512
1533
 
1513
1534
int
1514
 
get_partition(int warn, int max) {
 
1535
get_partition_dflt(int warn, int max, int dflt) {
1515
1536
        struct pte *pe;
1516
1537
        int i;
1517
1538
 
1518
 
        i = read_int(1, 0, max, 0, _("Partition number")) - 1;
 
1539
        i = read_int(1, dflt, max, 0, _("Partition number")) - 1;
1519
1540
        pe = &ptes[i];
1520
1541
 
1521
1542
        if (warn) {
1532
1553
        return i;
1533
1554
}
1534
1555
 
 
1556
int
 
1557
get_partition(int warn, int max) {
 
1558
        return get_partition_dflt(warn, max, 0);
 
1559
}
 
1560
 
1535
1561
static int
1536
1562
get_existing_partition(int warn, int max) {
1537
1563
        int pno = -1;
1562
1588
get_nonexisting_partition(int warn, int max) {
1563
1589
        int pno = -1;
1564
1590
        int i;
 
1591
        int dflt = 0;
1565
1592
 
1566
1593
        for (i = 0; i < max; i++) {
1567
1594
                struct pte *pe = &ptes[i];
1568
1595
                struct partition *p = pe->part_table;
1569
1596
 
1570
1597
                if (p && is_cleared_partition(p)) {
1571
 
                        if (pno >= 0)
 
1598
                        if (pno >= 0) {
 
1599
                                dflt = pno + 1;
1572
1600
                                goto not_unique;
 
1601
                        }
1573
1602
                        pno = i;
1574
1603
                }
1575
1604
        }
1581
1610
        return -1;
1582
1611
 
1583
1612
 not_unique:
1584
 
        return get_partition(warn, max);
 
1613
        return get_partition_dflt(warn, max, dflt);
1585
1614
}
1586
1615
 
1587
1616
const char *
1596
1625
{
1597
1626
        display_in_cyl_units = !display_in_cyl_units;
1598
1627
        update_units();
1599
 
        printf(_("Changing display/entry units to %s\n"),
1600
 
                str_units(PLURAL));
 
1628
 
 
1629
        if (display_in_cyl_units)
 
1630
                printf(_("Changing display/entry units to cylinders (DEPRECATED!)\n"));
 
1631
        else
 
1632
                printf(_("Changing display/entry units to sectors\n"));
1601
1633
}
1602
1634
 
1603
1635
static void
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"));
1621
1653
        else
1622
1654
                printf(_("DOS Compatibility flag is not set\n"));
1623
1655
 
1785
1817
 * Lubkin Oct.  1991). */
1786
1818
 
1787
1819
static void
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;
1790
1822
 
1791
1823
        *c = ls / spc;
1870
1902
 
1871
1903
static void
1872
1904
list_disk_geometry(void) {
1873
 
        long long bytes = (total_number_of_sectors << 9);
 
1905
        unsigned long long bytes = total_number_of_sectors * sector_size;
1874
1906
        long megabytes = bytes/1000000;
1875
1907
 
1876
1908
        if (megabytes < 10000)
1878
1910
                       disk_device, megabytes, bytes);
1879
1911
        else {
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);
1883
1915
        }
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);
1889
1920
        printf("\n");
1890
1921
        printf(_("Units = %s of %d * %d = %d bytes\n"),
1891
1922
               str_units(PLURAL),
2194
2225
verify(void) {
2195
2226
        int i, j;
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;
2200
2231
 
2308
2339
                if (display_in_cyl_units || !total_number_of_sectors)
2309
2340
                        llimit = heads * sectors * cylinders - 1;
2310
2341
                else
2311
 
                        llimit = (total_number_of_sectors / sector_factor) - 1;
 
2342
                        llimit = total_number_of_sectors - 1;
2312
2343
                limit = llimit;
2313
2344
                if (limit != llimit)
2314
2345
                        limit = 0x7fffffff;
2424
2455
                ext_index = n;
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];
2440
2470
 
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;
2537
2566
        int i;
2538
2567
 
2539
2568
        if (dos_label) {
2540
 
                for (i=0; i<3; i++)
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;
 
2574
                }
 
2575
                if (MBRbuffer_changed) {
 
2576
                        write_part_table_flag(MBRbuffer);
 
2577
                        write_sector(fd, 0, MBRbuffer);
 
2578
                }
 
2579
                /* EBR (logical partitions) */
 
2580
                for (i = 4; i < partitions; i++) {
2544
2581
                        struct pte *pe = &ptes[i];
2545
2582
 
2546
2583
                        if (pe->changed) {
2643
2680
move_begin(int i) {
2644
2681
        struct pte *pe = &ptes[i];
2645
2682
        struct partition *p = pe->part_table;
2646
 
        unsigned int new, first;
 
2683
        unsigned int new, free_start, curr_start, last;
 
2684
        int x;
2647
2685
 
2648
2686
        if (warn_geometry())
2649
2687
                return;
2651
2689
                printf(_("Partition %d has no data area\n"), i + 1);
2652
2690
                return;
2653
2691
        }
2654
 
        first = get_partition_start(pe);
2655
 
        new = read_int(first, first, first + get_nr_sects(p) - 1, first,
 
2692
 
 
2693
        /* the default start is at the second sector of the disk or at the
 
2694
         * second sector of the extended partition
 
2695
         */
 
2696
        free_start = pe->offset ? pe->offset + 1 : 1;
 
2697
 
 
2698
        curr_start = get_partition_start(pe);
 
2699
 
 
2700
        /* look for a free space before the current start of the partition */
 
2701
        for (x = 0; x < partitions; x++) {
 
2702
                unsigned int end;
 
2703
                struct pte *prev_pe = &ptes[x];
 
2704
                struct partition *prev_p = prev_pe->part_table;
 
2705
 
 
2706
                if (!prev_p)
 
2707
                        continue;
 
2708
                end = get_partition_start(prev_pe) + get_nr_sects(prev_p);
 
2709
 
 
2710
                if (!is_cleared_partition(prev_p) &&
 
2711
                    end > free_start && end <= curr_start)
 
2712
                        free_start = end;
 
2713
        }
 
2714
 
 
2715
        last = get_partition_start(pe) + get_nr_sects(p) - 1;
 
2716
 
 
2717
        new = read_int(free_start, curr_start, last, free_start,
2656
2718
                       _("New beginning of data")) - pe->offset;
2657
2719
 
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;
2663
2725
        }
2845
2907
        int ma, mi;
2846
2908
        unsigned long long sz;
2847
2909
 
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);
2851
2913
                return;
2852
2914
        }
2853
2915
 
2856
2918
                            &ma, &mi, &sz, ptname) != 4)
2857
2919
                        continue;
2858
2920
                snprintf(devname, sizeof(devname), "/dev/%s", ptname);
2859
 
                if (is_whole_disk(devname))
2860
 
                        try(devname, 0);
 
2921
                if (is_whole_disk(devname)) {
 
2922
                        char *cn = canonicalize_path(devname);
 
2923
                        if (cn) {
 
2924
                                try(cn, 0);
 
2925
                                free(cn);
 
2926
                        }
 
2927
                }
2861
2928
        }
2862
2929
        fclose(procpt);
2863
2930
}
2881
2948
        bindtextdomain(PACKAGE, LOCALEDIR);
2882
2949
        textdomain(PACKAGE);
2883
2950
 
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) {
2885
2952
                switch (c) {
2886
2953
                case 'b':
2887
2954
                        /* Ugly: this sector size is really per device,
2891
2958
                        sector_size = atoi(optarg);
2892
2959
                        if (sector_size != 512 && sector_size != 1024 &&
2893
2960
                            sector_size != 2048 && sector_size != 4096)
2894
 
                                fatal(usage);
 
2961
                                usage(stderr);
2895
2962
                        sector_offset = 2;
2896
2963
                        user_set_sector_size = 1;
2897
2964
                        break;
2899
2966
                        user_cylinders = atoi(optarg);
2900
2967
                        break;
2901
2968
                case 'c':
2902
 
                        dos_compatible_flag = 0;
 
2969
                        dos_compatible_flag = 0;        /* default */
 
2970
 
 
2971
                        if (optarg && !strcmp(optarg, "=dos"))
 
2972
                                dos_compatible_flag = ~0;
 
2973
                        else if (optarg && strcmp(optarg, "=nondos"))
 
2974
                                usage(stderr);
2903
2975
                        break;
2904
2976
                case 'h':
2905
 
                        fatal(help);
 
2977
                        usage(stdout);
2906
2978
                        break;
2907
2979
                case 'H':
2908
2980
                        user_heads = atoi(optarg);
2921
2993
                        opts = 1;
2922
2994
                        break;
2923
2995
                case 'u':
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"))
 
3000
                                usage(stderr);
2925
3001
                        break;
2926
3002
                case 'V':
2927
3003
                case 'v':
2928
3004
                        printf("fdisk (%s)\n", PACKAGE_STRING);
2929
3005
                        exit(0);
2930
3006
                default:
2931
 
                        fatal(usage);
 
3007
                        usage(stderr);
2932
3008
                }
2933
3009
        }
2934
3010
 
2970
3046
 
2971
3047
                opts = argc - optind;
2972
3048
                if (opts <= 0)
2973
 
                        fatal(usage);
 
3049
                        usage(stderr);
2974
3050
 
2975
3051
                for (j = optind; j < argc; j++) {
2976
3052
                        disk_device = argv[j];
2990
3066
        if (argc-optind == 1)
2991
3067
                disk_device = argv[optind];
2992
3068
        else
2993
 
                fatal(usage);
 
3069
                usage(stderr);
2994
3070
 
2995
3071
        gpt_warning(disk_device);
2996
3072
        get_boot(fdisk);