← Commit list

c1289d58d

Denys Vlasenko
Denys Vlasenko
2026-09-28
SUCCESS Duration: 297s

Subject

fdisk: add a test of adding a 1-sector primary partition

Binary

No binary (build failed)

Architecture & Compiler Flags

Architecture: x86_64-linux-gnu Compiler: gcc (Ubuntu 11.4.0-1ubuntu1~22.04.3) 11.4.0

—

Build Log

(log yok)

Commit Diff GitHub →

libbb/lineedit.c+2 -1
@@ -2502,8 +2502,8 @@ int FAST_FUNC read_line_input(line_input_t *st, const char *prompt, char *comman
* (example: interactive python ^Z-backgrounded,
* tty is still in "raw mode").
*/
- parse_and_put_prompt(prompt);
fflush_all();
+ parse_and_put_prompt(prompt);
if (fgets(command, maxsize, stdin) == NULL)
len = -1; /* EOF or error */
else
@@ -2548,6 +2548,7 @@ int FAST_FUNC read_line_input(line_input_t *st, const char *prompt, char *comman
#endif
#define command command_must_not_be_used
+ fflush_all();
tcsetattr_stdin_TCSANOW(&new_settings);
#if 0
testsuite/fdisk.tests+43 -0
@@ -0,0 +1,43 @@
+#!/bin/sh
+
+# Copyright 2026 by Denys Vlasenko <[email protected]>
+# Licensed under GPLv2, see file LICENSE in this source tree.
+
+. ./testing.sh
+
+# testing "description" "command" "result" "infile" "stdin"
+
+# We require -u for this test to disable use of incorrectly guessed
+# sectors-per-track (15, should be 16).
+# utili-linux 2.41.1 does not - did they change the default?
+testing 'fdisk -u fdisk_8k_parts1_5-11_ext14.raw add primary' \
+ 'fdisk -u fdisk_8k_parts1_5-11_ext14.raw 2>&1' \
+ "\
+Changes will remain in memory only, until you decide to write them.
+Be careful before using the write command.
+
+Command (m for help): Partition type
+ p primary (1-4)
+ l logical (5+)
+Partition number (1-4):
+Command (m for help): Command (m for help): Disk fdisk_8k_parts1_5-11_ext14.raw: 8192, 8192 bytes, 16 sectors
+1 cylinders, 1 heads, 15 sectors/track
+Units: sectors of 1 * 512 = 512 bytes
+
+Device Boot StartCHS EndCHS StartLBA EndLBA Sectors Size Id Type
+fdisk_8k_parts1_5-11_ext14.raw1 0,0,2 0,0,15 1 14 14 7168 5 Extended
+fdisk_8k_parts1_5-11_ext14.raw2 1,0,1 1,0,1 15 15 1 512 83 Linux
+fdisk_8k_parts1_5-11_ext14.raw5 0,0,3 0,0,3 2 2 1 512 83 Linux
+fdisk_8k_parts1_5-11_ext14.raw6 0,0,5 0,0,5 4 4 1 512 83 Linux
+fdisk_8k_parts1_5-11_ext14.raw7 0,0,7 0,0,7 6 6 1 512 83 Linux
+fdisk_8k_parts1_5-11_ext14.raw8 0,0,9 0,0,9 8 8 1 512 83 Linux
+fdisk_8k_parts1_5-11_ext14.raw9 0,0,11 0,0,11 10 10 1 512 83 Linux
+fdisk_8k_parts1_5-11_ext14.raw10 0,0,13 0,0,13 12 12 1 512 83 Linux
+fdisk_8k_parts1_5-11_ext14.raw11 0,0,15 0,0,15 14 14 1 512 83 Linux
+
+Command (m for help): " \
+ '' \
+ 'n''\n''p''\n''2''\n''\n''p''\n'
+# n(create),p(primary),2,(agree to default start sector [this could be suppressed, since there is ony one choice:15]),p(print)
+
+exit $FAILCOUNT
?+0 -0
?+0 -0
testsuite/fdisk_8k_parts1_5-11_ext15.txt+26 -0
@@ -0,0 +1,26 @@
+This is an example disk image created via:
+ dd bs=1K count=8 </dev/zero >IMAGE
+ fdisk IMAGE
+then creating extended partition on the whole disk,
+then creating one-sector-sized logical partitions,
+up to partition 11.
+Every logical partition was filled by data in QEMU via
+ yes "part 05" >/dev/sda5
+and similar commands.
+
+This image, if mounted by linux, will have extended partition
+visible as 1024-byte /dev/sda1 partition, which also
+includes /dev/sda5 first (and only) sector -
+kernel does not check for overlap!
+
+The last link sector of extended partition chain, one just before
+partition 11, has only data pointer, no "next ext" pointer.
+There is an unused sector at the end. It is meant to be this
+"next ext" pointer if further logical partitions were to be created
+(and if the disk would have space for them).
+
+It is possible to use the last sector for a primary partition.
+The extended partition needs to resized ('e','1') to 14 sectors:
+'7168' in util-linux 2.41.1 works. In fact, you can resize it
+down to 1 sector (0 does not work, kernel will ignore it).
+Then you can create a primary partition in sector 15.
util-linux/fdisk.c+43 -13
@@ -81,6 +81,7 @@
//usage:#define fdisk_full_usage "\n\n"
//usage: IF_FEATURE_FDISK_WRITABLE("Change")IF_NOT_FEATURE_FDISK_WRITABLE("Show")" partition table\n"
//usage: "\n -u Start and End are in sectors (instead of cylinders)"
+//usage: "\n Also disable rounding of sizes to cylinders"
//usage: "\n -l Show partition table for each DISK and exit"
//usage: IF_FEATURE_FDISK_BLKSIZE(
//usage: "\n -s Show size in kb for each DISK and exit"
@@ -108,6 +109,12 @@
# define BLKGETSIZE64 _IOR(0x12,114,size_t)
#endif
+#if 0
+# define dbg(...) bb_error_msg(__VA_ARGS__)
+#else
+# define dbg(...) ((void)0)
+#endif
+
/* Get device geometry in this struct: */
#define HDIO_GETGEO 0x0301
struct hd_geometry {
@@ -1118,7 +1125,7 @@ get_partition_table_geometry(void)
p = pt_offset(bufp, i);
if (!is_cleared_partition(p)) {
h = p->end_head + 1;
- s = (p->end_sector & 077);
+ s = (p->end_sector & 0x3f);
if (first) {
hh = h;
ss = s;
@@ -1318,14 +1325,18 @@ static sector_t
read_int(sector_t low, sector_t dflt, sector_t high, sector_t base, const char *mesg)
{
sector_t value;
- int default_ok = 1;
- const char *fmt = "%s (%u-%u, default %u): ";
+ int default_ok;
+ const char *fmt;
+
+ if (low == high) // no need to ask
+ return low;
+ default_ok = 1;
+ fmt = "%s (%u-%u, default %u): ";
if (dflt < low || dflt > high) {
fmt = "%s (%u-%u): ";
default_ok = 0;
}
-
while (1) {
int use_default = default_ok;
@@ -2201,6 +2212,7 @@ verify(void)
struct pte *pe = &ptes[i];
p = pe->part_table;
+//TODO: warn about EXTENDED partitions with nr_sect==0? Kernel will ignore these (requires at least 1)
if (!is_cleared_partition(p) && !IS_EXTENDED(p->sys_ind)) {
check_consistency(p, i);
if (get_partition_start_from_dev_start(pe) < first[i])
@@ -2317,17 +2329,22 @@ add_partition(int n, int sys)
main_ext = ptes[ext_index].part_table;
if (n < 4) {
start = offset_after_MBR_and_ext;
- if (DISPLAY_IN_CYL_UNITS || !total_number_of_sectors)
+ if (DISPLAY_IN_CYL_UNITS || !total_number_of_sectors) {
limit = (sector_t) g_heads * g_sectors * g_cylinders - 1;
- else
+ dbg("%d: limit:%d", __LINE__, limit);
+ } else {
limit = total_number_of_sectors - 1;
+ dbg("%d: limit:%d", __LINE__, limit);
+ }
if (extended_offset) {
first[ext_index] = extended_offset;
last[ext_index] = extended_offset + get_nr_sects(main_ext) - 1;
}
+ dbg("%d: start:%d limit:%d", __LINE__, start, limit);
} else {
start = extended_offset + offset_after_MBR_and_ext;
limit = extended_offset + get_nr_sects(main_ext) - 1;
+ dbg("%d: start:%d limit:%d", __LINE__, start, limit);
}
if (DISPLAY_IN_CYL_UNITS)
for (i = 0; i < g_partitions; i++)
@@ -2338,13 +2355,17 @@ add_partition(int n, int sys)
do {
temp = start;
for (i = 0; i < g_partitions; i++) {
- int lastplusoff;
+ sector_t lastplusoff;
- if (start == ptes[i].offset_from_dev_start)
+ if (start == ptes[i].offset_from_dev_start) {
start += offset_after_MBR_and_ext;
+ dbg("%d: start:%d", __LINE__, start);
+ }
lastplusoff = last[i] + ((n < 4) ? 0 : offset_after_MBR_and_ext);
- if (start >= first[i] && start <= lastplusoff)
+ if (start >= first[i] && start <= lastplusoff) {
start = lastplusoff + 1;
+ dbg("%d: start:%d", __LINE__, start);
+ }
}
if (start > limit)
break;
@@ -2360,8 +2381,11 @@ add_partition(int n, int sys)
start = read_int(cround(saved_start), cround(saved_start), cround(limit), 0, mesg);
if (DISPLAY_IN_CYL_UNITS) {
start = (start - 1) * units_per_sector;
- if (start < saved_start)
+ dbg("%d: start:%d", __LINE__, start);
+ if (start < saved_start) {
start = saved_start;
+ dbg("%d: start:%d", __LINE__, start);
+ }
}
num_read = 1;
}
@@ -2373,18 +2397,24 @@ add_partition(int n, int sys)
pe->offset_from_dev_start = start - offset_after_MBR_and_ext;
if (pe->offset_from_dev_start == extended_offset) { /* must be corrected */
pe->offset_from_dev_start++;
- if (offset_after_MBR_and_ext == 1)
+ if (offset_after_MBR_and_ext == 1) {
start++;
+ dbg("%d: ++start:%d", __LINE__, start);
+ }
}
}
for (i = 0; i < g_partitions; i++) {
struct pte *pe = &ptes[i];
- if (start < pe->offset_from_dev_start && limit >= pe->offset_from_dev_start)
+ if (start < pe->offset_from_dev_start && limit >= pe->offset_from_dev_start) {
limit = pe->offset_from_dev_start - 1;
- if (start < first[i] && limit >= first[i])
+ dbg("%d: limit:%d", __LINE__, limit);
+ }
+ if (start < first[i] && limit >= first[i]) {
limit = first[i] - 1;
+ dbg("%d: limit:%d", __LINE__, limit);
+ }
}
if (start > limit) {
puts("No free sectors available");