From 23c682a5aa123fdf16e826209eb5aa4461ce744f Mon Sep 17 00:00:00 2001 From: neil Date: Sun, 7 Jun 2015 07:11:44 +0000 Subject: [PATCH] - Implemented ACTION_FORMAT. - Fixed name handling for ACTION_RENAME_DISK (the first character was cut off). - Check that the boot block's sector count is the same as the partition's sector count. This stops a resized partition being mounted before reformatting. git-svn-id: https://svn.aros.org/svn/aros/trunk/AROS@50783 fb15a70f-31f2-0310-bbcc-cdcc74a49acc --- rom/filesys/fat/direntry.c | 36 ++--- rom/filesys/fat/disk.c | 3 +- rom/filesys/fat/fat.c | 310 +++++++++++++++++++++++++++++++++++++++---- rom/filesys/fat/fat.conf | 2 +- rom/filesys/fat/fat_fs.h | 3 +- rom/filesys/fat/fat_protos.h | 31 ++--- rom/filesys/fat/fat_struct.h | 32 ++--- rom/filesys/fat/main.c | 3 + rom/filesys/fat/packet.c | 48 ++++++- 9 files changed, 383 insertions(+), 85 deletions(-) diff --git a/rom/filesys/fat/direntry.c b/rom/filesys/fat/direntry.c index 02b1943afe..7ff4210776 100644 --- a/rom/filesys/fat/direntry.c +++ b/rom/filesys/fat/direntry.c @@ -2,7 +2,7 @@ * fat-handler - FAT12/16/32 filesystem handler * * Copyright © 2006 Marek Szyprowski - * Copyright © 2007-2013 The AROS Development Team + * Copyright © 2007-2015 The AROS Development Team * * This program is free software; you can redistribute it and/or modify it * under the same terms as AROS itself. @@ -79,7 +79,7 @@ LONG GetDirEntry(struct DirHandle *dh, ULONG index, struct DirEntry *de) { return ERROR_OBJECT_NOT_FOUND; } - /* setup the return object */ + /* set up the return object */ de->sb = dh->ioh.sb; de->cluster = dh->ioh.first_cluster; de->index = index; @@ -431,7 +431,6 @@ LONG CreateDirEntry(struct DirHandle *dh, STRPTR name, ULONG namelen, UBYTE attr, ULONG cluster, struct DirEntry *de) { ULONG gap; LONG err; - struct DateStamp ds; D(bug("[fat] creating dir entry (name '"); RawPutChars(name, namelen); bug("' attr 0x%02x cluster %ld)\n", attr, cluster)); @@ -445,11 +444,29 @@ LONG CreateDirEntry(struct DirHandle *dh, STRPTR name, ULONG namelen, return err; /* build the entry */ + FillDirEntry(de, attr, cluster); + + SetDirEntryName(de, name, namelen); + + if ((err = UpdateDirEntry(de)) != 0) { + D(bug("[fat] couldn't update base directory entry, creation failed\n")); + return err; + } + + D(bug("[fat] created dir entry %ld\n", de->index)); + + return 0; +} + +void FillDirEntry(struct DirEntry *de, UBYTE attr, ULONG cluster) { + struct DateStamp ds; + de->e.entry.attr = attr; de->e.entry.nt_res = 0; DateStamp(&ds); - ConvertAROSDate(&ds, &(de->e.entry.create_date), &(de->e.entry.create_time)); + ConvertAROSDate(&ds, &(de->e.entry.create_date), + &(de->e.entry.create_time)); de->e.entry.write_date = de->e.entry.create_date; de->e.entry.write_time = de->e.entry.create_time; de->e.entry.last_access_date = de->e.entry.create_date; @@ -460,17 +477,6 @@ LONG CreateDirEntry(struct DirHandle *dh, STRPTR name, ULONG namelen, de->e.entry.first_cluster_hi = cluster >> 16; de->e.entry.file_size = 0; - - SetDirEntryName(de, name, namelen); - - if ((err = UpdateDirEntry(de)) != 0) { - D(bug("[fat] couldn't update base directory entry, creation failed\n")); - return err; - } - - D(bug("[fat] created dir entry %ld\n", de->index)); - - return 0; } LONG DeleteDirEntry(struct DirEntry *de) { diff --git a/rom/filesys/fat/disk.c b/rom/filesys/fat/disk.c index 5c1f6cb8dc..6c6a5a8611 100644 --- a/rom/filesys/fat/disk.c +++ b/rom/filesys/fat/disk.c @@ -2,7 +2,7 @@ * fat-handler - FAT12/16/32 filesystem handler * * Copyright © 2006 Marek Szyprowski - * Copyright © 2007-2011 The AROS Development Team + * Copyright © 2007-2015 The AROS Development Team * * This program is free software; you can redistribute it and/or modify it * under the same terms as AROS itself. @@ -228,7 +228,6 @@ void DoDiskInsert(void) { } sb->info = vol_info; - glob->sb = sb; glob->last_num = -1; if (dl != NULL) diff --git a/rom/filesys/fat/fat.c b/rom/filesys/fat/fat.c index a64cf58ab4..664693af52 100644 --- a/rom/filesys/fat/fat.c +++ b/rom/filesys/fat/fat.c @@ -20,6 +20,8 @@ #include #include #include +#include +#include #include @@ -32,6 +34,27 @@ #define DEBUG DEBUG_MISC #include "debug.h" +static const UBYTE default_oem_name[] = "MSWIN4.1"; +static const UBYTE default_filsystype[] = "FAT16 "; + +static const ULONG fat16_cluster_thresholds[] = +{ + 8400, + 32680, + 262144, + 524288, + 1048576, + 0xFFFFFFFF +}; + +static const ULONG fat32_cluster_thresholds[] = +{ + 16777216, + 33554432, + 67108864, + 0xFFFFFFFF +}; + /* helper function to get the location of a fat entry for a cluster. it used * to be a define until it got too crazy */ static UBYTE *GetFatEntryPtr(struct FSSuper *sb, ULONG offset, APTR *rb, @@ -203,11 +226,17 @@ static void SetFat32Entry(struct FSSuper *sb, ULONG n, ULONG val) { LONG ReadFATSuper(struct FSSuper *sb ) { struct DosEnvec *de = BADDR(glob->fssm->fssm_Environ); LONG err; - ULONG bsize = de->de_SizeBlock * 4; + ULONG bsize = de->de_SizeBlock * 4, total_sectors; struct FATBootSector *boot; + struct FATEBPB *ebpb; struct FATFSInfo *fsinfo; BOOL invalid = FALSE; ULONG end; + LONG i; + struct DirHandle dh; + struct DirEntry dir_entry; + APTR block_ref; + UBYTE *fat_block; D(bug("[fat] reading boot sector\n")); @@ -215,17 +244,23 @@ LONG ReadFATSuper(struct FSSuper *sb ) { if (!boot) return ERROR_NO_FREE_STORE; + sb->first_device_sector = + de->de_BlocksPerTrack * de->de_Surfaces * de->de_LowCyl; + + /* Get a preliminary total-sectors value so we don't risk going outside + * partition limits */ + sb->total_sectors = + de->de_BlocksPerTrack * de->de_Surfaces * (de->de_HighCyl + 1) + - sb->first_device_sector; + + D(bug("[fat] boot sector at sector %ld\n", sb->first_device_sector)); + /* * Read the boot sector. We go direct because we don't have a cache yet, * and can't create one until we know the sector size, which is held in * the boot sector. In practice it doesn't matter - we're going to use * this once and once only. */ - sb->first_device_sector = - de->de_BlocksPerTrack * de->de_Surfaces * de->de_LowCyl; - - D(bug("[fat] boot sector at sector %ld\n", sb->first_device_sector)); - if ((err = AccessDisk(FALSE, sb->first_device_sector, 1, bsize, (UBYTE *)boot)) != 0) { D(bug("[fat] couldn't read boot block (%ld)\n", err)); FreeMem(boot, bsize); @@ -258,15 +293,21 @@ LONG ReadFATSuper(struct FSSuper *sb ) { if (boot->bpb_fat_size_16 != 0) sb->fat_size = AROS_LE2WORD(boot->bpb_fat_size_16); else - sb->fat_size = AROS_LE2LONG(boot->type.fat32.bpb_fat_size_32); + sb->fat_size = AROS_LE2LONG(boot->ebpbs.ebpb32.bpb_fat_size_32); D(bug("\tFAT Size = %ld\n", sb->fat_size)); if (boot->bpb_total_sectors_16 != 0) - sb->total_sectors = AROS_LE2WORD(boot->bpb_total_sectors_16); + total_sectors = AROS_LE2WORD(boot->bpb_total_sectors_16); else - sb->total_sectors = AROS_LE2LONG(boot->bpb_total_sectors_32); + total_sectors = AROS_LE2LONG(boot->bpb_total_sectors_32); D(bug("\tTotal Sectors = %ld\n", sb->total_sectors)); + /* Check that the boot block's sector count is the same as the + * partition's sector count. This stops a resized partition being + * mounted before reformatting */ + if (total_sectors != sb->total_sectors) + invalid = TRUE; + sb->rootdir_sectors = ((AROS_LE2WORD(boot->bpb_root_entries_count) * sizeof(struct FATDirEntry)) + (sb->sectorsize - 1)) >> sb->sectorsize_bits; D(bug("\tRootDir Sectors = %ld\n", sb->rootdir_sectors)); @@ -344,6 +385,7 @@ LONG ReadFATSuper(struct FSSuper *sb ) { sb->func_get_fat_entry = GetFat32Entry; sb->func_set_fat_entry = SetFat32Entry; } + glob->sb = sb; /* setup the FAT cache and load the first blocks */ sb->fat_cachesize = 4096; @@ -359,27 +401,72 @@ LONG ReadFATSuper(struct FSSuper *sb ) { if (sb->type != 32) { /* FAT 12/16 */ /* setup volume id */ - sb->volume_id = AROS_LE2LONG(boot->type.fat16.bs_volid); + sb->volume_id = AROS_LE2LONG(boot->ebpbs.ebpb.bs_volid); /* location of root directory */ sb->rootdir_cluster = 0; sb->rootdir_sector = sb->first_rootdir_sector; + ebpb = &boot->ebpbs.ebpb; } else { /* setup volume id */ - sb->volume_id = AROS_LE2LONG(boot->type.fat32.bs_volid); + sb->volume_id = AROS_LE2LONG(boot->ebpbs.ebpb32.ebpb.bs_volid); /* location of root directory */ - sb->rootdir_cluster = AROS_LE2LONG(boot->type.fat32.bpb_root_cluster); + sb->rootdir_cluster = AROS_LE2LONG(boot->ebpbs.ebpb32.bpb_root_cluster); sb->rootdir_sector = 0; + ebpb = &boot->ebpbs.ebpb32.ebpb; } D(bug("[fat] rootdir at cluster %ld sector %ld\n", sb->rootdir_cluster, sb->rootdir_sector)); + /* Initialise the root directory if this is a newly formatted volume */ + if (glob->formatting) + { + /* Clear all FAT sectors */ + for (i = 0; i < sb->fat_size * 2; i++) { + block_ref = Cache_GetBlock(sb->cache, + sb->first_device_sector + sb->first_fat_sector + i, + &fat_block); + memset(fat_block, 0, bsize); + if (i == 0) { + /* The first two entries are special */ + if (sb->type == 32) + *(UQUAD *)fat_block = AROS_QUAD2LE(0x0FFFFFFF0FFFFFF8); + else if (sb->type == 16) + *(ULONG *)fat_block = AROS_LONG2LE(0xFFFFFFF8); + else + *(ULONG *)fat_block = AROS_LONG2LE(0x00FFFFF8); + } + Cache_MarkBlockDirty(sb->cache, block_ref); + Cache_FreeBlock(sb->cache, block_ref); + } + + /* allocate first cluster of the root directory */ + if (sb->type == 32) + AllocCluster(sb, sb->rootdir_cluster); + + /* get a handle on the root directory */ + InitDirHandle(sb, 0, &dh, FALSE); + + /* clear all entries */ + for (i = 0; GetDirEntry(&dh, i, &dir_entry) == 0; i++) { + memset(&dir_entry.e.entry, 0, sizeof(struct FATDirEntry)); + UpdateDirEntry(&dir_entry); + } + + SetVolumeName(sb, ebpb->bs_vollab, 11); + + ReleaseDirHandle(&dh); + glob->formatting = FALSE; + D(bug("\tRoot dir created.\n")); + } + if (GetVolumeIdentity(sb, &(sb->volume)) != 0) { LONG i; UBYTE *uu = (void *)&sb->volume_id; + /* No volume name entry, so construct name from serial number */ for (i=1; i<10;) { int d; @@ -403,7 +490,7 @@ LONG ReadFATSuper(struct FSSuper *sb ) { sb->next_cluster = -1; if (sb->type == 32) { sb->fsinfo_block = Cache_GetBlock(sb->cache, sb->first_device_sector - + AROS_LE2WORD(boot->type.fat32.bpb_fs_info), (UBYTE **)&fsinfo); + + AROS_LE2WORD(boot->ebpbs.ebpb32.bpb_fs_info), (UBYTE **)&fsinfo); if (sb->fsinfo_block != NULL) { if (fsinfo->lead_sig == AROS_LONG2LE(FSI_LEAD_SIG) && fsinfo->struct_sig == AROS_LONG2LE(FSI_STRUCT_SIG) @@ -484,7 +571,181 @@ LONG GetVolumeIdentity(struct FSSuper *sb, struct VolumeIdentity *volume) { return err; } -LONG SetVolumeName(struct FSSuper *sb, UBYTE *name) { +LONG FormatFATVolume(const UBYTE *name, UWORD len) { + struct DosEnvec *de = BADDR(glob->fssm->fssm_Environ); + LONG err; + ULONG bsize = de->de_SizeBlock * 4; + struct FATBootSector *boot; + struct FATEBPB *ebpb; + struct FATFSInfo *fsinfo; + UWORD type, i, root_entries_count; + struct EClockVal eclock; + ULONG sectors_per_cluster = 0, sector_count, first_fat_sector, + fat_size, root_dir_sectors, first_device_sector, temp1, temp2; + + /* Decide on FAT type based on number of sectors */ + sector_count = (de->de_HighCyl - de->de_LowCyl + 1) + * de->de_Surfaces * de->de_BlocksPerTrack; + if (sector_count < 4085) + type = 12; + else if (sector_count < 1024 * 1024) + type = 16; + else + type = 32; + + D(bug("[fat] writing boot sector\n")); + + /* Decide on cluster size and root dir entries */ + first_fat_sector = 1; + if (type == 12) { + if (sector_count == 1440) { + sectors_per_cluster = 2; + root_entries_count = 112; + } else if (sector_count == 2880) { + sectors_per_cluster = 1; + root_entries_count = 224; + } else if (sector_count == 5760) { + sectors_per_cluster = 2; + root_entries_count = 240; + } else { + /* We only support some common 3.5" floppy formats */ + return ERROR_NOT_IMPLEMENTED; + } + } else if (type == 16) { + for (i = 0; fat16_cluster_thresholds[i] < sector_count; i++); + sectors_per_cluster = 1 << i; + root_entries_count = 512; + } else { + for (i = 0; fat32_cluster_thresholds[i] < sector_count; i++); + sectors_per_cluster = 8 << i; + root_entries_count = 0; + first_fat_sector = 32; + } + + D(bug("\tFirst FAT Sector = %ld\n", first_fat_sector)); + + /* Determine FAT size */ + root_dir_sectors = (root_entries_count * 32 + (bsize - 1)) / bsize; + temp1 = sector_count - (first_fat_sector + root_dir_sectors); + temp2 = 256 * sectors_per_cluster + 2; + if (type == 32) + temp2 /= 2; + fat_size = (temp1 + temp2 - 1) / temp2; + + boot = AllocMem(bsize, MEMF_CLEAR); + if (!boot) + return ERROR_NO_FREE_STORE; + + /* Install x86 infinite loop boot code to keep major OSes happy */ + boot->bs_jmp_boot[0] = 0xEB; + boot->bs_jmp_boot[1] = 0xFE; + boot->bs_jmp_boot[2] = 0x90; + + CopyMem(default_oem_name, boot->bs_oem_name, 8); + + boot->bpb_bytes_per_sect = AROS_WORD2LE(bsize); + boot->bpb_sect_per_clust = sectors_per_cluster; + + boot->bpb_rsvd_sect_count = AROS_WORD2LE(first_fat_sector); + + boot->bpb_num_fats = 2; + + boot->bpb_root_entries_count = AROS_WORD2LE(root_entries_count); + + if (sector_count < 0x10000 && type != 32) + boot->bpb_total_sectors_16 = AROS_WORD2LE(sector_count); + else + boot->bpb_total_sectors_32 = AROS_LONG2LE(sector_count); + + boot->bpb_media = 0xF8; + + boot->bpb_sect_per_track = AROS_WORD2LE(de->de_BlocksPerTrack); + boot->bpb_num_heads = AROS_WORD2LE(de->de_Surfaces); + boot->bpb_hidden_sect = AROS_LONG2LE(de->de_Reserved); + + if (type == 32) { + boot->ebpbs.ebpb32.bpb_fat_size_32 = AROS_LONG2LE(fat_size); + boot->ebpbs.ebpb32.bpb_root_cluster = AROS_LONG2LE(2); + boot->ebpbs.ebpb32.bpb_fs_info = AROS_WORD2LE(1); + boot->ebpbs.ebpb32.bpb_back_bootsec = AROS_WORD2LE(6); + ebpb = &boot->ebpbs.ebpb32.ebpb; + } + else { + boot->bpb_fat_size_16 = AROS_WORD2LE(fat_size); + ebpb = &boot->ebpbs.ebpb; + } + + ebpb->bs_drvnum = 0x80; + ebpb->bs_bootsig = 0x29; + + /* Generate a pseudo-random serial number. Not the original algorithm, + * but it shouldn't matter */ + ReadEClock(&eclock); + ebpb->bs_volid = FastRand(eclock.ev_lo ^ eclock.ev_hi); + + /* copy volume name in */ + for (i = 0; i < 11; i++) + if (i < len) + ebpb->bs_vollab[i] = toupper(name[i]); + else + ebpb->bs_vollab[i] = ' '; + + CopyMem(default_filsystype, ebpb->bs_filsystype, 8); + if (type != 16) { + if (type == 32) + ebpb->bs_filsystype[3] = '3'; + ebpb->bs_filsystype[4] = '2'; + } + + boot->bpb_signature[0] = 0x55; + boot->bpb_signature[1] = 0xaa; + + /* Write the boot sector */ + first_device_sector = + de->de_BlocksPerTrack * de->de_Surfaces * de->de_LowCyl; + + D(bug("[fat] boot sector at sector %ld\n", first_device_sector)); + + if ((err = AccessDisk(TRUE, first_device_sector, 1, bsize, (UBYTE *)boot)) != 0) { + D(bug("[fat] couldn't write boot block (%ld)\n", err)); + FreeMem(boot, bsize); + return err; + } + + /* Write back-up boot sector and FS info sector */ + if (type == 32) { + if ((err = AccessDisk(TRUE, first_device_sector + 6, 1, bsize, + (UBYTE *)boot)) != 0) { + D(bug("[fat] couldn't write back-up boot block (%ld)\n", err)); + FreeMem(boot, bsize); + return err; + } + + fsinfo = (APTR)boot; + memset(fsinfo, 0, bsize); + + fsinfo->lead_sig = AROS_LONG2LE(FSI_LEAD_SIG); + fsinfo->struct_sig = AROS_LONG2LE(FSI_STRUCT_SIG); + fsinfo->trail_sig = AROS_LONG2LE(FSI_TRAIL_SIG); + fsinfo->free_count = AROS_LONG2LE(0xFFFFFFFF); + fsinfo->next_free = AROS_LONG2LE(0xFFFFFFFF); + + if ((err = AccessDisk(TRUE, first_device_sector + 1, 1, bsize, + (UBYTE *)fsinfo)) != 0) { + D(bug("[fat] couldn't write back-up boot block (%ld)\n", err)); + FreeMem(boot, bsize); + return err; + } + } + + FreeMem(boot, bsize); + + glob->formatting = TRUE; + + return 0; +} + +LONG SetVolumeName(struct FSSuper *sb, UBYTE *name, UWORD len) { struct DirHandle dh; struct DirEntry de; LONG err; @@ -532,18 +793,15 @@ LONG SetVolumeName(struct FSSuper *sb, UBYTE *name) { /* create a new volume id entry if there wasn't one */ if (err != 0) { err = AllocDirEntry(&dh, 0, &de); - if (err == 0) { - memset(&de.e.entry, 0, sizeof(struct FATDirEntry)); - de.e.entry.attr = ATTR_VOLUME_ID; - } + if (err == 0) + FillDirEntry(&de, ATTR_VOLUME_ID, 0); } - /* copy the name in. name is a BSTR */ + /* copy the name in */ if (err == 0) { - de.e.entry.name[0] = name[1]; for (i = 0; i < 11; i++) - if (i < name[0]) - de.e.entry.name[i] = toupper(name[i+1]); + if (i < len) + de.e.entry.name[i] = toupper(name[i]); else de.e.entry.name[i] = ' '; @@ -555,9 +813,9 @@ LONG SetVolumeName(struct FSSuper *sb, UBYTE *name) { /* copy name to boot block as well, and save */ if (sb->type == 32) - CopyMem(de.e.entry.name, boot->type.fat32.bs_vollab, 11); + CopyMem(de.e.entry.name, boot->ebpbs.ebpb32.ebpb.bs_vollab, 11); else - CopyMem(de.e.entry.name, boot->type.fat16.bs_vollab, 11); + CopyMem(de.e.entry.name, boot->ebpbs.ebpb.bs_vollab, 11); if ((err = AccessDisk(TRUE, sb->first_device_sector, 1, bsize, (UBYTE *)boot)) != 0) @@ -565,8 +823,8 @@ LONG SetVolumeName(struct FSSuper *sb, UBYTE *name) { FreeMem(boot, bsize); /* update name in sb */ - sb->volume.name[0] = name[0] <= 11 ? name[0] : 11; - CopyMem(&name[1], &(sb->volume.name[1]), sb->volume.name[0]); + sb->volume.name[0] = len <= 11 ? len : 11; + CopyMem(name, &(sb->volume.name[1]), sb->volume.name[0]); sb->volume.name[sb->volume.name[0]+1] = '\0'; D(bug("[fat] new volume name is '%s'\n", &(sb->volume.name[1]))); diff --git a/rom/filesys/fat/fat.conf b/rom/filesys/fat/fat.conf index 52f79d90cc..0904080dde 100644 --- a/rom/filesys/fat/fat.conf +++ b/rom/filesys/fat/fat.conf @@ -1,5 +1,5 @@ ##begin config -version 41.59 +version 41.60 basename fat residentpri -1 handler_func handler diff --git a/rom/filesys/fat/fat_fs.h b/rom/filesys/fat/fat_fs.h index 6cd7df51f3..68cac8c778 100644 --- a/rom/filesys/fat/fat_fs.h +++ b/rom/filesys/fat/fat_fs.h @@ -2,7 +2,7 @@ * fat-handler - FAT12/16/32 filesystem handler * * Copyright © 2006 Marek Szyprowski - * Copyright © 2007-2013 The AROS Development Team + * Copyright © 2007-2015 The AROS Development Team * * This program is free software; you can redistribute it and/or modify it * under the same terms as AROS itself. @@ -253,6 +253,7 @@ struct Globals { /* disk status */ LONG disk_inserted; LONG disk_inhibited; + BOOL formatting; /* Character sets translation */ UBYTE from_unicode[65536]; diff --git a/rom/filesys/fat/fat_protos.h b/rom/filesys/fat/fat_protos.h index e01324bb80..bde3876568 100644 --- a/rom/filesys/fat/fat_protos.h +++ b/rom/filesys/fat/fat_protos.h @@ -2,7 +2,7 @@ * fat-handler - FAT12/16/32 filesystem handler * * Copyright © 2006 Marek Szyprowski - * Copyright © 2007-2011 The AROS Development Team + * Copyright © 2007-2015 The AROS Development Team * * This program is free software; you can redistribute it and/or modify it * under the same terms as AROS itself. @@ -13,17 +13,6 @@ #ifndef FAT_HANDLER_PROTO_H #define FAT_HANDLER_PROTO_H -/* fat */ -LONG ReadFATSuper (struct FSSuper *s); -void FreeFATSuper(struct FSSuper *s); -LONG CompareFATSuper(struct FSSuper *s1, struct FSSuper *s2); - -LONG GetVolumeIdentity(struct FSSuper *sb, struct VolumeIdentity *volume); - -void CountFreeClusters(struct FSSuper *sb); -void AllocCluster(struct FSSuper *sb, ULONG cluster); -void FreeCluster(struct FSSuper *sb, ULONG cluster); - /* disk.c */ void ProcessDiskChange (void); void DoDiskInsert(); @@ -37,14 +26,14 @@ void UpdateDisk(void); void Probe_64bit_support(void); ULONG AccessDisk(BOOL do_write, ULONG num, ULONG nblocks, ULONG block_size, UBYTE *data); -/* info.c */ void FillDiskInfo (struct InfoData *id); - + /* packet.c */ void ProcessPackets(void); void ReplyPacket(struct DosPacket *pkt); /* direntry.c */ +void InitDir(struct FSSuper *sb, ULONG cluster, struct DirEntry *de); LONG InitDirHandle(struct FSSuper *sb, ULONG cluster, struct DirHandle *dh, BOOL reuse); LONG ReleaseDirHandle(struct DirHandle *dh); @@ -62,6 +51,7 @@ LONG UpdateDirEntry(struct DirEntry *de); LONG AllocDirEntry(struct DirHandle *dh, ULONG gap, struct DirEntry *de); LONG CreateDirEntry(struct DirHandle *dh, STRPTR name, ULONG namelen, UBYTE attr, ULONG cluster, struct DirEntry *de); +void FillDirEntry(struct DirEntry *de, UBYTE attr, ULONG cluster); LONG DeleteDirEntry(struct DirEntry *de); LONG FillFIB(struct ExtFileLock *fl, struct FileInfoBlock *fib); @@ -73,9 +63,20 @@ LONG SetDirEntryName(struct DirEntry *de, STRPTR name, ULONG len); ULONG NumLongNameEntries(STRPTR name, ULONG len); /* fat.c */ +LONG ReadFATSuper(struct FSSuper *s); +void FreeFATSuper(struct FSSuper *s); +LONG FormatFATVolume(const UBYTE *name, UWORD len); +LONG CompareFATSuper(struct FSSuper *s1, struct FSSuper *s2); + +LONG GetVolumeIdentity(struct FSSuper *sb, struct VolumeIdentity *volume); + +void CountFreeClusters(struct FSSuper *sb); +void AllocCluster(struct FSSuper *sb, ULONG cluster); +void FreeCluster(struct FSSuper *sb, ULONG cluster); + void ConvertFATDate(UWORD date, UWORD time, struct DateStamp *ds); void ConvertAROSDate(struct DateStamp *ds, UWORD *date, UWORD *time); -LONG SetVolumeName(struct FSSuper *sb, UBYTE *name); +LONG SetVolumeName(struct FSSuper *sb, UBYTE *name, UWORD len); LONG FindFreeCluster(struct FSSuper *sb, ULONG *rcluster); /* file.c */ diff --git a/rom/filesys/fat/fat_struct.h b/rom/filesys/fat/fat_struct.h index 363a4f6df0..8d88321d03 100644 --- a/rom/filesys/fat/fat_struct.h +++ b/rom/filesys/fat/fat_struct.h @@ -2,7 +2,7 @@ * fat-handler - FAT12/16/32 filesystem handler * * Copyright © 2006 Marek Szyprowski - * Copyright © 2007-2011 The AROS Development Team + * Copyright © 2007-2015 The AROS Development Team * * This program is free software; you can redistribute it and/or modify it * under the same terms as AROS itself. @@ -10,6 +10,15 @@ * $Id$ */ +struct FATEBPB{ + UBYTE bs_drvnum; + UBYTE bs_reserved1; + UBYTE bs_bootsig; + ULONG bs_volid; + UBYTE bs_vollab[11]; + UBYTE bs_filsystype[8]; +} __attribute__ ((__packed__)); + struct FATBootSector { UBYTE bs_jmp_boot[3]; UBYTE bs_oem_name[8]; @@ -27,15 +36,7 @@ struct FATBootSector { ULONG bpb_total_sectors_32; union { - struct { - UBYTE bs_drvnum; - UBYTE bs_reserved1; - UBYTE bs_bootsig; - ULONG bs_volid; - UBYTE bs_vollab[11]; - UBYTE bs_filsystype[8]; - } __attribute__ ((__packed__)) fat16; - + struct FATEBPB ebpb; struct { ULONG bpb_fat_size_32; UWORD bpb_extflags; @@ -44,14 +45,9 @@ struct FATBootSector { UWORD bpb_fs_info; UWORD bpb_back_bootsec; UBYTE bpb_reserved[12]; - UBYTE bs_drvnum; - UBYTE bs_reserved1; - UBYTE bs_bootsig; - ULONG bs_volid; - UBYTE bs_vollab[11]; - UBYTE bs_filsystype[8]; - } __attribute__ ((__packed__)) fat32; - } type; + struct FATEBPB ebpb; + } __attribute__ ((__packed__)) ebpb32; + } ebpbs; UBYTE pad[420]; UBYTE bpb_signature[2]; } __attribute__ ((__packed__)); diff --git a/rom/filesys/fat/main.c b/rom/filesys/fat/main.c index a62bd64d2b..83c517ce65 100644 --- a/rom/filesys/fat/main.c +++ b/rom/filesys/fat/main.c @@ -36,6 +36,7 @@ struct DosLibrary *DOSBase; struct Library *UtilityBase; struct Library *IntuitionBase; +struct Device *TimerBase; struct Globals global_data; struct Globals *glob = &global_data; @@ -69,6 +70,8 @@ LONG handler(struct ExecBase *SysBase) { error = InitTimer(); if (!error) { + TimerBase = glob->timereq->tr_node.io_Device; + InitCharsetTables(); if ((error = InitDiskHandler(glob->fssm)) == 0) { ULONG pktsig = 1 << glob->ourport->mp_SigBit; diff --git a/rom/filesys/fat/packet.c b/rom/filesys/fat/packet.c index 92748a4ca0..c725ac6023 100644 --- a/rom/filesys/fat/packet.c +++ b/rom/filesys/fat/packet.c @@ -2,7 +2,7 @@ * fat-handler - FAT12/16/32 filesystem handler * * Copyright © 2006 Marek Szyprowski - * Copyright © 2007-2014 The AROS Development Team + * Copyright © 2007-2015 The AROS Development Team * * This program is free software; you can redistribute it and/or modify it * under the same terms as AROS itself. @@ -488,7 +488,7 @@ void ProcessPackets(void) { SendEvent(IECLASS_DISKINSERTED); - D(bug("\tVolume added successfuly\n")); + D(bug("\tVolume added\n")); } else if (type == ACTION_VOLUME_REMOVE) { RemDosEntry(vol); @@ -497,7 +497,7 @@ void ProcessPackets(void) { SendEvent(IECLASS_DISKREMOVED); - D(bug("\tVolume removed successfuly.\n")); + D(bug("\tVolume removed\n")); } FreeDosObject(DOS_STDPKT, pkt); /* cleanup */ @@ -521,9 +521,10 @@ void ProcessPackets(void) { } case ACTION_RENAME_DISK: { - UBYTE *name = BADDR(pkt->dp_Arg1); - - D(bug("[FAT] RENAME_DISK: name '"); RawPutChars(AROS_BSTR_ADDR(name), AROS_BSTR_strlen(name)); bug("'\n")); + + D(bug("[FAT] RENAME_DISK: name '"); + RawPutChars(AROS_BSTR_ADDR(pkt->dp_Arg1), + AROS_BSTR_strlen(pkt->dp_Arg1)); bug("'\n")); if (glob->sb->doslist == NULL) { err = glob->disk_inserted ? ERROR_NOT_A_DOS_DISK : ERROR_NO_DISK; @@ -533,7 +534,8 @@ void ProcessPackets(void) { while (! AttemptLockDosList(LDF_VOLUMES | LDF_WRITE)) ProcessPackets(); - err = SetVolumeName(glob->sb, name); + err = SetVolumeName(glob->sb, AROS_BSTR_ADDR(pkt->dp_Arg1), + AROS_BSTR_strlen(pkt->dp_Arg1)); UnLockDosList(LDF_VOLUMES | LDF_WRITE); if (err != 0) break; @@ -555,6 +557,38 @@ void ProcessPackets(void) { break; } + case ACTION_FORMAT: { + D(bug("[FAT] FORMAT: name '"); + RawPutChars(AROS_BSTR_ADDR(pkt->dp_Arg1), + AROS_BSTR_strlen(pkt->dp_Arg1)); bug("'\n")); + + if (glob->sb->doslist == NULL) { + err = glob->disk_inserted ? ERROR_NOT_A_DOS_DISK : ERROR_NO_DISK; + break; + } + + err = FormatFATVolume(AROS_BSTR_ADDR(pkt->dp_Arg1), + AROS_BSTR_strlen(pkt->dp_Arg1)); + if (err != 0) + break; + +#ifdef AROS_FAST_BPTR + /* ReadFATSuper() sets a null byte after the + * string, so this should be fine */ + CopyMem(glob->sb->volume.name + 1, glob->sb->doslist->dol_Name, + glob->sb->volume.name[0] + 1); +#else + CopyMem(glob->sb->volume.name, BADDR(glob->sb->doslist->dol_Name), + glob->sb->volume.name[0] + 2); +#endif + + SendEvent(IECLASS_DISKINSERTED); + + res = DOSTRUE; + + break; + } + case ACTION_DELETE_OBJECT: { struct ExtFileLock *fl = BADDR(pkt->dp_Arg1); UBYTE *name = BADDR(pkt->dp_Arg2); -- 2.11.4.GIT