mirror of
https://github.com/ventoy/Ventoy.git
synced 2025-05-18 17:25:13 -04:00
1.0.36 release
This commit is contained in:
parent
7b08954e57
commit
cbbd57eee5
58 changed files with 136 additions and 1042 deletions
373
LinuxGUI/Ventoy2Disk/Lib/fat_io_lib/fat_write.c
Normal file
373
LinuxGUI/Ventoy2Disk/Lib/fat_io_lib/fat_write.c
Normal file
|
@ -0,0 +1,373 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
// FAT16/32 File IO Library
|
||||
// V2.6
|
||||
// Ultra-Embedded.com
|
||||
// Copyright 2003 - 2012
|
||||
//
|
||||
// Email: admin@ultra-embedded.com
|
||||
//
|
||||
// License: GPL
|
||||
// If you would like a version with a more permissive license for use in
|
||||
// closed source commercial applications please contact me for details.
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// This file is part of FAT File IO Library.
|
||||
//
|
||||
// FAT File IO Library is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// FAT File IO Library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with FAT File IO Library; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
#include <string.h>
|
||||
#include "fat_defs.h"
|
||||
#include "fat_access.h"
|
||||
#include "fat_table.h"
|
||||
#include "fat_write.h"
|
||||
#include "fat_string.h"
|
||||
#include "fat_misc.h"
|
||||
|
||||
#if FATFS_INC_WRITE_SUPPORT
|
||||
//-----------------------------------------------------------------------------
|
||||
// fatfs_add_free_space: Allocate another cluster of free space to the end
|
||||
// of a files cluster chain.
|
||||
//-----------------------------------------------------------------------------
|
||||
int fatfs_add_free_space(struct fatfs *fs, uint32 *startCluster, uint32 clusters)
|
||||
{
|
||||
uint32 i;
|
||||
uint32 nextcluster;
|
||||
uint32 start = *startCluster;
|
||||
|
||||
// Set the next free cluster hint to unknown
|
||||
if (fs->next_free_cluster != FAT32_LAST_CLUSTER)
|
||||
fatfs_set_fs_info_next_free_cluster(fs, FAT32_LAST_CLUSTER);
|
||||
|
||||
for (i=0;i<clusters;i++)
|
||||
{
|
||||
// Start looking for free clusters from the beginning
|
||||
if (fatfs_find_blank_cluster(fs, fs->rootdir_first_cluster, &nextcluster))
|
||||
{
|
||||
// Point last to this
|
||||
fatfs_fat_set_cluster(fs, start, nextcluster);
|
||||
|
||||
// Point this to end of file
|
||||
fatfs_fat_set_cluster(fs, nextcluster, FAT32_LAST_CLUSTER);
|
||||
|
||||
// Adjust argument reference
|
||||
start = nextcluster;
|
||||
if (i == 0)
|
||||
*startCluster = nextcluster;
|
||||
}
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
// fatfs_allocate_free_space: Add an ammount of free space to a file either from
|
||||
// 'startCluster' if newFile = false, or allocating a new start to the chain if
|
||||
// newFile = true.
|
||||
//-----------------------------------------------------------------------------
|
||||
int fatfs_allocate_free_space(struct fatfs *fs, int newFile, uint32 *startCluster, uint32 size)
|
||||
{
|
||||
uint32 clusterSize;
|
||||
uint32 clusterCount;
|
||||
uint32 nextcluster;
|
||||
|
||||
if (size==0)
|
||||
return 0;
|
||||
|
||||
// Set the next free cluster hint to unknown
|
||||
if (fs->next_free_cluster != FAT32_LAST_CLUSTER)
|
||||
fatfs_set_fs_info_next_free_cluster(fs, FAT32_LAST_CLUSTER);
|
||||
|
||||
// Work out size and clusters
|
||||
clusterSize = fs->sectors_per_cluster * FAT_SECTOR_SIZE;
|
||||
clusterCount = (size / clusterSize);
|
||||
|
||||
// If any left over
|
||||
if (size-(clusterSize*clusterCount))
|
||||
clusterCount++;
|
||||
|
||||
// Allocated first link in the chain if a new file
|
||||
if (newFile)
|
||||
{
|
||||
if (!fatfs_find_blank_cluster(fs, fs->rootdir_first_cluster, &nextcluster))
|
||||
return 0;
|
||||
|
||||
// If this is all that is needed then all done
|
||||
if (clusterCount==1)
|
||||
{
|
||||
fatfs_fat_set_cluster(fs, nextcluster, FAT32_LAST_CLUSTER);
|
||||
*startCluster = nextcluster;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
// Allocate from end of current chain (startCluster is end of chain)
|
||||
else
|
||||
nextcluster = *startCluster;
|
||||
|
||||
if (!fatfs_add_free_space(fs, &nextcluster, clusterCount))
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
// fatfs_find_free_dir_offset: Find a free space in the directory for a new entry
|
||||
// which takes up 'entryCount' blocks (or allocate some more)
|
||||
//-----------------------------------------------------------------------------
|
||||
static int fatfs_find_free_dir_offset(struct fatfs *fs, uint32 dirCluster, int entryCount, uint32 *pSector, uint8 *pOffset)
|
||||
{
|
||||
struct fat_dir_entry *directoryEntry;
|
||||
uint8 item=0;
|
||||
uint16 recordoffset = 0;
|
||||
uint8 i=0;
|
||||
int x=0;
|
||||
int possible_spaces = 0;
|
||||
int start_recorded = 0;
|
||||
|
||||
// No entries required?
|
||||
if (entryCount == 0)
|
||||
return 0;
|
||||
|
||||
// Main cluster following loop
|
||||
while (1)
|
||||
{
|
||||
// Read sector
|
||||
if (fatfs_sector_reader(fs, dirCluster, x++, 0))
|
||||
{
|
||||
// Analyse Sector
|
||||
for (item = 0; item < FAT_DIR_ENTRIES_PER_SECTOR; item++)
|
||||
{
|
||||
// Create the multiplier for sector access
|
||||
recordoffset = FAT_DIR_ENTRY_SIZE * item;
|
||||
|
||||
// Overlay directory entry over buffer
|
||||
directoryEntry = (struct fat_dir_entry*)(fs->currentsector.sector+recordoffset);
|
||||
|
||||
// LFN Entry
|
||||
if (fatfs_entry_lfn_text(directoryEntry))
|
||||
{
|
||||
// First entry?
|
||||
if (possible_spaces == 0)
|
||||
{
|
||||
// Store start
|
||||
*pSector = x-1;
|
||||
*pOffset = item;
|
||||
start_recorded = 1;
|
||||
}
|
||||
|
||||
// Increment the count in-case the file turns
|
||||
// out to be deleted...
|
||||
possible_spaces++;
|
||||
}
|
||||
// SFN Entry
|
||||
else
|
||||
{
|
||||
// Has file been deleted?
|
||||
if (fs->currentsector.sector[recordoffset] == FILE_HEADER_DELETED)
|
||||
{
|
||||
// First entry?
|
||||
if (possible_spaces == 0)
|
||||
{
|
||||
// Store start
|
||||
*pSector = x-1;
|
||||
*pOffset = item;
|
||||
start_recorded = 1;
|
||||
}
|
||||
|
||||
possible_spaces++;
|
||||
|
||||
// We have found enough space?
|
||||
if (possible_spaces >= entryCount)
|
||||
return 1;
|
||||
|
||||
// Else continue counting until we find a valid entry!
|
||||
}
|
||||
// Is the file entry empty?
|
||||
else if (fs->currentsector.sector[recordoffset] == FILE_HEADER_BLANK)
|
||||
{
|
||||
// First entry?
|
||||
if (possible_spaces == 0)
|
||||
{
|
||||
// Store start
|
||||
*pSector = x-1;
|
||||
*pOffset = item;
|
||||
start_recorded = 1;
|
||||
}
|
||||
|
||||
// Increment the blank entries count
|
||||
possible_spaces++;
|
||||
|
||||
// We have found enough space?
|
||||
if (possible_spaces >= entryCount)
|
||||
return 1;
|
||||
}
|
||||
// File entry is valid
|
||||
else
|
||||
{
|
||||
// Reset all flags
|
||||
possible_spaces = 0;
|
||||
start_recorded = 0;
|
||||
}
|
||||
}
|
||||
} // End of for
|
||||
} // End of if
|
||||
// Run out of free space in the directory, allocate some more
|
||||
else
|
||||
{
|
||||
uint32 newCluster;
|
||||
|
||||
// Get a new cluster for directory
|
||||
if (!fatfs_find_blank_cluster(fs, fs->rootdir_first_cluster, &newCluster))
|
||||
return 0;
|
||||
|
||||
// Add cluster to end of directory tree
|
||||
if (!fatfs_fat_add_cluster_to_chain(fs, dirCluster, newCluster))
|
||||
return 0;
|
||||
|
||||
// Erase new directory cluster
|
||||
memset(fs->currentsector.sector, 0x00, FAT_SECTOR_SIZE);
|
||||
for (i=0;i<fs->sectors_per_cluster;i++)
|
||||
{
|
||||
if (!fatfs_write_sector(fs, newCluster, i, 0))
|
||||
return 0;
|
||||
}
|
||||
|
||||
// If non of the name fitted on previous sectors
|
||||
if (!start_recorded)
|
||||
{
|
||||
// Store start
|
||||
*pSector = (x-1);
|
||||
*pOffset = 0;
|
||||
start_recorded = 1;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
} // End of while loop
|
||||
|
||||
return 0;
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
// fatfs_add_file_entry: Add a directory entry to a location found by FindFreeOffset
|
||||
//-----------------------------------------------------------------------------
|
||||
int fatfs_add_file_entry(struct fatfs *fs, uint32 dirCluster, char *filename, char *shortfilename, uint32 startCluster, uint32 size, int dir)
|
||||
{
|
||||
uint8 item=0;
|
||||
uint16 recordoffset = 0;
|
||||
uint8 i=0;
|
||||
uint32 x=0;
|
||||
int entryCount;
|
||||
struct fat_dir_entry shortEntry;
|
||||
int dirtySector = 0;
|
||||
|
||||
uint32 dirSector = 0;
|
||||
uint8 dirOffset = 0;
|
||||
int foundEnd = 0;
|
||||
|
||||
uint8 checksum;
|
||||
uint8 *pSname;
|
||||
|
||||
// No write access?
|
||||
if (!fs->disk_io.write_media)
|
||||
return 0;
|
||||
|
||||
#if FATFS_INC_LFN_SUPPORT
|
||||
// How many LFN entries are required?
|
||||
// NOTE: We always request one LFN even if it would fit in a SFN!
|
||||
entryCount = fatfs_lfn_entries_required(filename);
|
||||
if (!entryCount)
|
||||
return 0;
|
||||
#else
|
||||
entryCount = 0;
|
||||
#endif
|
||||
|
||||
// Find space in the directory for this filename (or allocate some more)
|
||||
// NOTE: We need to find space for at least the LFN + SFN (or just the SFN if LFNs not supported).
|
||||
if (!fatfs_find_free_dir_offset(fs, dirCluster, entryCount + 1, &dirSector, &dirOffset))
|
||||
return 0;
|
||||
|
||||
// Generate checksum of short filename
|
||||
pSname = (uint8*)shortfilename;
|
||||
checksum = 0;
|
||||
for (i=11; i!=0; i--) checksum = ((checksum & 1) ? 0x80 : 0) + (checksum >> 1) + *pSname++;
|
||||
|
||||
// Start from current sector where space was found!
|
||||
x = dirSector;
|
||||
|
||||
// Main cluster following loop
|
||||
while (1)
|
||||
{
|
||||
// Read sector
|
||||
if (fatfs_sector_reader(fs, dirCluster, x++, 0))
|
||||
{
|
||||
// Analyse Sector
|
||||
for (item = 0; item < FAT_DIR_ENTRIES_PER_SECTOR; item++)
|
||||
{
|
||||
// Create the multiplier for sector access
|
||||
recordoffset = FAT_DIR_ENTRY_SIZE * item;
|
||||
|
||||
// If the start position for the entry has been found
|
||||
if (foundEnd==0)
|
||||
if ( (dirSector==(x-1)) && (dirOffset==item) )
|
||||
foundEnd = 1;
|
||||
|
||||
// Start adding filename
|
||||
if (foundEnd)
|
||||
{
|
||||
if (entryCount==0)
|
||||
{
|
||||
// Short filename
|
||||
fatfs_sfn_create_entry(shortfilename, size, startCluster, &shortEntry, dir);
|
||||
|
||||
#if FATFS_INC_TIME_DATE_SUPPORT
|
||||
// Update create, access & modify time & date
|
||||
fatfs_update_timestamps(&shortEntry, 1, 1, 1);
|
||||
#endif
|
||||
|
||||
memcpy(&fs->currentsector.sector[recordoffset], &shortEntry, sizeof(shortEntry));
|
||||
|
||||
// Writeback
|
||||
return fs->disk_io.write_media(fs->currentsector.address, fs->currentsector.sector, 1);
|
||||
}
|
||||
#if FATFS_INC_LFN_SUPPORT
|
||||
else
|
||||
{
|
||||
entryCount--;
|
||||
|
||||
// Copy entry to directory buffer
|
||||
fatfs_filename_to_lfn(filename, &fs->currentsector.sector[recordoffset], entryCount, checksum);
|
||||
dirtySector = 1;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
} // End of if
|
||||
|
||||
// Write back to disk before loading another sector
|
||||
if (dirtySector)
|
||||
{
|
||||
if (!fs->disk_io.write_media(fs->currentsector.address, fs->currentsector.sector, 1))
|
||||
return 0;
|
||||
|
||||
dirtySector = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
return 0;
|
||||
} // End of while loop
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
Loading…
Add table
Add a link
Reference in a new issue