← Commit list

4da3f6df0

Denys Vlasenko
Denys Vlasenko
2026-10-04
SUCCESS Duration: 214s

Subject

fatlabel: require dir_entries = 0 in FAT32 check; fix typos

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 →

networking/tls_aes.c+1 -1
@@ -170,7 +170,7 @@ static int KeyExpansion(uint32_t *RoundKey, const void *key, unsigned key_len)
j = 0;
k++;
//TODO: we can eliminate k and Rcon[] and just generate Rcon[k]?
-//instead of k++, do: Rcon = (Rcon << 1) & ^ ((Rcon & 0x80) ? 0x1b : 0)
+//instead of k++, do: Rcon = (Rcon << 1) ^ ((Rcon & 0x80) ? 0x1b : 0)
}
}
return rounds;
util-linux/fatlabel.c+34 -13
@@ -8,7 +8,7 @@
//config: bool "fatlabel (1 kb)"
//config: default y
//config: help
-//config: fatlabel shows or sets FAT33 label.
+//config: fatlabel shows or sets FAT32 label.
//applet:IF_FATLABEL(APPLET(fatlabel, BB_DIR_SBIN, BB_SUID_DROP))
@@ -75,17 +75,18 @@ struct msdos_dir_entry {
*/
struct msdos_volume_info { // (offsets are relative to start of boot sector)
uint8_t drive_number; // 040 BIOS drive number
- uint8_t reserved; // 041 unused
- uint8_t ext_boot_sign; // 042 0x29 if fields below exist (DOS 3.3+)
+ uint8_t reserved; // 041 'unused'. Linux uses this for 0x01 'mounted now' bit, some WinNT too?
+ uint8_t ext_boot_sign; // 042 0x28 (40) if volume_id32 exists, 0x29 (41) if all three fields below exist (0x29 is 'standard' since DOS 4.0).
uint32_t volume_id32; // 043 volume ID number
char volume_label[11];// 047 volume label
- char fs_type[8]; // 052 typically "FATnn"
+ char fs_type[8]; // 052 typically "FATnn "
} PACKED; // 05a end. Total size 26 (0x1a) bytes
struct msdos_boot_sector {
// We use strcpy to fill both, and gcc-4.4.x complains if they are separate
char boot_jump_and_sys_id[3+8]; //000 short or near jump instruction
- /*char system_id[8];*/ // 003 name - can be used to special case partition manager volumes
+ /*char system_id[8];*/ // 003 usually formatting util's id: "MSDOSn.n", "MSWINn.n", "mkfs.fat", "mkdosfs\0" (ours).
+ // "EXFAT " and "NTFS " are required signatures for those filesystems at this offset
uint16_t bytes_per_sect; // 00b bytes per logical sector
uint8_t sect_per_clust; // 00d sectors/cluster
uint16_t reserved_sect; // 00e reserved sectors (sector offset of 1st FAT relative to volume start)
@@ -104,13 +105,33 @@ struct msdos_boot_sector {
uint32_t fat32_root_cluster; // 02c first cluster in root directory
uint16_t fat32_info_sector; // 030 filesystem info sector (usually 1)
uint16_t fat32_backup_boot; // 032 backup boot sector (usually 6)
- uint32_t reserved2[3]; // 034 unused
+ uint32_t reserved2[3]; // 034 'unused'. 12 bytes of 'boot file name'?
struct msdos_volume_info vi; // 040
char boot_code[0x200 - 0x5a - 2]; // 05a
#define BOOT_SIGN 0xAA55
uint16_t boot_sign; // 1fe
} PACKED;
+// Microsoft's EFI FAT32 specification states that any FAT file system with
+// less than 4085 clusters is FAT12, else any FAT file system with less than
+// 65525 clusters is FAT16, and otherwise it is FAT32. The entry for cluster
+// 0 at the beginning of the FAT must be identical to the media descriptor byte
+// found in the BPB, whereas the entry for cluster 1 reflects the end-of-chain
+// value used by the formatter for cluster chains (0xFFF, 0xFFFF or 0x0FFFFFFF).
+// The entries for cluster numbers 0 and 1 end at a byte boundary even
+// for FAT12, e.g., 0xF9FFFF for media descriptor 0xF9.
+//
+// In practice, FAT12/16 has to have nonzero fat16_sect_per_fat field.
+// (it never needs more than 16 bits for this value, unlike FAT32).
+// If it is zero, it is either not a FAT fs at all, or it is FAT32.
+// Unknown whether converse is true (can small FAT32 fs exist with
+// fat16_sect_per_fat field set to nonzero?).
+//
+// A better field for FAT32 discrimination is dir_entries.
+// By necessity, it has to be nonzero for FAT12/16 (you have to have
+// a non-empty root dir). It does not make sense for FAT32 whose root dir
+// is not fixed size, thus presumably always 0.
+
#define FAT_FSINFO_SIG1 0x41615252
#define FAT_FSINFO_SIG2 0x61417272
struct fat32_fsinfo {
@@ -151,7 +172,7 @@ static int bad_fat32(const struct msdos_boot_sector *boot_blk)
move_from_unaligned16(bytes_per_sect16, &boot_blk->bytes_per_sect);
return ((uint8_t)(boot_blk->fats - 1) > 1 // 0 or >2
|| boot_blk->fat16_sect_per_fat != 0
- // maybe also check boot_blk->dir_entries == 0? It's only for FAT16/12
+ || boot_blk->dir_entries != 0
|| boot_blk->vi.ext_boot_sign != 0x29
|| boot_blk->boot_sign != SWAP_LE16(BOOT_SIGN)
|| bytes_per_sect16 != SWAP_LE16(SECTOR_SIZE)
@@ -179,12 +200,12 @@ int fatlabel_main(int argc UNUSED_PARAM, char **argv)
#if 0
fprintf(stderr,
"0x003: sys_id:'%.8s'\n"
- "0x00b: bytes_per_sect: 0x%04x\n" // 0
- "0x00d: sect_per_clust: 0x%02x\n" // 0
+ "0x00b: bytes_per_sect: 0x%04x\n" // 0x200
+ "0x00d: sect_per_clust: 0x%02x\n"
"0x010: fats: 0x%02x\n" // 1 or 2
- "0x011: dir_entries: 0x%04x\n" // always 0 for FAT32?
+ "0x011: dir_entries: 0x%04x\n" // always !0 for FAT12/16! Always 0 for FAT32?
"0x015: media_byte: 0x%02x\n" // 0xf8 for "hard disk"
- "0x016: fat16_sect_per_fat: 0x%04x\n" // 0
+ "0x016: fat16_sect_per_fat: 0x%04x\n" // Always 0 for FAT32?
"0x028: fat32_flags: 0x%04x\n" // 0,0
"0x02a: fat32_version: 0x%02x,0x%02x\n" // 0,0
"0x030: fat32_info_sector: 0x%04x\n" // always 1?
@@ -206,7 +227,7 @@ int fatlabel_main(int argc UNUSED_PARAM, char **argv)
, boot_blk->fat32_version[0], boot_blk->fat32_version[1]
, FETCH_LE16(boot_blk->fat32_info_sector)
, backup_boot_sect
- , boot_blk->vi.reserved // Linux uses this as "mounted now" bit, some WinNT too?
+ , boot_blk->vi.reserved // Linux uses this for 0x01 "mounted now" bit, some WinNT too?
, boot_blk->vi.ext_boot_sign
, FETCH_LE32(boot_blk->vi.volume_id32) // FIXME: unaligned fetch
, boot_blk->vi.volume_label
@@ -238,7 +259,7 @@ int fatlabel_main(int argc UNUSED_PARAM, char **argv)
sprintf(boot_blk->vi.volume_label, "%-11.11s", argv[1]);
xlseek(fd, 0x047, SEEK_SET);
xwrite(fd, boot_blk->vi.volume_label, 11);
- // Redundant is backup_boot_sect == 0, but no harm done:
+ // Redundant if backup_boot_sect == 0, but no harm done:
xlseek(fd, 0x047 + backup_boot_sect * SECTOR_SIZE, SEEK_SET);
xwrite(fd, boot_blk->vi.volume_label, 11);
} else {