mirror of
https://github.com/eclipse-threadx/filex.git
synced 2026-09-14 04:05:59 +08:00
711 lines
24 KiB
C
711 lines
24 KiB
C
/***************************************************************************
|
|
* Copyright (c) 2024 Microsoft Corporation
|
|
*
|
|
* This program and the accompanying materials are made available under the
|
|
* terms of the MIT License which is available at
|
|
* https://opensource.org/licenses/MIT.
|
|
*
|
|
* SPDX-License-Identifier: MIT
|
|
**************************************************************************/
|
|
|
|
|
|
/**************************************************************************/
|
|
/**************************************************************************/
|
|
/** */
|
|
/** FileX Component */
|
|
/** */
|
|
/** Directory */
|
|
/** */
|
|
/**************************************************************************/
|
|
/**************************************************************************/
|
|
|
|
#define FX_SOURCE_CODE
|
|
|
|
|
|
/* Include necessary system files. */
|
|
|
|
#include "fx_api.h"
|
|
#include "fx_system.h"
|
|
#include "fx_directory.h"
|
|
#include "fx_file.h"
|
|
#include "fx_utility.h"
|
|
#ifdef FX_ENABLE_FAULT_TOLERANT
|
|
#include "fx_fault_tolerant.h"
|
|
#endif /* FX_ENABLE_FAULT_TOLERANT */
|
|
|
|
|
|
/**************************************************************************/
|
|
/* */
|
|
/* FUNCTION RELEASE */
|
|
/* */
|
|
/* _fx_directory_create PORTABLE C */
|
|
/* 6.1 */
|
|
/* AUTHOR */
|
|
/* */
|
|
/* William E. Lamie, Microsoft Corporation */
|
|
/* */
|
|
/* DESCRIPTION */
|
|
/* */
|
|
/* This function first attempts to find the specified directory. */
|
|
/* If found, the create request is invalid and an error is returned */
|
|
/* to the caller. After the file name verification is made, a search */
|
|
/* for a free directory entry will be made. If nothing is available, */
|
|
/* an error will be returned to the caller. Otherwise, if all is */
|
|
/* okay, an empty directory will be created. */
|
|
/* */
|
|
/* INPUT */
|
|
/* */
|
|
/* media_ptr Media control block pointer */
|
|
/* directory_name Directory name */
|
|
/* */
|
|
/* OUTPUT */
|
|
/* */
|
|
/* return status */
|
|
/* */
|
|
/* CALLS */
|
|
/* */
|
|
/* _fx_directory_entry_write Write the new directory entry */
|
|
/* _fx_directory_name_extract Pickup next part of name */
|
|
/* _fx_directory_search Search for the file name in */
|
|
/* the directory structure */
|
|
/* _fx_directory_free_search Search for a free directory */
|
|
/* entry */
|
|
/* _fx_utility_FAT_flush Flush written FAT entries */
|
|
/* _fx_utility_FAT_entry_read Read a FAT entry */
|
|
/* _fx_utility_FAT_entry_write Write a FAT entry */
|
|
/* _fx_utility_logical_sector_flush Flush the written log sector */
|
|
/* _fx_utility_logical_sector_read Read logical sector */
|
|
/* _fx_fault_tolerant_transaction_start Start fault tolerant */
|
|
/* transaction */
|
|
/* _fx_fault_tolerant_transaction_end End fault tolerant transaction*/
|
|
/* _fx_fault_tolerant_recover Recover FAT chain */
|
|
/* _fx_fault_tolerant_reset_log_file Reset the log file */
|
|
/* */
|
|
/* CALLED BY */
|
|
/* */
|
|
/* Application Code */
|
|
/* */
|
|
/* RELEASE HISTORY */
|
|
/* */
|
|
/* DATE NAME DESCRIPTION */
|
|
/* */
|
|
/* 05-19-2020 William E. Lamie Initial Version 6.0 */
|
|
/* 09-30-2020 William E. Lamie Modified comment(s), */
|
|
/* resulting in version 6.1 */
|
|
/* */
|
|
/**************************************************************************/
|
|
UINT _fx_directory_create(FX_MEDIA *media_ptr, CHAR *directory_name)
|
|
{
|
|
|
|
UINT status;
|
|
ULONG FAT_index;
|
|
ULONG FAT_value;
|
|
UINT sectors;
|
|
ULONG total_clusters;
|
|
CHAR *work_ptr;
|
|
ULONG64 logical_sector;
|
|
ULONG i;
|
|
FX_DIR_ENTRY dir_entry;
|
|
FX_DIR_ENTRY sub_dir_entry;
|
|
FX_DIR_ENTRY search_directory;
|
|
|
|
FX_INT_SAVE_AREA
|
|
|
|
|
|
#ifndef FX_MEDIA_STATISTICS_DISABLE
|
|
|
|
/* Increment the number of times this service has been called. */
|
|
media_ptr -> fx_media_directory_creates++;
|
|
#endif
|
|
|
|
/* Determine if the supplied name is less than the maximum supported name size. The
|
|
maximum name (FX_MAX_LONG_NAME_LEN) is defined in fx_api.h. */
|
|
i = 0;
|
|
work_ptr = (CHAR *)directory_name;
|
|
while (*work_ptr && (i < FX_MAX_LONG_NAME_LEN))
|
|
{
|
|
|
|
/* Determine if the character designates a new path. */
|
|
if ((*work_ptr == '\\') || (*work_ptr == '/'))
|
|
{
|
|
/* Yes, reset the name size. */
|
|
i = 0;
|
|
}
|
|
/* Check for leading spaces. */
|
|
else if ((*work_ptr != ' ') || (i != 0))
|
|
{
|
|
|
|
/* No leading spaces, increment the name size. */
|
|
i++;
|
|
}
|
|
|
|
/* Move to the next character. */
|
|
work_ptr++;
|
|
}
|
|
|
|
/* Determine if the supplied name is valid. */
|
|
if ((i == 0) || (i >= FX_MAX_LONG_NAME_LEN))
|
|
{
|
|
|
|
/* Return an invalid name value. */
|
|
return(FX_INVALID_NAME);
|
|
}
|
|
|
|
/* Setup pointer to media name buffer. */
|
|
dir_entry.fx_dir_entry_name = media_ptr -> fx_media_name_buffer + FX_MAX_LONG_NAME_LEN;
|
|
|
|
/* Setup search directory pointer to another media name buffer. */
|
|
search_directory.fx_dir_entry_name = media_ptr -> fx_media_name_buffer + FX_MAX_LONG_NAME_LEN * 2;
|
|
|
|
/* Clear the short name string. */
|
|
dir_entry.fx_dir_entry_short_name[0] = 0;
|
|
|
|
/* Clear the search short name string. */
|
|
search_directory.fx_dir_entry_short_name[0] = 0;
|
|
|
|
/* Check the media to make sure it is open. */
|
|
if (media_ptr -> fx_media_id != FX_MEDIA_ID)
|
|
{
|
|
|
|
/* Return the media not opened error. */
|
|
return(FX_MEDIA_NOT_OPEN);
|
|
}
|
|
|
|
/* If trace is enabled, insert this event into the trace buffer. */
|
|
FX_TRACE_IN_LINE_INSERT(FX_TRACE_DIRECTORY_CREATE, media_ptr, directory_name, 0, 0, FX_TRACE_DIRECTORY_EVENTS, 0, 0)
|
|
|
|
/* Protect against other threads accessing the media. */
|
|
FX_PROTECT
|
|
|
|
/* Check for write protect at the media level (set by driver). */
|
|
if (media_ptr -> fx_media_driver_write_protect)
|
|
{
|
|
|
|
/* Release media protection. */
|
|
FX_UNPROTECT
|
|
|
|
/* Return write protect error. */
|
|
return(FX_WRITE_PROTECT);
|
|
}
|
|
|
|
/* Make sure there is at least one cluster remaining for the new file. */
|
|
if (!media_ptr -> fx_media_available_clusters)
|
|
{
|
|
|
|
/* Release media protection. */
|
|
FX_UNPROTECT
|
|
|
|
/* Return a no-space error. */
|
|
return(FX_NO_MORE_SPACE);
|
|
}
|
|
|
|
/* Search the system for the supplied directory name. */
|
|
status = _fx_directory_search(media_ptr, directory_name, &dir_entry, &search_directory, &work_ptr);
|
|
|
|
/* Determine if the search was successful. */
|
|
if (status == FX_SUCCESS)
|
|
{
|
|
|
|
/* Release media protection. */
|
|
FX_UNPROTECT
|
|
|
|
/* Directory found - Return the error code. */
|
|
return(FX_ALREADY_CREATED);
|
|
}
|
|
|
|
/* Determine if there is anything left after the name. */
|
|
if (_fx_directory_name_extract(work_ptr, &dir_entry.fx_dir_entry_name[0]))
|
|
{
|
|
|
|
/* Release media protection. */
|
|
FX_UNPROTECT
|
|
|
|
/* Extra information after the file name, return an invalid name
|
|
error. */
|
|
return(FX_INVALID_PATH);
|
|
}
|
|
|
|
|
|
#ifdef FX_ENABLE_FAULT_TOLERANT
|
|
/* Start transaction. */
|
|
_fx_fault_tolerant_transaction_start(media_ptr);
|
|
#endif /* FX_ENABLE_FAULT_TOLERANT */
|
|
|
|
/* Find a free slot for the new directory. */
|
|
status = _fx_directory_free_search(media_ptr, &search_directory, &dir_entry);
|
|
|
|
/* Determine if the search was successful. */
|
|
if (status != FX_SUCCESS)
|
|
{
|
|
|
|
#ifdef FX_ENABLE_FAULT_TOLERANT
|
|
FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
|
|
#endif /* FX_ENABLE_FAULT_TOLERANT */
|
|
|
|
/* Release media protection. */
|
|
FX_UNPROTECT
|
|
|
|
/* Return the error code. */
|
|
return(status);
|
|
}
|
|
|
|
/* Now allocate a cluster for our new sub-directory entry. */
|
|
|
|
FAT_index = media_ptr -> fx_media_cluster_search_start;
|
|
total_clusters = media_ptr -> fx_media_total_clusters;
|
|
|
|
/* Loop to find the first available cluster. */
|
|
do
|
|
{
|
|
|
|
/* Make sure we don't go past the FAT table. */
|
|
if (!total_clusters)
|
|
{
|
|
|
|
#ifdef FX_ENABLE_FAULT_TOLERANT
|
|
FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
|
|
#endif /* FX_ENABLE_FAULT_TOLERANT */
|
|
|
|
/* Release media protection. */
|
|
FX_UNPROTECT
|
|
|
|
/* Something is wrong with the media - the desired clusters were
|
|
not found in the FAT table. */
|
|
return(FX_NO_MORE_SPACE);
|
|
}
|
|
|
|
/* Read FAT entry. */
|
|
status = _fx_utility_FAT_entry_read(media_ptr, FAT_index, &FAT_value);
|
|
|
|
/* Check for a bad status. */
|
|
if (status != FX_SUCCESS)
|
|
{
|
|
|
|
#ifdef FX_ENABLE_FAULT_TOLERANT
|
|
FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
|
|
#endif /* FX_ENABLE_FAULT_TOLERANT */
|
|
|
|
/* Release media protection. */
|
|
FX_UNPROTECT
|
|
|
|
/* Return the bad status. */
|
|
return(status);
|
|
}
|
|
|
|
/* Decrement the total cluster count. */
|
|
total_clusters--;
|
|
|
|
/* Determine if the FAT entry is free. */
|
|
if (FAT_value == FX_FREE_CLUSTER)
|
|
{
|
|
|
|
/* Move cluster search pointer forward. */
|
|
media_ptr -> fx_media_cluster_search_start = FAT_index + 1;
|
|
|
|
/* Determine if this needs to be wrapped. */
|
|
if (media_ptr -> fx_media_cluster_search_start >= (media_ptr -> fx_media_total_clusters + FX_FAT_ENTRY_START))
|
|
{
|
|
|
|
/* Wrap the search to the beginning FAT entry. */
|
|
media_ptr -> fx_media_cluster_search_start = FX_FAT_ENTRY_START;
|
|
}
|
|
|
|
/* Break this loop. */
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
|
|
/* FAT entry is not free... Advance the FAT index. */
|
|
FAT_index++;
|
|
|
|
/* Determine if we need to wrap the FAT index around. */
|
|
if (FAT_index >= (media_ptr -> fx_media_total_clusters + FX_FAT_ENTRY_START))
|
|
{
|
|
|
|
/* Wrap the search to the beginning FAT entry. */
|
|
FAT_index = FX_FAT_ENTRY_START;
|
|
}
|
|
}
|
|
} while (FX_TRUE);
|
|
|
|
/* Decrease the number of available clusters for the media. */
|
|
media_ptr -> fx_media_available_clusters--;
|
|
|
|
/* Defer the writing of the FAT entry until the directory's first sector
|
|
has been properly written. If a power loss occurs prior to writing
|
|
the FAT entry, it will not result in a lost cluster. */
|
|
|
|
/* Populate the directory entry. */
|
|
|
|
/* Isolate the file name. */
|
|
_fx_directory_name_extract(work_ptr, &dir_entry.fx_dir_entry_name[0]);
|
|
|
|
/* Lockout interrupts for time/date access. */
|
|
FX_DISABLE_INTS
|
|
|
|
/* Set time and date stamps. */
|
|
dir_entry.fx_dir_entry_time = _fx_system_time;
|
|
dir_entry.fx_dir_entry_date = _fx_system_date;
|
|
|
|
/* Restore interrupts. */
|
|
FX_RESTORE_INTS
|
|
|
|
/* Set the attributes for the file. */
|
|
dir_entry.fx_dir_entry_attributes = FX_DIRECTORY;
|
|
|
|
|
|
/* Set file size to 0. */
|
|
dir_entry.fx_dir_entry_file_size = 0;
|
|
|
|
|
|
/* Set the cluster to EOF. */
|
|
dir_entry.fx_dir_entry_cluster = FAT_index;
|
|
|
|
/* Is there a leading dot? */
|
|
if (dir_entry.fx_dir_entry_name[0] == '.')
|
|
{
|
|
|
|
/* Yes, toggle the hidden attribute bit. */
|
|
dir_entry.fx_dir_entry_attributes |= FX_HIDDEN;
|
|
}
|
|
|
|
/* In previous versions, the new directory was written here. It
|
|
is now at the bottom of the file - after the FAT and the initial
|
|
sub-directory is written out. This makes the directory create
|
|
more fault tolerant. */
|
|
|
|
/* Calculate the first sector of the sub-directory file. */
|
|
logical_sector = ((ULONG) media_ptr -> fx_media_data_sector_start) +
|
|
(((ULONG64) FAT_index - FX_FAT_ENTRY_START) *
|
|
((ULONG) media_ptr -> fx_media_sectors_per_cluster));
|
|
|
|
/* Pickup the number of sectors for the initial sub-directory cluster. */
|
|
sectors = media_ptr -> fx_media_sectors_per_cluster;
|
|
|
|
/* Read the first logical sector associated with the allocated
|
|
cluster. */
|
|
status = _fx_utility_logical_sector_read(media_ptr, logical_sector,
|
|
media_ptr -> fx_media_memory_buffer, ((ULONG) 1), FX_DIRECTORY_SECTOR);
|
|
|
|
/* Determine if an error occurred. */
|
|
if (status != FX_SUCCESS)
|
|
{
|
|
|
|
#ifdef FX_ENABLE_FAULT_TOLERANT
|
|
FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
|
|
#endif /* FX_ENABLE_FAULT_TOLERANT */
|
|
|
|
/* Release media protection. */
|
|
FX_UNPROTECT
|
|
|
|
/* Return error code. */
|
|
return(status);
|
|
}
|
|
|
|
/* Clear the entire first sector of the new sub-directory cluster. */
|
|
work_ptr = (CHAR *)media_ptr -> fx_media_memory_buffer;
|
|
i = 0;
|
|
while (i < media_ptr -> fx_media_bytes_per_sector)
|
|
{
|
|
|
|
/* Clear 4 bytes. */
|
|
*((ULONG *)work_ptr) = (ULONG)0;
|
|
|
|
/* Increment pointer. */
|
|
work_ptr = work_ptr + sizeof(ULONG);
|
|
|
|
/* Increment counter. */
|
|
i = i + (ULONG)sizeof(ULONG);
|
|
}
|
|
|
|
#ifdef FX_ENABLE_FAULT_TOLERANT
|
|
if (media_ptr -> fx_media_fault_tolerant_enabled == FX_TRUE)
|
|
{
|
|
|
|
/* Write back. */
|
|
status = _fx_utility_logical_sector_write(media_ptr, logical_sector,
|
|
media_ptr -> fx_media_memory_buffer, (ULONG)1, FX_DIRECTORY_SECTOR);
|
|
|
|
/* Determine if an error occurred. */
|
|
if (status != FX_SUCCESS)
|
|
{
|
|
FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
|
|
|
|
/* Release media protection. */
|
|
FX_UNPROTECT
|
|
|
|
/* Return error code. */
|
|
return(status);
|
|
}
|
|
|
|
/* Force flush the internal logical sector cache. */
|
|
status = _fx_utility_logical_sector_flush(media_ptr, logical_sector, sectors, FX_TRUE);
|
|
|
|
/* Determine if the write was successful. */
|
|
if (status != FX_SUCCESS)
|
|
{
|
|
FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
|
|
|
|
/* Release media protection. */
|
|
FX_UNPROTECT
|
|
|
|
/* Return the error code. */
|
|
return(status);
|
|
}
|
|
}
|
|
#endif /* FX_ENABLE_FAULT_TOLERANT */
|
|
|
|
/* Determine if there are more sectors to clear in the first cluster of the new
|
|
sub-directory. */
|
|
if (sectors > 1)
|
|
{
|
|
|
|
/* Yes, invalidate all cached sectors that are contained in the newly allocated first
|
|
cluster of the directory. */
|
|
|
|
#ifdef FX_ENABLE_FAULT_TOLERANT
|
|
if (media_ptr -> fx_media_fault_tolerant_enabled == FX_FALSE)
|
|
#endif /* FX_ENABLE_FAULT_TOLERANT */
|
|
{
|
|
|
|
/* Flush the internal logical sector cache. */
|
|
status = _fx_utility_logical_sector_flush(media_ptr, logical_sector + 1, ((ULONG64)(sectors - 1)), FX_TRUE);
|
|
|
|
/* Determine if the write was successful. */
|
|
if (status != FX_SUCCESS)
|
|
{
|
|
|
|
#ifdef FX_ENABLE_FAULT_TOLERANT
|
|
FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
|
|
#endif /* FX_ENABLE_FAULT_TOLERANT */
|
|
|
|
/* Release media protection. */
|
|
FX_UNPROTECT
|
|
|
|
/* Return the error code. */
|
|
return(status);
|
|
}
|
|
}
|
|
|
|
/* Clear all additional sectors of new sub-directory. */
|
|
sectors--;
|
|
while (sectors)
|
|
{
|
|
|
|
#ifndef FX_MEDIA_STATISTICS_DISABLE
|
|
|
|
/* Increment the number of driver write sector(s) requests. */
|
|
media_ptr -> fx_media_driver_write_requests++;
|
|
#endif
|
|
|
|
/* Build Write request to the driver. */
|
|
media_ptr -> fx_media_driver_request = FX_DRIVER_WRITE;
|
|
media_ptr -> fx_media_driver_status = FX_IO_ERROR;
|
|
media_ptr -> fx_media_driver_buffer = media_ptr -> fx_media_memory_buffer;
|
|
#ifdef FX_DRIVER_USE_64BIT_LBA
|
|
media_ptr -> fx_media_driver_logical_sector = logical_sector + ((ULONG)sectors);
|
|
#else
|
|
media_ptr -> fx_media_driver_logical_sector = (ULONG)logical_sector + ((ULONG)sectors);
|
|
#endif
|
|
media_ptr -> fx_media_driver_sectors = 1;
|
|
media_ptr -> fx_media_driver_sector_type = FX_DIRECTORY_SECTOR;
|
|
|
|
/* Set the system write flag since we are writing a directory sector. */
|
|
media_ptr -> fx_media_driver_system_write = FX_TRUE;
|
|
|
|
/* If trace is enabled, insert this event into the trace buffer. */
|
|
FX_TRACE_IN_LINE_INSERT(FX_TRACE_INTERNAL_IO_DRIVER_WRITE, media_ptr, ((ULONG)logical_sector) + ((ULONG)sectors), 1, media_ptr -> fx_media_memory_buffer, FX_TRACE_INTERNAL_EVENTS, 0, 0)
|
|
|
|
/* Invoke the driver to write the sector. */
|
|
(media_ptr -> fx_media_driver_entry) (media_ptr);
|
|
|
|
/* Clear the system write flag. */
|
|
media_ptr -> fx_media_driver_system_write = FX_FALSE;
|
|
|
|
/* Determine if an error occurred. */
|
|
if (media_ptr -> fx_media_driver_status != FX_SUCCESS)
|
|
{
|
|
|
|
#ifdef FX_ENABLE_FAULT_TOLERANT
|
|
FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
|
|
#endif /* FX_ENABLE_FAULT_TOLERANT */
|
|
|
|
/* Release media protection. */
|
|
FX_UNPROTECT
|
|
|
|
/* Return error code. */
|
|
return(media_ptr -> fx_media_driver_status);
|
|
}
|
|
|
|
/* Decrease the number of sectors to clear. */
|
|
sectors--;
|
|
}
|
|
}
|
|
|
|
|
|
/* Now setup the first sector with the initial sub-directory information. */
|
|
|
|
/* Copy the base directory entry to the sub-directory entry. */
|
|
sub_dir_entry = dir_entry;
|
|
|
|
/* Setup pointer to media name buffer. */
|
|
sub_dir_entry.fx_dir_entry_name = media_ptr -> fx_media_name_buffer + (FX_MAX_LONG_NAME_LEN * 3);
|
|
|
|
/* Set the directory entry name to all blanks. */
|
|
work_ptr = &sub_dir_entry.fx_dir_entry_name[0];
|
|
for (i = 0; i < (FX_DIR_NAME_SIZE + FX_DIR_EXT_SIZE); i++)
|
|
{
|
|
*work_ptr++ = ' ';
|
|
}
|
|
|
|
sub_dir_entry.fx_dir_entry_long_name_present = 0;
|
|
|
|
/* Now build the "." directory entry. */
|
|
sub_dir_entry.fx_dir_entry_name[0] = '.';
|
|
sub_dir_entry.fx_dir_entry_name[1] = 0;
|
|
sub_dir_entry.fx_dir_entry_log_sector = logical_sector;
|
|
sub_dir_entry.fx_dir_entry_byte_offset = 0;
|
|
|
|
/* Write the directory's first entry. */
|
|
status = _fx_directory_entry_write(media_ptr, &sub_dir_entry);
|
|
|
|
/* Check for error condition. */
|
|
if (status != FX_SUCCESS)
|
|
{
|
|
|
|
#ifdef FX_ENABLE_FAULT_TOLERANT
|
|
FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
|
|
#endif /* FX_ENABLE_FAULT_TOLERANT */
|
|
|
|
/* Release media protection. */
|
|
FX_UNPROTECT
|
|
|
|
/* Return error status. */
|
|
return(status);
|
|
}
|
|
|
|
/* Now build the ".." directory entry. */
|
|
|
|
/* Determine if the search directory is the root. */
|
|
if (search_directory.fx_dir_entry_name[0])
|
|
{
|
|
|
|
/* Previous directory is not the root directory. */
|
|
|
|
/* Copy into the working directory entry. */
|
|
sub_dir_entry = search_directory;
|
|
|
|
/* Copy the date and time from the actual sub-directory. */
|
|
sub_dir_entry.fx_dir_entry_time = dir_entry.fx_dir_entry_time;
|
|
sub_dir_entry.fx_dir_entry_date = dir_entry.fx_dir_entry_date;
|
|
|
|
/* Adjust pointer to media name buffer. */
|
|
sub_dir_entry.fx_dir_entry_name = media_ptr -> fx_media_name_buffer + (FX_MAX_LONG_NAME_LEN * 3);
|
|
|
|
/* Change the name to ".." */
|
|
work_ptr = &sub_dir_entry.fx_dir_entry_name[0];
|
|
for (i = 0; i < (FX_DIR_NAME_SIZE + FX_DIR_EXT_SIZE); i++)
|
|
{
|
|
*work_ptr++ = ' ';
|
|
}
|
|
|
|
sub_dir_entry.fx_dir_entry_name[0] = '.';
|
|
sub_dir_entry.fx_dir_entry_name[1] = '.';
|
|
sub_dir_entry.fx_dir_entry_name[2] = 0;
|
|
|
|
sub_dir_entry.fx_dir_entry_long_name_present = 0;
|
|
|
|
/* Set file size to 0. */
|
|
sub_dir_entry.fx_dir_entry_file_size = 0;
|
|
|
|
/* Change the logical sector for this entry. */
|
|
sub_dir_entry.fx_dir_entry_log_sector = logical_sector;
|
|
}
|
|
else
|
|
{
|
|
|
|
/* Just modify the current directory since the parent
|
|
directory is the root. */
|
|
sub_dir_entry.fx_dir_entry_name[1] = '.';
|
|
sub_dir_entry.fx_dir_entry_name[2] = 0;
|
|
|
|
/* Clear the cluster to indicate the root directory. */
|
|
sub_dir_entry.fx_dir_entry_cluster = 0;
|
|
}
|
|
|
|
/* Setup the byte offset. */
|
|
sub_dir_entry.fx_dir_entry_byte_offset = FX_DIR_ENTRY_SIZE;
|
|
|
|
/* Write the directory's second entry. */
|
|
status = _fx_directory_entry_write(media_ptr, &sub_dir_entry);
|
|
|
|
/* Check for error condition. */
|
|
if (status != FX_SUCCESS)
|
|
{
|
|
|
|
#ifdef FX_ENABLE_FAULT_TOLERANT
|
|
FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
|
|
#endif /* FX_ENABLE_FAULT_TOLERANT */
|
|
|
|
/* Release media protection. */
|
|
FX_UNPROTECT
|
|
|
|
/* Return error status. */
|
|
return(status);
|
|
}
|
|
|
|
/* Write an EOF in the found FAT entry. */
|
|
status = _fx_utility_FAT_entry_write(media_ptr, FAT_index, media_ptr -> fx_media_fat_last);
|
|
|
|
/* Check for a bad status. */
|
|
if (status != FX_SUCCESS)
|
|
{
|
|
|
|
#ifdef FX_ENABLE_FAULT_TOLERANT
|
|
FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
|
|
#endif /* FX_ENABLE_FAULT_TOLERANT */
|
|
|
|
/* Release media protection. */
|
|
FX_UNPROTECT
|
|
|
|
/* Return the bad status. */
|
|
return(status);
|
|
}
|
|
|
|
|
|
#ifdef FX_FAULT_TOLERANT
|
|
|
|
/* Flush the cached individual FAT entries */
|
|
_fx_utility_FAT_flush(media_ptr);
|
|
#endif
|
|
|
|
/* Now write out the new directory entry. */
|
|
|
|
status = _fx_directory_entry_write(media_ptr, &dir_entry);
|
|
|
|
#ifdef FX_ENABLE_FAULT_TOLERANT
|
|
/* Check for a bad status. */
|
|
if (status != FX_SUCCESS)
|
|
{
|
|
FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
|
|
|
|
/* Release media protection. */
|
|
FX_UNPROTECT
|
|
|
|
/* Return the bad status. */
|
|
return(status);
|
|
}
|
|
|
|
/* End transaction. */
|
|
status = _fx_fault_tolerant_transaction_end(media_ptr);
|
|
#endif /* FX_ENABLE_FAULT_TOLERANT */
|
|
|
|
/* Release media protection. */
|
|
FX_UNPROTECT
|
|
|
|
/* Directory create is complete, return status. */
|
|
return(status);
|
|
}
|
|
|