Toby Betts Public domain. Like any other piece of software (and information generally), this patch comes with NO WARRANTY. --- Overview --- TempleOS includes a very basic FAT32 kernel driver. While the FAT32 file system adds backwards-compatible support for long file names (LFNs) allowing a file name to contain up to 255 characters, the TempleOS FAT32 driver only allows at most 26 characters. This patch edits the default TempleOS FAT32 kernel driver to extend the maximum permitted file name length to 39 characters, which *includes the '\0' null byte* at the end of the file name's C string array. --- What This Patch Does --- The TempleOS FAT32 implementation is very minimal and I find patching it to be incredibly finicky. In order to add one additional LFN record to a file on FAT32 in TempleOS requires (1) making changes to the maximum permitted file name length in the TempleOS kernel, (2) disabling all support for the preferred RedSea TempleOS file system, and (3) carefully extending the "fat_long_name_map" logic in /Kernel/BlkDev/FileSysFAT.HC to handle files with names between 26 and 39 characters. --- Installation --- This is a standard patch-format file and uses the common UNIX/Linux patch(1) utility. Copy this file to an installed TempleOS host -- a shared-partition, dual-boot setup is recommended, see Notes for details -- and run the following commands. Assuming the TempleOS partition is "/dev/sda1": 1. Mount the TempleOS partition from UNIX or Linux: mount -o noatime /dev/sda1 /mnt/sda1 cd /mnt/sda1 2. Check that the patch will apply cleanly without making any changes to your system: patch -p1 --dry-run < /path/to/patch Confirm that no patch hunks report as failing or would be rejected. Do not continue without correcting all errors. If the patch applies cleanly, proceed to the next step. 3. Run the patch utility to apply the changes: patch -p1 < /path/to/calm.patch 4. Boot TempleOS and make a backup of your existing kernel: Copy("/Kernel.BIN.C","/Kernel.BIN.BAK"); 5. Compile a new kernel to accept the changes made to the kernel header file. Follow the interactive kernel compiling process: BootHDIns; 6. Repair your bootloader (as needed). --- Notes --- Related information you might find useful: - Shared-partition, dual-boot TempleOS setup: "The Cathedral and the Bizarre, or Dual-Booting for Fun and Prophet" --- Version History --- 2025-03-03, v.1.0 - initial release --- old/Kernel/BlkDev/FileSysFAT.HC +++ new/Kernel/BlkDev/FileSysFAT.HC @@ -184,6 +184,8 @@ offset(CFAT32DirEntryLong.name3)+2 }; +#define FAT32_VFAT_LEN 13 + Bool DirLongNameFill(CDirEntry *tmpde,CFAT32DirEntryLong *de,I64 *xsum) { I64 i; @@ -198,13 +200,18 @@ } switch (de->ord&0x3F) { case 1: - for (i=0;i<13;i++) + for (i=0;iname[i]=ptr[fat_long_name_map[i]])) return TRUE; break; case 2: - for (i=0;i<12;i++) - if (!(tmpde->name[i+13]=ptr[fat_long_name_map[i]])) + for (i=0;iname[i+FAT32_VFAT_LEN]=ptr[fat_long_name_map[i]])) + return TRUE; + break; + case 3: + for (i=0;iname[i+2*FAT32_VFAT_LEN]=ptr[fat_long_name_map[i]])) return TRUE; break; } @@ -240,21 +247,38 @@ if (StrCmp(dname,tmpde->name)) { ord=0x41; xsum=FATNameXSum(de->name); - if ((l=StrLen(tmpde->name))>13) { + l=StrLen(tmpde->name); + if (l>2*FAT32_VFAT_LEN) { + ptr=&ld[de_cnt]; + MemSet(ptr,0,sizeof(CFAT32DirEntryLong)); + ld[de_cnt].attr=RS_ATTR_LONG_NAME; + ld[de_cnt].xsum=xsum; + ld[de_cnt].ord=0x43; + for (i=2*FAT32_VFAT_LEN;iname[i]; + i++; + for (;i<3*FAT32_VFAT_LEN;i++) + ptr[fat_long_name_map[i-2*FAT32_VFAT_LEN]](U16)=0xFFFF; + ord=1; + l=2*FAT32_VFAT_LEN; + de_cnt++; + } + if (l>FAT32_VFAT_LEN) { ptr=&ld[de_cnt]; MemSet(ptr,0,sizeof(CFAT32DirEntryLong)); ld[de_cnt].attr=RS_ATTR_LONG_NAME; ld[de_cnt].xsum=xsum; - ld[de_cnt].ord=0x42; - for (i=13;iname[i]; + ld[de_cnt].ord=1+ord; + for (i=FAT32_VFAT_LEN;iname[i]; i++; - for (;i<26;i++) - ptr[fat_long_name_map[i-13]](U16)=0xFFFF; + for (;i<2*FAT32_VFAT_LEN;i++) + ptr[fat_long_name_map[i-FAT32_VFAT_LEN]](U16)=0xFFFF; ord=1; - l=13; + l=FAT32_VFAT_LEN; de_cnt++; } + ptr=&de[de_cnt]; MemSet(ptr,0,sizeof(CFAT32DirEntryLong)); ld[de_cnt].attr=RS_ATTR_LONG_NAME; @@ -263,7 +287,7 @@ for (i=0;iname[i]; i++; - for (;i<13;i++) + for (;iname)) { + PrintErr("Invalid File Length: \"%d\".\n",StrLen(tmpde->name)); + return FALSE; + } FAT32DirFill(&de,tmpde,&de_cnt,dv->fat32_local_time_offset); MemSet(&long_name,0,sizeof(CDirEntry)); try { --- old/Kernel/BlkDev/FileSysRedSea.HC +++ new/Kernel/BlkDev/FileSysRedSea.HC @@ -603,7 +603,7 @@ {//entry_cnt is for preallocating dir blks. I64 c,cur_dir_clus=Name2DirClus(dv,cur_dir), size=CeilU64((entry_cnt+3)<<6,BLK_SIZE); -#assert CDIR_SIZE==64 +//#assert CDIR_SIZE==64 U8 *buf=CAlloc(size); CDirEntry *d_native=buf-offset(CDirEntry.start); Bool unlock_break; --- old/Kernel/KernelA.HH +++ new/Kernel/KernelA.HH @@ -2516,7 +2516,7 @@ #help_index "File/Low Level;File/Program Routines" //CDirEntry flags (Used by $LK,"FileMgr",A="MN:FileMgr"$()) -#define CDIR_FILENAME_LEN 38 //Must include terminator zero +#define CDIR_FILENAME_LEN 39 //Must include terminator zero public class CDirEntry { CDirEntry *next,*parent,*sub;