mirror of
https://github.com/eclipse-threadx/filex.git
synced 2026-09-13 19:45:58 +08:00
Transition FileX to Eclipse Fundation
This commit is contained in:
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"image": "ghcr.io/tiejunms/azure_rtos_docker",
|
||||
|
||||
// Add the IDs of extensions you want installed when the container is created.
|
||||
"extensions": [
|
||||
"ms-vscode.cpptools",
|
||||
"ms-vscode.cmake-tools"
|
||||
],
|
||||
|
||||
"remoteUser": "vscode",
|
||||
|
||||
"runArgs": [ "--cap-add=NET_ADMIN"]
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
.git* export-ignore
|
||||
.hooks* export-ignore
|
||||
|
||||
# Custom attribute to mark sources as using our C code style.
|
||||
[attr]our-c-style whitespace=tab-in-indent eol=lf format.clang-format-6.0
|
||||
|
||||
# Custom attribute to mark sources as generated.
|
||||
# Do not perform whitespace checks. Do not format.
|
||||
[attr]generated whitespace=-tab-in-indent,-indent-with-non-tab -format.clang-format-6.0
|
||||
|
||||
bootstrap eol=lf
|
||||
configure eol=lf
|
||||
*.[1-9] eol=lf
|
||||
*.bash eol=lf
|
||||
*.sh eol=lf
|
||||
*.sh.in eol=lf
|
||||
|
||||
*.bat eol=crlf
|
||||
*.bat.in eol=crlf
|
||||
*.sln eol=crlf
|
||||
*.vcproj eol=crlf
|
||||
|
||||
*.pfx -text
|
||||
*.png -text
|
||||
*.png.in -text
|
||||
|
||||
*.c our-c-style
|
||||
*.cc our-c-style
|
||||
*.cpp our-c-style
|
||||
*.cu our-c-style
|
||||
*.cxx our-c-style
|
||||
*.h our-c-style
|
||||
*.hh our-c-style
|
||||
*.hpp our-c-style
|
||||
*.hxx our-c-style
|
||||
*.notcu our-c-style
|
||||
|
||||
*.cmake whitespace=tab-in-indent
|
||||
*.rst whitespace=tab-in-indent conflict-marker-size=79
|
||||
*.txt whitespace=tab-in-indent
|
||||
@@ -0,0 +1,35 @@
|
||||
---
|
||||
name: Bug report
|
||||
about: Create a report to help us improve Azure RTOS.
|
||||
title: ''
|
||||
labels: bug
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
**Describe the bug**
|
||||
A clear and concise description of what the bug is.
|
||||
|
||||
Please also mention any information which could help others to understand
|
||||
the problem you're facing:
|
||||
- What target device are you using?
|
||||
- Which version of Azure RTOS?
|
||||
- What toolchain and environment?
|
||||
- What have you tried to diagnose or workaround this issue?
|
||||
|
||||
**To Reproduce**
|
||||
Steps to reproduce the behavior:
|
||||
1. Build my project in IAR Workbench.
|
||||
1. See error
|
||||
|
||||
**Expected behavior**
|
||||
A clear and concise description of what you expected to happen.
|
||||
|
||||
**Impact**
|
||||
What impact does this issue have on your progress (e.g., annoyance, showstopper)
|
||||
|
||||
**Logs and console output**
|
||||
If applicable, add console logs or other types of debug information like Wireshark capture as `.zip` file.
|
||||
|
||||
**Additional context**
|
||||
Add any other context about the problem here.
|
||||
@@ -0,0 +1,20 @@
|
||||
---
|
||||
name: Feature request
|
||||
about: Suggest an idea or enhancement to existing feature for Azure RTOS.
|
||||
title: ''
|
||||
labels: feature
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
**Is your feature request related to a problem? Please describe.**
|
||||
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
|
||||
|
||||
**Describe the solution you'd like**
|
||||
A clear and concise description of what you want to happen.
|
||||
|
||||
**Describe alternatives you've considered**
|
||||
A clear and concise description of any alternative solutions or features you've considered.
|
||||
|
||||
**Additional context**
|
||||
Add any other context or screenshots about the feature request here.
|
||||
@@ -0,0 +1,19 @@
|
||||
---
|
||||
name: Hardware or architecture support
|
||||
about: Suggest adding hardware or new architecture support.
|
||||
title: ''
|
||||
labels: hardware
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
**Is this request related to a particular hardware platform, SoC, board? Please describe.**
|
||||
Describe in details the hardware support being requested and why this support benefits Azure RTOS.
|
||||
|
||||
**Describe why you are asking for this support?**
|
||||
Describe why you are asking for this support.
|
||||
|
||||
If this is a new board or SoC, please state whether you are willing to maintain the Azure RTOS support together with you.
|
||||
|
||||
**Additional context**
|
||||
Add any other context or graphics (drag-and-drop an image) about the hardware here.
|
||||
@@ -0,0 +1,25 @@
|
||||
# This is a basic workflow that is manually triggered
|
||||
|
||||
name: regression_test
|
||||
|
||||
# Controls when the action will run. Triggers the workflow on push or pull request
|
||||
# events but only for the master branch
|
||||
on:
|
||||
workflow_dispatch:
|
||||
push:
|
||||
branches: [ master ]
|
||||
pull_request:
|
||||
branches: [ master ]
|
||||
|
||||
# A workflow run is made up of one or more jobs that can run sequentially or in parallel
|
||||
jobs:
|
||||
# This workflow contains a single job called "linux_job"
|
||||
run_tests:
|
||||
permissions:
|
||||
contents: read
|
||||
issues: read
|
||||
checks: write
|
||||
pull-requests: write
|
||||
pages: write
|
||||
id-token: write
|
||||
uses: azure-rtos/threadx/.github/workflows/regression_template.yml@master
|
||||
Executable
+16
@@ -0,0 +1,16 @@
|
||||
.vscode/
|
||||
_deps/
|
||||
build/
|
||||
coverage_report/
|
||||
CMakeFiles/
|
||||
CMakeScripts/
|
||||
CMakeLists.txt.user
|
||||
CMakeCache.txt
|
||||
Testing
|
||||
Makefile
|
||||
cmake_install.cmake
|
||||
install_manifest.txt
|
||||
compile_commands.json
|
||||
CTestTestfile.cmake
|
||||
.run.sh
|
||||
|
||||
Executable
+77
@@ -0,0 +1,77 @@
|
||||
cmake_minimum_required(VERSION 3.0.0 FATAL_ERROR)
|
||||
|
||||
# Set up the project
|
||||
project(filex
|
||||
LANGUAGES C ASM
|
||||
)
|
||||
|
||||
|
||||
option(FX_STANDALONE_ENABLE "Enable Filex in standalone mode" OFF)
|
||||
|
||||
if(NOT DEFINED THREADX_ARCH)
|
||||
message(FATAL_ERROR "Error: THREADX_ARCH not defined")
|
||||
endif()
|
||||
if(NOT DEFINED THREADX_TOOLCHAIN)
|
||||
message(FATAL_ERROR "Error: THREADX_TOOLCHAIN not defined")
|
||||
endif()
|
||||
|
||||
# Define our target library and an alias for consumers
|
||||
add_library(${PROJECT_NAME})
|
||||
add_library("azrtos::${PROJECT_NAME}" ALIAS ${PROJECT_NAME})
|
||||
|
||||
# Define any required dependencies between this library and others
|
||||
if(NOT FX_STANDALONE_ENABLE)
|
||||
target_link_libraries(${PROJECT_NAME} PUBLIC
|
||||
"azrtos::threadx"
|
||||
)
|
||||
endif()
|
||||
|
||||
# A place for generated/copied include files (no need to change)
|
||||
set(CUSTOM_INC_DIR ${CMAKE_CURRENT_BINARY_DIR}/custom_inc)
|
||||
|
||||
# Pick up the port specific stuff first
|
||||
if(DEFINED FILEX_CUSTOM_PORT)
|
||||
add_subdirectory(${FILEX_CUSTOM_PORT} filex_port)
|
||||
else()
|
||||
add_subdirectory(${CMAKE_CURRENT_LIST_DIR}/ports/${THREADX_ARCH}/${THREADX_TOOLCHAIN})
|
||||
endif()
|
||||
|
||||
# Then the common files
|
||||
add_subdirectory(${CMAKE_CURRENT_LIST_DIR}/common)
|
||||
|
||||
|
||||
|
||||
|
||||
# Include the user's override file if required
|
||||
if (NOT FX_USER_FILE)
|
||||
message(STATUS "Using default fx_user.h file")
|
||||
set(FX_USER_FILE ${CMAKE_CURRENT_LIST_DIR}/common/inc/fx_user_sample.h)
|
||||
else()
|
||||
message(STATUS "Using custom fx_user.h file from ${FX_USER_FILE}")
|
||||
endif()
|
||||
configure_file(${FX_USER_FILE} ${CUSTOM_INC_DIR}/fx_user.h COPYONLY)
|
||||
target_include_directories(${PROJECT_NAME}
|
||||
PUBLIC
|
||||
${CUSTOM_INC_DIR}
|
||||
)
|
||||
|
||||
if(NOT FX_STANDALONE_ENABLE)
|
||||
target_compile_definitions(${PROJECT_NAME} PUBLIC "FX_INCLUDE_USER_DEFINE_FILE" )
|
||||
else()
|
||||
target_compile_definitions(${PROJECT_NAME} PUBLIC "FX_INCLUDE_USER_DEFINE_FILE" -DFX_STANDALONE_ENABLE)
|
||||
endif()
|
||||
|
||||
# Enable a build target that produces a ZIP file of all sources
|
||||
set(CPACK_SOURCE_GENERATOR "ZIP")
|
||||
set(CPACK_SOURCE_IGNORE_FILES
|
||||
\\.git/
|
||||
\\.github/
|
||||
_build/
|
||||
\\.git
|
||||
\\.gitattributes
|
||||
\\.gitignore
|
||||
".*~$"
|
||||
)
|
||||
set(CPACK_VERBATIM_VARIABLES YES)
|
||||
include(CPack)
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
# Contributing
|
||||
|
||||
This project welcomes contributions and suggestions. Most contributions require you to
|
||||
agree to a Contributor License Agreement (CLA) declaring that you have the right to,
|
||||
and actually do, grant us the rights to use your contribution. For details, visit
|
||||
https://cla.microsoft.com.
|
||||
|
||||
When you submit a pull request, a CLA-bot will automatically determine whether you need
|
||||
to provide a CLA and decorate the PR appropriately (e.g., label, comment). Simply follow the
|
||||
instructions provided by the bot. You will only need to do this once across all repositories using our CLA.
|
||||
|
||||
This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/).
|
||||
For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/)
|
||||
or contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments.
|
||||
+249
@@ -0,0 +1,249 @@
|
||||
MICROSOFT SOFTWARE LICENSE TERMS
|
||||
|
||||
MICROSOFT AZURE RTOS
|
||||
|
||||
|
||||
These license terms are an agreement between you and Microsoft Corporation (or
|
||||
one of its affiliates). They apply to the software named above and any Microsoft
|
||||
services or software updates (except to the extent such services or updates are
|
||||
accompanied by new or additional terms, in which case those different terms
|
||||
apply prospectively and do not alter your or Microsoft’s rights relating to
|
||||
pre-updated software or services). IF YOU COMPLY WITH THESE LICENSE TERMS, YOU
|
||||
HAVE THE RIGHTS BELOW. BY USING THE SOFTWARE, YOU ACCEPT THESE TERMS.
|
||||
|
||||
1. INSTALLATION AND USE RIGHTS.
|
||||
|
||||
a) General. You may (I) install, use and modify the software and (ii) install and use the included Microsoft
|
||||
Applications (if any), each solely for internal development, testing and evaluation purposes.
|
||||
Distribution or production use is governed by the license terms set forth in
|
||||
Section 2. You may also obtain distribution or production use rights through a separate agreement with
|
||||
Microsoft.
|
||||
|
||||
b) Contributions. Microsoft welcomes contributions to this software. In the event
|
||||
that you make a contribution to this software you will be required to agree to a
|
||||
Contributor License Agreement (CLA) declaring that you have the right to, and
|
||||
actually do, grant Microsoft the rights to use your contribution. For details,
|
||||
visit https://cla.microsoft.com.
|
||||
|
||||
c) Included Microsoft Applications. The software may include other Microsoft
|
||||
applications which are governed by the licenses embedded in or made available
|
||||
with those applications.
|
||||
|
||||
d) Third Party Components. The software may include third party components with
|
||||
separate legal notices or governed by other agreements, as may be described
|
||||
within the software or in the ThirdPartyNotices file(s) accompanying the
|
||||
software.
|
||||
|
||||
e) Competitive Benchmarking. If you are a direct competitor, and you access or use
|
||||
the software for purposes of competitive benchmarking, analysis, or intelligence
|
||||
gathering, you waive as against Microsoft, its subsidiaries, and its affiliated
|
||||
companies (including prospectively) any competitive use, access, and
|
||||
benchmarking test restrictions in the terms governing your software to the
|
||||
extent your terms of use are, or purport to be, more restrictive than
|
||||
Microsoft’s terms. If you do not waive any such purported restrictions in the
|
||||
terms governing your software, you are not allowed to access or use this
|
||||
software, and will not do so.
|
||||
|
||||
2. DISTRIBUTION AND PRODUCTION USE. If you have obtained and/or are developing on
|
||||
microprocessor(s) and/or microcontroller(s) (“hardware”) listed in the file
|
||||
named “LICENSED-HARDWARE.txt” included in the repository and/or distributed with
|
||||
the software you have the following rights in and to the software solely when
|
||||
used in combination with the hardware. In the event hardware is not listed in
|
||||
the LICENSED-HARDWARE.txt file, you do not have the rights in this Section 2.
|
||||
|
||||
a) Distribution and Production Use Rights.
|
||||
|
||||
i. You may use the software in production (e.g. program the modified or unmodified
|
||||
software to devices you own or control) and distribute (i.e. make available to
|
||||
third parties) the modified or unmodified binary image produced from this code.
|
||||
|
||||
ii. You may permit your device distributors or developers to copy and distribute the
|
||||
binary image as programmed or to be programmed to your devices.
|
||||
|
||||
iii. You may redistribute the unmodified or modified source to your device
|
||||
distributors or developers. Modifications must be clearly marked. Any
|
||||
redistribution in source code form must contain this license and any other
|
||||
licenses that accompany the software.
|
||||
|
||||
b) Requirements. For any code you distribute, you must:
|
||||
|
||||
i. when distributed in binary form, except as embedded in a device, include with
|
||||
such distribution the terms of this agreement;
|
||||
ii. when distributed in source code form to distributors or developers of your
|
||||
devices, include with such distribution the terms of this agreement; and
|
||||
iii. indemnify, defend and hold harmless Microsoft from any claims, including claims arising from any High Risk Uses, and inclusive of attorneys’ fees, related to the distribution or use of your devices that include the software, except to the extent that any intellectual property claim is based solely on the unmodified software.
|
||||
|
||||
c) Restrictions. You may not:
|
||||
i. use or modify the software to create competing real time operating system
|
||||
software;
|
||||
|
||||
ii. remove any copyright notices or licenses contained in the software;
|
||||
|
||||
iii. use Microsoft’s trademarks or trade dress in your application in any way that
|
||||
suggests your device or application comes from or is endorsed by Microsoft;
|
||||
|
||||
iv. transfer individual components, specific libraries, classes, functions or code
|
||||
fragments of the software separately for purposes unrelated to the software; or
|
||||
|
||||
v. use or distribute the software in any way that would subject the software or
|
||||
Microsoft’s intellectual property or technology to any other license terms.
|
||||
|
||||
3. SCOPE OF LICENSE. The software is licensed, not sold. Microsoft reserves all
|
||||
other rights. Unless applicable law gives you more rights despite this
|
||||
limitation, you will not (and have no right to):
|
||||
|
||||
a) remove, minimize, block, or modify any notices of Microsoft or its suppliers in
|
||||
the software;
|
||||
|
||||
b) use the software in any way that is against the law or to create or propagate
|
||||
malware; or
|
||||
|
||||
c) share, publish, distribute, or lease the software (except as permitted in
|
||||
Section 2 above), or provide the software as a stand-alone offering for others
|
||||
to use.
|
||||
|
||||
4. DATA. This software may interact with other Microsoft products that collect data
|
||||
that is transmitted to Microsoft. To learn more about how Microsoft processes
|
||||
personal data we collect, please see the Microsoft Privacy Statement at
|
||||
https://go.microsoft.com/fwlink/?LinkId=248681.
|
||||
|
||||
5. EXPORT RESTRICTIONS. You must comply with all domestic and international export
|
||||
laws and regulations that apply to the software, which include restrictions on
|
||||
destinations, end users, and end use. For further information on export
|
||||
restrictions, visit https://aka.ms/exporting.
|
||||
|
||||
6. SUPPORT SERVICES. Microsoft is not obligated under this agreement to provide any
|
||||
support services for the software. Any support provided is “as is”, “with all
|
||||
faults”, and without warranty of any kind.
|
||||
|
||||
7. UPDATES. Microsoft may periodically update the software. You may obtain updates
|
||||
only from Microsoft or Microsoft-authorized sources. Updates may not include or
|
||||
support all existing software features, services, or peripheral devices.
|
||||
|
||||
8. TERMINATION. Without prejudice to any other rights, Microsoft may terminate this
|
||||
agreement if you fail to comply with any of its terms or conditions. In such
|
||||
event, you must destroy all copies of the software and all of its component
|
||||
parts.
|
||||
|
||||
9. ENTIRE AGREEMENT. This agreement, and any other terms Microsoft may provide for
|
||||
supplements, updates, or third-party applications, is the entire agreement for
|
||||
the software. To the extent you have entered into a separate agreement with
|
||||
Microsoft relating specifically to the software, the terms in such agreement
|
||||
shall control.
|
||||
|
||||
10. APPLICABLE LAW AND PLACE TO RESOLVE DISPUTES. If you acquired the software in
|
||||
the United States or Canada, the laws of the state or province where you live
|
||||
(or, if a business, where your principal place of business is located) govern
|
||||
the interpretation of this agreement, claims for its breach, and all other
|
||||
claims (including consumer protection, unfair competition, and tort claims),
|
||||
regardless of conflict of laws principles. If you acquired the software in any
|
||||
other country, its laws apply. If U.S. federal jurisdiction exists, you and
|
||||
Microsoft consent to exclusive jurisdiction and venue in the federal court in
|
||||
King County, Washington for all disputes heard in court. If not, you and
|
||||
Microsoft consent to exclusive jurisdiction and venue in the Superior Court of
|
||||
King County, Washington for all disputes heard in court.
|
||||
|
||||
11. CONSUMER RIGHTS; REGIONAL VARIATIONS. This agreement describes certain legal
|
||||
rights. You may have other rights, including consumer rights, under the laws of
|
||||
your state or country. Separate and apart from your relationship with Microsoft,
|
||||
you may also have rights with respect to the party from which you acquired the
|
||||
software. This agreement does not change those other rights if the laws of your
|
||||
state or country do not permit it to do so. For example, if you acquired the
|
||||
software in one of the below regions, or mandatory country law applies, then the
|
||||
following provisions apply to you:
|
||||
|
||||
a) Australia. You have statutory guarantees under the Australian Consumer Law and
|
||||
nothing in this agreement is intended to affect those rights.
|
||||
|
||||
b) Germany and Austria.
|
||||
|
||||
i. Warranty. The properly licensed software will perform substantially as
|
||||
described in any Microsoft materials that accompany the software. However,
|
||||
Microsoft gives no contractual guarantee in relation to the licensed software.
|
||||
|
||||
ii. Limitation of Liability. In case of intentional conduct, gross negligence,
|
||||
claims based on the Product Liability Act, as well as, in case of death or
|
||||
personal or physical injury, Microsoft is liable according to the statutory law.
|
||||
|
||||
|
||||
Subject to the foregoing clause ii., Microsoft will only be liable for slight
|
||||
negligence if Microsoft is in breach of such material contractual obligations,
|
||||
the fulfillment of which facilitate the due performance of this agreement, the
|
||||
breach of which would endanger the purpose of this agreement and the compliance
|
||||
with which a party may constantly trust in (so-called "cardinal obligations").
|
||||
In other cases of slight negligence, Microsoft will not be liable for slight
|
||||
negligence.
|
||||
12. DISCLAIMER OF WARRANTY.
|
||||
a) THE SOFTWARE IS LICENSED “AS IS.” YOU BEAR THE RISK OF
|
||||
USING IT. MICROSOFT GIVES NO EXPRESS WARRANTIES, GUARANTEES, OR CONDITIONS. TO
|
||||
THE EXTENT PERMITTED UNDER APPLICABLE LAWS, MICROSOFT EXCLUDES ALL IMPLIED
|
||||
WARRANTIES, INCLUDING MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND
|
||||
NON-INFRINGEMENT.
|
||||
b) HIGH RISK USE DISCLAIMER. WARNING: THE SOFTWARE IS NOT DESIGNED OR INTENDED FOR USE WHERE FAILURE OR FAULT OF ANY KIND OF THE SOFTWARE COULD RESULT IN DEATH OR SERIOUS BODILY INJURY, OR IN PHYSICAL OR ENVIRONMENTAL DAMAGE (“collectively High Risk Use”). Accordingly, You must design and implement your hardware and software such that, in the event of any interruption, defect, error, or other failure of the software, the safety of people, property, and the environment are not reduced below a level that is reasonable, appropriate, and legal, whether in general or for a specific industry. Your High Risk Use of the software is at Your own risk.
|
||||
|
||||
13. LIMITATION ON AND EXCLUSION OF DAMAGES. IF YOU HAVE ANY BASIS FOR RECOVERING
|
||||
DAMAGES DESPITE THE PRECEDING DISCLAIMER OF WARRANTY, YOU CAN RECOVER FROM
|
||||
MICROSOFT AND ITS SUPPLIERS ONLY DIRECT DAMAGES UP TO U.S. $5.00. YOU CANNOT
|
||||
RECOVER ANY OTHER DAMAGES, INCLUDING CONSEQUENTIAL, LOST PROFITS, SPECIAL,
|
||||
INDIRECT, OR INCIDENTAL DAMAGES.
|
||||
|
||||
This limitation applies to (a) anything related to the software, services,
|
||||
content (including code) on third party Internet sites, or third party
|
||||
applications; and (b) claims for breach of contract, warranty, guarantee, or
|
||||
condition; strict liability, negligence, or other tort; or any other claim; in
|
||||
each case to the extent permitted by applicable law.
|
||||
|
||||
It also applies even if Microsoft knew or should have known about the
|
||||
possibility of the damages. The above limitation or exclusion may not apply to
|
||||
you because your state, province, or country may not allow the exclusion or
|
||||
limitation of incidental, consequential, or other damages.
|
||||
|
||||
Please note: As this software is distributed in Canada, some of the clauses in
|
||||
this agreement are provided below in French.
|
||||
|
||||
Remarque: Ce logiciel étant distribué au Canada, certaines des clauses dans ce
|
||||
contrat sont fournies ci-dessous en français.
|
||||
|
||||
EXONÉRATION DE GARANTIE.
|
||||
a) Le logiciel visé par une licence est offert « tel quel
|
||||
». Toute utilisation de ce logiciel est à votre seule risque et péril. Microsoft
|
||||
n’accorde aucune autre garantie expresse. Vous pouvez bénéficier de droits
|
||||
additionnels en vertu du droit local sur la protection des consommateurs, que ce
|
||||
contrat ne peut modifier. La ou elles sont permises par le droit locale, les
|
||||
garanties implicites de qualité marchande, d’adéquation à un usage particulier
|
||||
et d’absence de contrefaçon sont exclues.
|
||||
b) CLAUSE D’EXCLUSION DE RESPONSABILITÉ RELATIVE À L’UTILISATION À HAUT RISQUE.
|
||||
AVERTISSEMENT: LE LOGICIEL N’EST PAS CONÇU OU DESTINÉ À ÊTRE UTILISÉ LORSQU’UNE
|
||||
DÉFAILLANCE OU UN DÉFAUT DE QUELQUE NATURE QUE CE SOIT POURRAIT ENTRAÎNER LA
|
||||
MORT OU DES BLESSURES CORPORELLES GRAVES, OU DES DOMMAGES PHYSIQUES OU
|
||||
ENVIRONNEMENTAUX (« Utilisation à haut risque »). Par conséquent, vous devez concevoir et mettre en
|
||||
œuvre votre équipement et votre logiciel de manière à ce que, en cas d’interruption, de défaut, d’erreur
|
||||
ou de toute autre défaillance du logiciel, la sécurité des personnes, des biens et de l’environnement ne
|
||||
soit pas réduite en dessous d’un niveau raisonnable, approprié et légal, que ce soit en général ou pour
|
||||
un secteur spécifique. Votre utilisation à haut risque du logiciel est à vos propres risques.
|
||||
|
||||
LIMITATION DES DOMMAGES-INTÉRÊTS ET EXCLUSION DE RESPONSABILITÉ POUR LES
|
||||
DOMMAGES. Vous pouvez obtenir de Microsoft et de ses fournisseurs une
|
||||
indemnisation en cas de dommages directs uniquement à hauteur de 5,00 $ US. Vous
|
||||
ne pouvez prétendre à aucune indemnisation pour les autres dommages, y compris
|
||||
les dommages spéciaux, indirects ou accessoires et pertes de bénéfices.
|
||||
|
||||
Cette limitation concerne:
|
||||
|
||||
•tout ce qui est relié au logiciel, aux services ou au contenu (y compris le
|
||||
code) figurant sur des sites Internet tiers ou dans des programmes tiers; et
|
||||
|
||||
•les réclamations au titre de violation de contrat ou de garantie, ou au titre
|
||||
de responsabilité stricte, de négligence ou d’une autre faute dans la limite
|
||||
autorisée par la loi en vigueur.
|
||||
|
||||
Elle s’applique également, même si Microsoft connaissait ou devrait connaître
|
||||
l’éventualité d’un tel dommage. Si votre pays n’autorise pas l’exclusion ou la
|
||||
limitation de responsabilité pour les dommages indirects, accessoires ou de
|
||||
quelque nature que ce soit, il se peut que la limitation ou l’exclusion
|
||||
ci-dessus ne s’appliquera pas à votre égard.
|
||||
|
||||
EFFET JURIDIQUE. Le présent contrat décrit certains droits juridiques. Vous
|
||||
pourriez avoir d’autres droits prévus par les lois de votre pays. Le présent
|
||||
contrat ne modifie pas les droits que vous confèrent les lois de votre pays si
|
||||
celles-ci ne le permettent pas.
|
||||
@@ -0,0 +1,45 @@
|
||||
LICENSED HARDWARE LIST
|
||||
|
||||
Last Updated: 2023-02-10
|
||||
|
||||
Microsoft has entered into OEM Agreements with manufacturers of the following
|
||||
microprocessors and microcontrollers (the “hardware”) to enable those
|
||||
manufacturers to include and distribute Azure RTOS in certain hardware. If you
|
||||
have obtained and/or are developing on microprocessor(s) and/or
|
||||
microcontroller(s) (“hardware”) listed below you inherit the “Distribution and
|
||||
Production Use” rights in Section 2 of the Microsoft Software License Terms for
|
||||
Microsoft Azure RTOS. If hardware is not listed below, you do not have those
|
||||
rights.
|
||||
|
||||
|
||||
STMicroelectronics:
|
||||
|
||||
STM32 MCUs
|
||||
STM32 MPUs
|
||||
|
||||
MediaTek:
|
||||
|
||||
MT3620 MCU (Azure Sphere)
|
||||
|
||||
Microchip:
|
||||
|
||||
PIC 32-bit MCUs
|
||||
SAM 32-bit MCUs
|
||||
SAM 32-bit MPUs
|
||||
|
||||
NXP:
|
||||
|
||||
i.MX RT10xx and RT116x/7x series crossover MCUs
|
||||
LPC5500 series
|
||||
MCX N series
|
||||
|
||||
Renesas:
|
||||
|
||||
Synergy Platform
|
||||
RX Family of MCUs
|
||||
RA Family of MCUs
|
||||
RZ Family of MPUs
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
More coming soon. Please check back frequently for updates.
|
||||
@@ -0,0 +1,152 @@
|
||||
# Azure RTOS FileX
|
||||
|
||||
This is a high-performance, file allocation table (FAT)-compatible file system that’s fully integrated with Azure RTOS ThreadX and available for all supported processors. Like Azure RTOS ThreadX, Azure RTOS FileX is designed to have a small footprint and high performance, making it ideal for today’s deeply embedded applications that require file management operations. FileX supports most physical media, including RAM, Azure RTOS USBX, SD CARD, and NAND/NOR flash memories via Azure RTOS LevelX.
|
||||
|
||||
Here are the key features and modules of FileX:
|
||||
|
||||

|
||||
|
||||
## Getting Started
|
||||
|
||||
Azure RTOS FileX as part of Azure RTOS has been integrated to the semiconductor's SDKs and development environment. You can develop using the tools of choice from [STMicroelectronics](https://www.st.com/content/st_com/en/campaigns/x-cube-azrtos-azure-rtos-stm32.html), [NXP](https://www.nxp.com/design/software/embedded-software/azure-rtos-for-nxp-microcontrollers:AZURE-RTOS), [Renesas](https://github.com/renesas/azure-rtos) and [Microchip](https://mu.microchip.com/get-started-simplifying-your-iot-design-with-azure-rtos).
|
||||
|
||||
We also provide [samples](https://github.com/azure-rtos/samples) using hero development boards from semiconductors you can build and test with.
|
||||
|
||||
See [Overview of Azure RTOS FileX](https://learn.microsoft.com/azure/rtos/filex/overview-filex) for the high-level overview, and all documentation and APIs can be found in: [Azure RTOS FileX documentation](https://learn.microsoft.com/azure/rtos/filex).
|
||||
|
||||
## Repository Structure and Usage
|
||||
|
||||
### Directory layout
|
||||
|
||||
.
|
||||
├── cmake # CMakeList files for building the project
|
||||
├── common # Core FileX files
|
||||
├── ports # Architecture and compiler specific files
|
||||
├── samples # Sample codes
|
||||
├── LICENSE.txt # License terms
|
||||
├── LICENSE-HARDWARE.txt # Licensed hardware from semiconductors
|
||||
├── CONTRIBUTING.md # Contribution guidance
|
||||
└── SECURITY.md # Microsoft repo security guidance
|
||||
|
||||
### Branches & Releases
|
||||
|
||||
The master branch has the most recent code with all new features and bug fixes. It does not represent the latest General Availability (GA) release of the library. Each official release (preview or GA) will be tagged to mark the commit and push it into the Github releases tab, e.g. `v6.2-rel`.
|
||||
|
||||
> When you see xx-xx-xxxx, 6.x or x.x in function header, this means the file is not officially released yet. They will be updated in the next release. See example below.
|
||||
```
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_initialize_low_level Cortex-M23/GNU */
|
||||
/* 6.x */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* Scott Larson, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function is responsible for any low-level processor */
|
||||
/* initialization, including setting up interrupt vectors, setting */
|
||||
/* up a periodic timer interrupt source, saving the system stack */
|
||||
/* pointer for use in ISR processing later, and finding the first */
|
||||
/* available RAM memory address for tx_application_define. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* _tx_initialize_kernel_enter ThreadX entry function */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 09-30-2020 Scott Larson Initial Version 6.1 */
|
||||
/* xx-xx-xxxx Scott Larson Include tx_user.h, */
|
||||
/* resulting in version 6.x */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
```
|
||||
|
||||
## Component dependencies
|
||||
|
||||
The main components of Azure RTOS are each provided in their own repository, but there are dependencies between them, as shown in the following graph. This is important to understand when setting up your builds.
|
||||
|
||||

|
||||
|
||||
> You will have to take the dependency graph above into account when building anything other than ThreadX itself.
|
||||
|
||||
### Building and using the library
|
||||
|
||||
Instruction for building the FileX as static library using Arm GNU Toolchain and CMake. If you are using toolchain and IDE from semiconductor, you might follow its own instructions to use Azure RTOS components as explained in the [Getting Started](#getting-started) section.
|
||||
|
||||
1. Install the following tools:
|
||||
|
||||
* [CMake](https://cmake.org/download/) version 3.0 or later
|
||||
* [Arm GNU Toolchain for arm-none-eabi](https://developer.arm.com/downloads/-/arm-gnu-toolchain-downloads)
|
||||
* [Ninja](https://ninja-build.org/)
|
||||
|
||||
1. Build the [ThreadX library](https://github.com/azure-rtos/threadx#building-and-using-the-library) as the dependency.
|
||||
|
||||
1. Cloning the repo.
|
||||
|
||||
```bash
|
||||
$ git clone https://github.com/azure-rtos/filex.git
|
||||
```
|
||||
|
||||
1. Define the features and addons you need in `fx_user.h` and build together with the component source code. You can refer to [`fx_user_sample.h`](https://github.com/azure-rtos/filex/blob/master/common/inc/fx_user_sample.h) as an example.
|
||||
|
||||
1. Building as a static library
|
||||
|
||||
Each component of Azure RTOS comes with a composable CMake-based build system that supports many different MCUs and host systems. Integrating any of these components into your device app code is as simple as adding a git submodule and then including it in your build using the CMake `add_subdirectory()`.
|
||||
|
||||
While the typical usage pattern is to include FileX into your device code source tree to be built & linked with your code, you can compile this project as a standalone static library to confirm your build is set up correctly.
|
||||
|
||||
An example of building the library for Cortex-M4:
|
||||
|
||||
```bash
|
||||
$ cmake -Bbuild -GNinja -DCMAKE_TOOLCHAIN_FILE=cmake/cortex_m4.cmake .
|
||||
|
||||
$ cmake --build ./build
|
||||
```
|
||||
|
||||
## Professional support
|
||||
|
||||
[Professional support plans](https://azure.microsoft.com/support/options/) are available from Microsoft. For community support and others, see the [Resources](#resources) section below.
|
||||
|
||||
## Licensing
|
||||
|
||||
License terms for using Azure RTOS are defined in the LICENSE.txt file of this repo. Please refer to this file for all definitive licensing information. No additional license fees are required for deploying Azure RTOS on hardware defined in the [LICENSED-HARDWARE.txt](./LICENSED-HARDWARE.txt) file. If you are using hardware not listed in the file or having licensing questions in general, please contact Microsoft directly at https://aka.ms/azrtos-license.
|
||||
|
||||
## Resources
|
||||
|
||||
The following are references to additional Azure RTOS resources:
|
||||
|
||||
- **Product introduction and white papers**: https://azure.com/rtos
|
||||
- **General technical questions**: https://aka.ms/QnA/azure-rtos
|
||||
- **Product issues and bugs, or feature requests**: https://github.com/azure-rtos/filex/issues
|
||||
- **Licensing and sales questions**: https://aka.ms/azrtos-license
|
||||
- **Product roadmap and support policy**: https://aka.ms/azrtos/lts
|
||||
- **Blogs and videos**: http://msiotblog.com and https://aka.ms/iotshow
|
||||
- **Azure RTOS TraceX Installer**: https://aka.ms/azrtos-tracex-installer
|
||||
|
||||
You can also check [previous questions](https://stackoverflow.com/questions/tagged/azure-rtos+filex) or ask new ones on StackOverflow using the `azure-rtos` and `filex` tags.
|
||||
|
||||
## Security
|
||||
|
||||
Azure RTOS provides OEMs with components to secure communication and to create code and data isolation using underlying MCU/MPU hardware protection mechanisms. It is ultimately the responsibility of the device builder to ensure the device fully meets the evolving security requirements associated with its specific use case.
|
||||
|
||||
## Contribution
|
||||
|
||||
Please follow the instructions provided in the [CONTRIBUTING.md](./CONTRIBUTING.md) for the corresponding repository.
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
## Security
|
||||
|
||||
Microsoft takes the security of our software products and services seriously, which includes all source code repositories managed through our GitHub organizations, which include [Microsoft](https://github.com/Microsoft), [Azure](https://github.com/Azure), [DotNet](https://github.com/dotnet), [AspNet](https://github.com/aspnet), [Xamarin](https://github.com/xamarin), and [our GitHub organizations](https://opensource.microsoft.com/).
|
||||
|
||||
If you believe you have found a security vulnerability in any Microsoft-owned repository that meets Microsoft's [Microsoft's definition of a security vulnerability](https://docs.microsoft.com/en-us/previous-versions/tn-archive/cc751383(v=technet.10)), please report it to us as described below.
|
||||
|
||||
## Reporting Security Issues
|
||||
|
||||
**Please do not report security vulnerabilities through public GitHub issues.**
|
||||
|
||||
Instead, please report them to the Microsoft Security Response Center (MSRC) at [https://msrc.microsoft.com/create-report](https://msrc.microsoft.com/create-report).
|
||||
|
||||
If you prefer to submit without logging in, send email to [secure@microsoft.com](mailto:secure@microsoft.com). If possible, encrypt your message with our PGP key; please download it from the the [Microsoft Security Response Center PGP Key page](https://www.microsoft.com/en-us/msrc/pgp-key-msrc).
|
||||
|
||||
You should receive a response within 24 hours. If for some reason you do not, please follow up via email to ensure we received your original message. Additional information can be found at [microsoft.com/msrc](https://www.microsoft.com/msrc).
|
||||
|
||||
Please include the requested information listed below (as much as you can provide) to help us better understand the nature and scope of the possible issue:
|
||||
|
||||
* Type of issue (e.g. buffer overflow, SQL injection, cross-site scripting, etc.)
|
||||
* Full paths of source file(s) related to the manifestation of the issue
|
||||
* The location of the affected source code (tag/branch/commit or direct URL)
|
||||
* Any special configuration required to reproduce the issue
|
||||
* Step-by-step instructions to reproduce the issue
|
||||
* Proof-of-concept or exploit code (if possible)
|
||||
* Impact of the issue, including how an attacker might exploit the issue
|
||||
|
||||
This information will help us triage your report more quickly.
|
||||
|
||||
## Preferred Languages
|
||||
|
||||
We prefer all communications to be in English.
|
||||
|
||||
## Policy
|
||||
|
||||
Microsoft follows the principle of [Coordinated Vulnerability Disclosure](https://www.microsoft.com/en-us/msrc/cvd).
|
||||
@@ -0,0 +1,29 @@
|
||||
# Toolchain settings
|
||||
set(CMAKE_C_COMPILER arm-none-eabi-gcc)
|
||||
set(CMAKE_CXX_COMPILER arm-none-eabi-g++)
|
||||
set(AS arm-none-eabi-as)
|
||||
set(AR arm-none-eabi-ar)
|
||||
set(OBJCOPY arm-none-eabi-objcopy)
|
||||
set(OBJDUMP arm-none-eabi-objdump)
|
||||
set(SIZE arm-none-eabi-size)
|
||||
|
||||
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
|
||||
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
|
||||
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
|
||||
set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)
|
||||
|
||||
# this makes the test compiles use static library option so that we don't need to pre-set linker flags and scripts
|
||||
set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY)
|
||||
|
||||
set(CMAKE_C_FLAGS "${MCPU_FLAGS} ${VFP_FLAGS} ${SPEC_FLAGS} -fdata-sections -ffunction-sections -mlong-calls" CACHE INTERNAL "c compiler flags")
|
||||
set(CMAKE_CXX_FLAGS "${MCPU_FLAGS} ${VFP_FLAGS} -fdata-sections -ffunction-sections -fno-rtti -fno-exceptions -mlong-calls" CACHE INTERNAL "cxx compiler flags")
|
||||
set(CMAKE_ASM_FLAGS "${MCPU_FLAGS} -x assembler-with-cpp" CACHE INTERNAL "asm compiler flags")
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${MCPU_FLAGS} ${LD_FLAGS} -Wl,--gc-sections" CACHE INTERNAL "exe link flags")
|
||||
|
||||
SET(CMAKE_C_FLAGS_DEBUG "-Og -g -ggdb3" CACHE INTERNAL "c debug compiler flags")
|
||||
SET(CMAKE_CXX_FLAGS_DEBUG "-Og -g -ggdb3" CACHE INTERNAL "cxx debug compiler flags")
|
||||
SET(CMAKE_ASM_FLAGS_DEBUG "-g -ggdb3" CACHE INTERNAL "asm debug compiler flags")
|
||||
|
||||
SET(CMAKE_C_FLAGS_RELEASE "-O3" CACHE INTERNAL "c release compiler flags")
|
||||
SET(CMAKE_CXX_FLAGS_RELEASE "-O3" CACHE INTERNAL "cxx release compiler flags")
|
||||
SET(CMAKE_ASM_FLAGS_RELEASE "" CACHE INTERNAL "asm release compiler flags")
|
||||
@@ -0,0 +1,13 @@
|
||||
# Name of the target
|
||||
set(CMAKE_SYSTEM_NAME Generic)
|
||||
set(CMAKE_SYSTEM_PROCESSOR cortex-m0)
|
||||
|
||||
set(THREADX_ARCH "cortex_m0")
|
||||
set(THREADX_TOOLCHAIN "gnu")
|
||||
|
||||
set(MCPU_FLAGS "-mthumb -mcpu=cortex-m0")
|
||||
set(VFP_FLAGS "")
|
||||
set(SPEC_FLAGS "--specs=nosys.specs")
|
||||
# set(LD_FLAGS "-nostartfiles")
|
||||
|
||||
include(${CMAKE_CURRENT_LIST_DIR}/arm-none-eabi.cmake)
|
||||
@@ -0,0 +1,13 @@
|
||||
# Name of the target
|
||||
set(CMAKE_SYSTEM_NAME Generic)
|
||||
set(CMAKE_SYSTEM_PROCESSOR cortex-m3)
|
||||
|
||||
set(THREADX_ARCH "cortex_m3")
|
||||
set(THREADX_TOOLCHAIN "gnu")
|
||||
|
||||
set(MCPU_FLAGS "-mthumb -mcpu=cortex-m3")
|
||||
set(VFP_FLAGS "")
|
||||
set(SPEC_FLAGS "--specs=nosys.specs")
|
||||
# set(LD_FLAGS "-nostartfiles")
|
||||
|
||||
include(${CMAKE_CURRENT_LIST_DIR}/arm-none-eabi.cmake)
|
||||
@@ -0,0 +1,13 @@
|
||||
# Name of the target
|
||||
set(CMAKE_SYSTEM_NAME Generic)
|
||||
set(CMAKE_SYSTEM_PROCESSOR cortex-m4)
|
||||
|
||||
set(THREADX_ARCH "cortex_m4")
|
||||
set(THREADX_TOOLCHAIN "gnu")
|
||||
|
||||
set(MCPU_FLAGS "-mthumb -mcpu=cortex-m4")
|
||||
set(VFP_FLAGS "")
|
||||
set(SPEC_FLAGS "--specs=nosys.specs")
|
||||
# set(LD_FLAGS "-nostartfiles")
|
||||
|
||||
include(${CMAKE_CURRENT_LIST_DIR}/arm-none-eabi.cmake)
|
||||
@@ -0,0 +1,13 @@
|
||||
# Name of the target
|
||||
set(CMAKE_SYSTEM_NAME Generic)
|
||||
set(CMAKE_SYSTEM_PROCESSOR cortex-m7)
|
||||
|
||||
set(THREADX_ARCH "cortex_m7")
|
||||
set(THREADX_TOOLCHAIN "gnu")
|
||||
|
||||
set(MCPU_FLAGS "-mthumb -mcpu=cortex-m7")
|
||||
set(VFP_FLAGS "")
|
||||
set(SPEC_FLAGS "--specs=nosys.specs")
|
||||
# set(LD_FLAGS "-nostartfiles")
|
||||
|
||||
include(${CMAKE_CURRENT_LIST_DIR}/arm-none-eabi.cmake)
|
||||
@@ -0,0 +1,15 @@
|
||||
# Add the required subdirectory and register it for linkage
|
||||
function(add_azrtos_component_dir dirname)
|
||||
# Store the current list in a temp
|
||||
set(tmp ${azrtos_targets})
|
||||
# Add the subdir
|
||||
add_subdirectory(${CMAKE_CURRENT_LIST_DIR}/lib/${dirname})
|
||||
# If there is a linker script defined, use it
|
||||
if(EXISTS ${LINKER_SCRIPT})
|
||||
target_link_options(${dirname} INTERFACE -T ${LINKER_SCRIPT})
|
||||
endif()
|
||||
# Add this target into the temp
|
||||
list(APPEND tmp "azrtos::${dirname}")
|
||||
# Copy the temp back up to the parent list
|
||||
set(azrtos_targets ${tmp} PARENT_SCOPE)
|
||||
endfunction()
|
||||
@@ -0,0 +1,221 @@
|
||||
target_sources(${PROJECT_NAME} PRIVATE
|
||||
# {{BEGIN_TARGET_SOURCES}}
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fx_directory_attributes_read.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fx_directory_attributes_set.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fx_directory_create.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fx_directory_default_get.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fx_directory_default_get_copy.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fx_directory_default_set.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fx_directory_delete.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fx_directory_entry_read.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fx_directory_entry_write.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fx_directory_first_entry_find.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fx_directory_first_full_entry_find.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fx_directory_free_search.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fx_directory_information_get.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fx_directory_local_path_clear.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fx_directory_local_path_get.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fx_directory_local_path_get_copy.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fx_directory_local_path_restore.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fx_directory_local_path_set.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fx_directory_long_name_get.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fx_directory_long_name_get_extended.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fx_directory_name_extract.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fx_directory_name_test.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fx_directory_next_entry_find.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fx_directory_next_full_entry_find.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fx_directory_rename.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fx_directory_search.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fx_directory_short_name_get.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fx_directory_short_name_get_extended.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fx_fault_tolerant_add_FAT_log.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fx_fault_tolerant_add_bitmap_log.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fx_fault_tolerant_add_checksum_log.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fx_fault_tolerant_add_dir_log.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fx_fault_tolerant_apply_logs.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fx_fault_tolerant_calculate_checksum.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fx_fault_tolerant_cleanup_FAT_chain.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fx_fault_tolerant_create_log_file.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fx_fault_tolerant_enable.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fx_fault_tolerant_read_FAT.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fx_fault_tolerant_read_directory_sector.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fx_fault_tolerant_read_log_file.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fx_fault_tolerant_recover.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fx_fault_tolerant_reset_log_file.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fx_fault_tolerant_set_FAT_chain.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fx_fault_tolerant_transaction_end.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fx_fault_tolerant_transaction_fail.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fx_fault_tolerant_transaction_start.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fx_fault_tolerant_write_log_file.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fx_file_allocate.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fx_file_attributes_read.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fx_file_attributes_set.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fx_file_best_effort_allocate.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fx_file_close.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fx_file_create.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fx_file_date_time_set.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fx_file_delete.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fx_file_extended_allocate.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fx_file_extended_best_effort_allocate.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fx_file_extended_relative_seek.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fx_file_extended_seek.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fx_file_extended_truncate.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fx_file_extended_truncate_release.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fx_file_open.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fx_file_read.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fx_file_relative_seek.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fx_file_rename.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fx_file_seek.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fx_file_truncate.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fx_file_truncate_release.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fx_file_write.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fx_file_write_notify_set.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fx_media_abort.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fx_media_boot_info_extract.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fx_media_cache_invalidate.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fx_media_check.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fx_media_check_FAT_chain_check.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fx_media_check_lost_cluster_check.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fx_media_close.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fx_media_close_notify_set.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fx_media_extended_space_available.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fx_media_flush.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fx_media_format.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fx_media_format_oem_name_set.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fx_media_format_type_set.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fx_media_format_volume_id_set.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fx_media_open.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fx_media_open_notify_set.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fx_media_read.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fx_media_space_available.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fx_media_volume_get.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fx_media_volume_get_extended.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fx_media_volume_set.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fx_media_write.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fx_partition_offset_calculate.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fx_ram_driver.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fx_system_date_get.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fx_system_date_set.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fx_system_initialize.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fx_system_time_get.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fx_system_time_set.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fx_system_timer_entry.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fx_trace_event_insert.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fx_trace_event_update.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fx_trace_object_register.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fx_trace_object_unregister.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fx_unicode_directory_create.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fx_unicode_directory_entry_change.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fx_unicode_directory_entry_read.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fx_unicode_directory_rename.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fx_unicode_directory_search.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fx_unicode_file_create.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fx_unicode_file_rename.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fx_unicode_length_get.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fx_unicode_length_get_extended.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fx_unicode_name_get.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fx_unicode_name_get_extended.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fx_unicode_short_name_get.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fx_unicode_short_name_get_extended.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fx_utility_16_unsigned_read.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fx_utility_16_unsigned_write.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fx_utility_32_unsigned_read.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fx_utility_32_unsigned_write.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fx_utility_64_unsigned_read.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fx_utility_64_unsigned_write.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fx_utility_FAT_entry_read.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fx_utility_FAT_entry_write.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fx_utility_FAT_flush.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fx_utility_FAT_map_flush.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fx_utility_FAT_sector_get.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fx_utility_absolute_path_get.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fx_utility_logical_sector_cache_entry_read.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fx_utility_logical_sector_flush.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fx_utility_logical_sector_read.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fx_utility_logical_sector_write.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fx_utility_memory_copy.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fx_utility_memory_set.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fx_utility_string_length_get.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fx_utility_token_length_get.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fxe_directory_attributes_read.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fxe_directory_attributes_set.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fxe_directory_create.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fxe_directory_default_get.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fxe_directory_default_get_copy.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fxe_directory_default_set.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fxe_directory_delete.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fxe_directory_first_entry_find.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fxe_directory_first_full_entry_find.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fxe_directory_information_get.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fxe_directory_local_path_clear.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fxe_directory_local_path_get.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fxe_directory_local_path_get_copy.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fxe_directory_local_path_restore.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fxe_directory_local_path_set.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fxe_directory_long_name_get.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fxe_directory_long_name_get_extended.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fxe_directory_name_test.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fxe_directory_next_entry_find.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fxe_directory_next_full_entry_find.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fxe_directory_rename.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fxe_directory_short_name_get.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fxe_directory_short_name_get_extended.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fxe_fault_tolerant_enable.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fxe_file_allocate.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fxe_file_attributes_read.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fxe_file_attributes_set.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fxe_file_best_effort_allocate.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fxe_file_close.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fxe_file_create.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fxe_file_date_time_set.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fxe_file_delete.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fxe_file_extended_allocate.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fxe_file_extended_best_effort_allocate.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fxe_file_extended_relative_seek.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fxe_file_extended_seek.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fxe_file_extended_truncate.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fxe_file_extended_truncate_release.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fxe_file_open.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fxe_file_read.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fxe_file_relative_seek.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fxe_file_rename.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fxe_file_seek.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fxe_file_truncate.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fxe_file_truncate_release.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fxe_file_write.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fxe_file_write_notify_set.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fxe_media_abort.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fxe_media_cache_invalidate.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fxe_media_check.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fxe_media_close.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fxe_media_close_notify_set.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fxe_media_extended_space_available.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fxe_media_flush.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fxe_media_format.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fxe_media_open.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fxe_media_open_notify_set.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fxe_media_read.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fxe_media_space_available.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fxe_media_volume_get.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fxe_media_volume_get_extended.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fxe_media_volume_set.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fxe_media_write.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fxe_system_date_get.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fxe_system_date_set.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fxe_system_time_get.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fxe_system_time_set.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fxe_unicode_directory_create.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fxe_unicode_directory_rename.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fxe_unicode_file_create.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fxe_unicode_file_rename.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fxe_unicode_name_get.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fxe_unicode_name_get_extended.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fxe_unicode_short_name_get.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fxe_unicode_short_name_get_extended.c
|
||||
|
||||
# {{END_TARGET_SOURCES}}
|
||||
)
|
||||
|
||||
target_include_directories(${PROJECT_NAME} PUBLIC
|
||||
${CMAKE_CURRENT_LIST_DIR}/inc
|
||||
)
|
||||
+1539
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,122 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** FileX Component */
|
||||
/** */
|
||||
/** Directory */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* COMPONENT DEFINITION RELEASE */
|
||||
/* */
|
||||
/* fx_directory.h PORTABLE C */
|
||||
/* 6.1 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This file defines the FileX Directory component constants, data */
|
||||
/* definitions, and external references. It is assumed that fx_api.h */
|
||||
/* (and fx_port.h) have already been included. */
|
||||
/* */
|
||||
/* 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 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
#ifndef FX_DIRECTORY_H
|
||||
#define FX_DIRECTORY_H
|
||||
|
||||
|
||||
/* Define the external Directory component function prototypes. */
|
||||
|
||||
UINT _fx_directory_attributes_read(FX_MEDIA *media_ptr, CHAR *directory_name, UINT *attributes_ptr);
|
||||
UINT _fx_directory_attributes_set(FX_MEDIA *media_ptr, CHAR *directory_name, UINT attributes);
|
||||
UINT _fx_directory_create(FX_MEDIA *media_ptr, CHAR *directory_name);
|
||||
UINT _fx_directory_default_get(FX_MEDIA *media_ptr, CHAR **return_path_name);
|
||||
UINT _fx_directory_default_get_copy(FX_MEDIA *media_ptr, CHAR *return_path_name_buffer, UINT return_path_name_buffer_size);
|
||||
UINT _fx_directory_default_set(FX_MEDIA *media_ptr, CHAR *new_path_name);
|
||||
UINT _fx_directory_delete(FX_MEDIA *media_ptr, CHAR *directory_name);
|
||||
UINT _fx_directory_entry_read_FAT(FX_MEDIA *media_ptr, FX_DIR_ENTRY *source_dir, ULONG *entry_ptr,
|
||||
FX_DIR_ENTRY *destination_ptr);
|
||||
UINT _fx_directory_first_entry_find(FX_MEDIA *media_ptr, CHAR *directory_name);
|
||||
UINT _fx_directory_first_full_entry_find(FX_MEDIA *media_ptr, CHAR *directory_name, UINT *attributes,
|
||||
ULONG *size, UINT *year, UINT *month, UINT *day, UINT *hour, UINT *minute, UINT *second);
|
||||
UINT _fx_directory_information_get(FX_MEDIA *media_ptr, CHAR *directory_name, UINT *attributes, ULONG *size,
|
||||
UINT *year, UINT *month, UINT *day, UINT *hour, UINT *minute, UINT *second);
|
||||
UINT _fx_directory_local_path_clear(FX_MEDIA *media_ptr);
|
||||
UINT _fx_directory_local_path_get(FX_MEDIA *media_ptr, CHAR **return_path_name);
|
||||
UINT _fx_directory_local_path_get_copy(FX_MEDIA *media_ptr, CHAR *return_path_name_buffer, UINT return_path_name_buffer_size);
|
||||
UINT _fx_directory_local_path_restore(FX_MEDIA *media_ptr, FX_LOCAL_PATH *local_path_ptr);
|
||||
UINT _fx_directory_local_path_set(FX_MEDIA *media_ptr, FX_LOCAL_PATH *local_path_ptr, CHAR *new_path_name);
|
||||
UINT _fx_directory_long_name_get(FX_MEDIA *media_ptr, CHAR *short_file_name, CHAR *long_file_name);
|
||||
UINT _fx_directory_long_name_get_extended(FX_MEDIA *media_ptr, CHAR *short_file_name, CHAR *long_file_name, UINT long_file_name_buffer_length);
|
||||
UINT _fx_directory_name_test(FX_MEDIA *media_ptr, CHAR *directory_name);
|
||||
UINT _fx_directory_next_entry_find(FX_MEDIA *media_ptr, CHAR *directory_name);
|
||||
UINT _fx_directory_next_full_entry_find(FX_MEDIA *media_ptr, CHAR *directory_name, UINT *attributes,
|
||||
ULONG *size, UINT *year, UINT *month, UINT *day, UINT *hour, UINT *minute, UINT *second);
|
||||
UINT _fx_directory_rename(FX_MEDIA *media_ptr, CHAR *old_directory_name, CHAR *new_directory_name);
|
||||
UINT _fx_directory_short_name_get(FX_MEDIA *media_ptr, CHAR *long_file_name, CHAR *short_file_name);
|
||||
UINT _fx_directory_short_name_get_extended(FX_MEDIA *media_ptr, CHAR *long_file_name, CHAR *short_file_name, UINT short_file_name_length);
|
||||
|
||||
UINT _fxe_directory_attributes_read(FX_MEDIA *media_ptr, CHAR *directory_name, UINT *attributes_ptr);
|
||||
UINT _fxe_directory_attributes_set(FX_MEDIA *media_ptr, CHAR *directory_name, UINT attributes);
|
||||
UINT _fxe_directory_create(FX_MEDIA *media_ptr, CHAR *directory_name);
|
||||
UINT _fxe_directory_default_get(FX_MEDIA *media_ptr, CHAR **return_path_name);
|
||||
UINT _fxe_directory_default_get_copy(FX_MEDIA *media_ptr, CHAR *return_path_name_buffer, UINT return_path_name_buffer_size);
|
||||
UINT _fxe_directory_default_set(FX_MEDIA *media_ptr, CHAR *new_path_name);
|
||||
UINT _fxe_directory_delete(FX_MEDIA *media_ptr, CHAR *directory_name);
|
||||
UINT _fxe_directory_first_entry_find(FX_MEDIA *media_ptr, CHAR *directory_name);
|
||||
UINT _fxe_directory_first_full_entry_find(FX_MEDIA *media_ptr, CHAR *directory_name, UINT *attributes,
|
||||
ULONG *size, UINT *year, UINT *month, UINT *day, UINT *hour, UINT *minute, UINT *second);
|
||||
UINT _fxe_directory_information_get(FX_MEDIA *media_ptr, CHAR *directory_name, UINT *attributes, ULONG *size,
|
||||
UINT *year, UINT *month, UINT *day, UINT *hour, UINT *minute, UINT *second);
|
||||
UINT _fxe_directory_local_path_clear(FX_MEDIA *media_ptr);
|
||||
UINT _fxe_directory_local_path_get(FX_MEDIA *media_ptr, CHAR **return_path_name);
|
||||
UINT _fxe_directory_local_path_get_copy(FX_MEDIA *media_ptr, CHAR *return_path_name_buffer, UINT return_path_name_buffer_size);
|
||||
UINT _fxe_directory_local_path_restore(FX_MEDIA *media_ptr, FX_LOCAL_PATH *local_path_ptr);
|
||||
UINT _fxe_directory_local_path_set(FX_MEDIA *media_ptr, FX_LOCAL_PATH *local_path_ptr, CHAR *new_path_name, UINT local_path_control_block_size);
|
||||
UINT _fxe_directory_long_name_get(FX_MEDIA *media_ptr, CHAR *short_file_name, CHAR *long_file_name);
|
||||
UINT _fxe_directory_long_name_get_extended(FX_MEDIA *media_ptr, CHAR *short_file_name, CHAR *long_file_name, UINT long_file_name_buffer_length);
|
||||
UINT _fxe_directory_name_test(FX_MEDIA *media_ptr, CHAR *directory_name);
|
||||
UINT _fxe_directory_next_entry_find(FX_MEDIA *media_ptr, CHAR *directory_name);
|
||||
UINT _fxe_directory_next_full_entry_find(FX_MEDIA *media_ptr, CHAR *directory_name, UINT *attributes,
|
||||
ULONG *size, UINT *year, UINT *month, UINT *day, UINT *hour, UINT *minute, UINT *second);
|
||||
UINT _fxe_directory_rename(FX_MEDIA *media_ptr, CHAR *old_directory_name, CHAR *new_directory_name);
|
||||
UINT _fxe_directory_short_name_get(FX_MEDIA *media_ptr, CHAR *long_file_name, CHAR *short_file_name);
|
||||
UINT _fxe_directory_short_name_get_extended(FX_MEDIA *media_ptr, CHAR *long_file_name, CHAR *short_file_name, UINT short_file_name_length);
|
||||
|
||||
|
||||
/* Define the internal Directory component function prototypes. */
|
||||
|
||||
UINT _fx_directory_entry_read(FX_MEDIA *media_ptr, FX_DIR_ENTRY *source_dir, ULONG *entry, FX_DIR_ENTRY *destination_ptr);
|
||||
UINT _fx_directory_entry_write(FX_MEDIA *media_ptr, FX_DIR_ENTRY *entry_ptr);
|
||||
UINT _fx_directory_free_search(FX_MEDIA *media_ptr, FX_DIR_ENTRY *directory_ptr, FX_DIR_ENTRY *entry_ptr);
|
||||
CHAR *_fx_directory_name_extract(CHAR *source_ptr, CHAR *dest_ptr);
|
||||
UINT _fx_directory_search(FX_MEDIA *media_ptr, CHAR *name_ptr, FX_DIR_ENTRY *entry_ptr, FX_DIR_ENTRY *last_dir_ptr, CHAR **last_name_ptr);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,407 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** FileX Component */
|
||||
/** */
|
||||
/** Fault Tolerant */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* COMPONENT DEFINITION RELEASE */
|
||||
/* */
|
||||
/* fx_fault_tolerant.h PORTABLE C */
|
||||
/* 6.1 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This file defines the FileX Fault Tolerant component constants, */
|
||||
/* data definitions, and external references. It is assumed that */
|
||||
/* fx_api.h (and fx_port.h) have already been included. */
|
||||
/* */
|
||||
/* 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 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
#ifndef _FX_FAULT_TOLERANT_H_
|
||||
#define _FX_FAULT_TOLERANT_H_
|
||||
|
||||
#ifdef FX_ENABLE_FAULT_TOLERANT
|
||||
|
||||
#ifndef FX_FAULT_TOLERANT
|
||||
#error "FX_FAULT_TOLERANT must be defined with FX_ENABLE_FAULT_TOLERANT"
|
||||
#endif /* FX_FAULT_TOLERANT */
|
||||
|
||||
/* Define ID of fault tolerant. */
|
||||
#define FX_FAULT_TOLERANT_ID 0x46544C52
|
||||
|
||||
/* Define fault tolerant version. */
|
||||
#define FX_FAULT_TOLERANT_VERSION_MAJOR 0x01
|
||||
#define FX_FAULT_TOLERANT_VERSION_MINOR 0x00
|
||||
|
||||
/* Define byte offset in boot sector where the cluster number of the Fault Tolerant Log file is.
|
||||
Note that this field (byte 116 to 119) is marked as reserved by FAT 12/16/32 specification. */
|
||||
#ifndef FX_FAULT_TOLERANT_BOOT_INDEX
|
||||
#define FX_FAULT_TOLERANT_BOOT_INDEX 116
|
||||
#endif /* FX_FAULT_TOLERANT_BOOT_INDEX */
|
||||
|
||||
/* Define the extension invoked when fault tolerant log is recovered or applied during enable API. */
|
||||
#ifndef FX_FAULT_TOLERANT_ENABLE_EXTENSION
|
||||
#define FX_FAULT_TOLERANT_ENABLE_EXTENSION
|
||||
#endif /* FX_FAULT_TOLERANT_ENABLE_EXTENSION */
|
||||
|
||||
/* Define the extension invoked when fault tolerant log is applied. */
|
||||
#ifndef FX_FAULT_TOLERANT_APPLY_LOGS_EXTENSION
|
||||
#define FX_FAULT_TOLERANT_APPLY_LOGS_EXTENSION
|
||||
#endif /* FX_FAULT_TOLERANT_APPLY_LOGS_EXTENSION */
|
||||
|
||||
/* If not-defined, default port-specific processing extensions to white space. */
|
||||
#ifndef FX_FAULT_TOLERANT_WRITE_LOG_FILE_EXTENSION
|
||||
#define FX_FAULT_TOLERANT_WRITE_LOG_FILE_EXTENSION
|
||||
#endif /* FX_FAULT_TOLERANT_WRITE_LOG_FILE_EXTENSION */
|
||||
|
||||
/* Define the maximum size of log file. */
|
||||
#define FX_FAULT_TOLERANT_MAXIMUM_LOG_FILE_SIZE 3072
|
||||
|
||||
/* For backward compatibility, map the symbols deprecated to FX_FAULT_TOLERANT_MINIMAL_BUFFER_SIZE. */
|
||||
#ifndef FX_FAULT_TOLERANT_MINIMAL_CLUSTER
|
||||
#define FX_FAULT_TOLERANT_MINIMAL_CLUSTER FX_FAULT_TOLERANT_MAXIMUM_LOG_FILE_SIZE
|
||||
#endif /* FX_FAULT_TOLERANT_MINIMAL_CLUSTER */
|
||||
#ifndef FX_FAULT_TOLERANT_MINIMAL_BUFFER_SIZE
|
||||
#define FX_FAULT_TOLERANT_MINIMAL_BUFFER_SIZE FX_FAULT_TOLERANT_MAXIMUM_LOG_FILE_SIZE
|
||||
#endif /* FX_FAULT_TOLERANT_MINIMAL_BUFFER_SIZE */
|
||||
|
||||
/* Define the states of the fault tolerant module. */
|
||||
#define FX_FAULT_TOLERANT_STATE_IDLE 0x00u
|
||||
#define FX_FAULT_TOLERANT_STATE_STARTED 0x01u
|
||||
#define FX_FAULT_TOLERANT_STATE_SET_FAT_CHAIN 0x02u
|
||||
|
||||
/* Define types of logs. */
|
||||
#define FX_FAULT_TOLERANT_FAT_LOG_TYPE 1
|
||||
#define FX_FAULT_TOLERANT_DIR_LOG_TYPE 2
|
||||
#define FX_FAULT_TOLERANT_BITMAP_LOG_TYPE 3
|
||||
|
||||
/* Define operations of FAT chain. */
|
||||
#define FX_FAULT_TOLERANT_FAT_CHAIN_RECOVER 0 /* Recover new FAT chain. */
|
||||
#define FX_FAULT_TOLERANT_FAT_CHAIN_CLEANUP 1 /* Cleanup old FAT chain. */
|
||||
|
||||
/* Define flags for FAT chain log. */
|
||||
#define FX_FAULT_TOLERANT_FLAG_FAT_CHAIN_VALID 0x01
|
||||
#define FX_FAULT_TOLERANT_FLAG_BITMAP_USED 0x02
|
||||
|
||||
/* Define size of each section in log file. */
|
||||
#define FX_FAULT_TOLERANT_LOG_HEADER_SIZE sizeof(FX_FAULT_TOLERANT_LOG_HEADER)
|
||||
#define FX_FAULT_TOLERANT_FAT_CHAIN_SIZE sizeof(FX_FAULT_TOLERANT_FAT_CHAIN)
|
||||
#define FX_FAULT_TOLERANT_LOG_CONTENT_HEADER_SIZE sizeof(FX_FAULT_TOLERANT_LOG_CONTENT)
|
||||
|
||||
/* Define offset of each section in log file. */
|
||||
#define FX_FAULT_TOLERANT_FAT_CHAIN_OFFSET (FX_FAULT_TOLERANT_LOG_HEADER_SIZE)
|
||||
#define FX_FAULT_TOLERANT_LOG_CONTENT_OFFSET (FX_FAULT_TOLERANT_LOG_HEADER_SIZE + FX_FAULT_TOLERANT_FAT_CHAIN_SIZE)
|
||||
|
||||
/* Define size of log entries. */
|
||||
/* The total size of DIR log entry is variable. 16 is the fixed size of DIR log entry. */
|
||||
#define FX_FAULT_TOLERANT_FAT_LOG_ENTRY_SIZE sizeof(FX_FAULT_TOLERANT_FAT_LOG)
|
||||
#define FX_FAULT_TOLERANT_BITMAP_LOG_ENTRY_SIZE sizeof(FX_FAULT_TOLERANT_BITMAP_LOG)
|
||||
#define FX_FAULT_TOLERANT_DIR_LOG_ENTRY_SIZE sizeof(FX_FAULT_TOLERANT_DIR_LOG)
|
||||
|
||||
#ifdef FX_FAULT_TOLERANT_TRANSACTION_FAIL_FUNCTION
|
||||
#define FX_FAULT_TOLERANT_TRANSACTION_FAIL _fx_fault_tolerant_transaction_fail
|
||||
#else
|
||||
/* Define transaction fail for fault tolerant. */
|
||||
#define FX_FAULT_TOLERANT_TRANSACTION_FAIL(m) \
|
||||
if ((m) -> fx_media_fault_tolerant_enabled == FX_TRUE) \
|
||||
{ \
|
||||
(m) -> fx_media_fault_tolerant_transaction_count--; \
|
||||
if ((m) -> fx_media_fault_tolerant_transaction_count == 0) \
|
||||
{ \
|
||||
_fx_fault_tolerant_recover(m); \
|
||||
_fx_fault_tolerant_reset_log_file(m); \
|
||||
} \
|
||||
}
|
||||
|
||||
#endif /* FX_FAULT_TOLERANT_TRANSACTION_FAIL_FUNCTION */
|
||||
|
||||
/* Log file format
|
||||
* The entire log file fits into one cluster.
|
||||
*
|
||||
* 1 2 3
|
||||
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
|
||||
* ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
* + ID +
|
||||
* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
* + Total Log Size (in Bytes) + Header Checksum + Log Header
|
||||
* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
* + version major + version minor + reserved +
|
||||
* ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
* + Checksum of FAT chain + Flag | Reserved +
|
||||
* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
* + Insertion Point - Front +
|
||||
* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
* + Head cluster of newly created FAT chain +
|
||||
* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ FAT Chain
|
||||
* + Head cluster of original FAT chain +
|
||||
* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
* + Insertion Point - Back +
|
||||
* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
* + Next Deletion Point +
|
||||
* ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
* + checksum of log content + count of log entries +
|
||||
* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
* + (log 0) . +
|
||||
* + . +
|
||||
* + . +
|
||||
* + . +
|
||||
* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
* + (log 1) . +
|
||||
* + . + Log Entries
|
||||
* + . +
|
||||
* + . +
|
||||
* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
* + ... +
|
||||
* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
* + (log N) . +
|
||||
* + . +
|
||||
* + . +
|
||||
* + . +
|
||||
* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
*
|
||||
*
|
||||
* Log Header
|
||||
*
|
||||
* * ID: It is fixed value FX_FAULT_TOLERANT_ID.
|
||||
* * Total Size: Total size (in bytes) of the log file, including Log Header, FAT Chain and Log Entries
|
||||
* * Header Checksum: It is the checksum of all data in log header.
|
||||
* * Version Major: The major version number.
|
||||
* * Version Minor: The minor version number.
|
||||
* * Reserved: Reserved for future use.
|
||||
*
|
||||
* FAT Chain
|
||||
*
|
||||
* * Checksum of FAT chain: It is the checksum of all data in the FAT Chain section.
|
||||
* * Flag: 8 bits. The 1-6 bits are not used (from left to right).
|
||||
* bit 7: When set, bitmap is used in old FAT chain.
|
||||
* bit 8: When set, FAT chain is valid.
|
||||
* * Reserved: Reserved for future use.
|
||||
* * Insertion Point - Front: The cluster where the newly created chain is attached to
|
||||
* * Head cluster of new FAT chain. It is the head cluster of new FAT chain.
|
||||
* * Head cluster of oritinal FAT chain. It is the head cluster of the original FAT chain,
|
||||
* which will be removed.
|
||||
* * Inswertion Point - Back: The original cluster right after the newly created chain is inserted.
|
||||
* * Next Deletion Point: next session of cluster to delete. It is used during deleting FAT chain.
|
||||
* The deltion is carried out in stages for perofmrance reasons. When delting a FAT chain, the
|
||||
* Next Deletion Point is chosen, and the chain between head and the Next Deletion Point is deleted.
|
||||
*
|
||||
* Log Entries:
|
||||
*
|
||||
* * Checksum of log entries: It is the checksum of all data in Log Entries
|
||||
* * Counter of log entries: It is the counter of all log entries in Log content.
|
||||
* * log 0 ... log N: Log entries. The formats are described below.
|
||||
*/
|
||||
|
||||
/* Defined structure of log header.
|
||||
|
||||
|
||||
*/
|
||||
typedef struct FX_FAULT_TOLERANT_LOG_HEADER_STRUCT
|
||||
{
|
||||
ULONG fx_fault_tolerant_log_header_id;
|
||||
USHORT fx_fault_tolerant_log_header_total_size;
|
||||
USHORT fx_fault_tolerant_log_header_checksum;
|
||||
UCHAR fx_fault_tolerant_log_header_version_major;
|
||||
UCHAR fx_fault_tolerant_log_header_version_minor;
|
||||
USHORT fx_fault_tolerant_log_header_reserved;
|
||||
} FX_FAULT_TOLERANT_LOG_HEADER;
|
||||
|
||||
/* Define structure of FAT chain. */
|
||||
typedef struct FX_FAULT_TOLERANT_FAT_CHAIN_STRUCT
|
||||
{
|
||||
USHORT fx_fault_tolerant_FAT_chain_checksumm;
|
||||
UCHAR fx_fault_tolerant_FAT_chain_flag;
|
||||
UCHAR fx_fault_tolerant_FAT_chain_reserved;
|
||||
|
||||
ULONG fx_fault_tolerant_FAT_chain_insertion_front;
|
||||
ULONG fx_fault_tolerant_FAT_chain_head_new;
|
||||
ULONG fx_fault_tolerant_FAT_chain_head_original;
|
||||
ULONG fx_fault_tolerant_FAT_chain_insertion_back;
|
||||
ULONG fx_fault_tolerant_FAT_chain_next_deletion;
|
||||
} FX_FAULT_TOLERANT_FAT_CHAIN;
|
||||
|
||||
|
||||
/* Define structure of Log content. */
|
||||
typedef struct FX_FAULT_TOLERANT_LOG_CONTENT_STRUCT
|
||||
{
|
||||
USHORT fx_fault_tolerant_log_content_checksum;
|
||||
USHORT fx_fault_tolerant_log_content_count;
|
||||
} FX_FAULT_TOLERANT_LOG_CONTENT;
|
||||
|
||||
|
||||
/* 3 types of log entries are defined. */
|
||||
/* FAT log format
|
||||
* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
* + type + size +
|
||||
* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
* + cluster +
|
||||
* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
* + value +
|
||||
* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
*
|
||||
* Description:
|
||||
*
|
||||
* Type: FX_FAULT_TOLERANT_FAT_LOG.
|
||||
* Size: The size of this log entry.
|
||||
* Cluster: The cluster number in FAT.
|
||||
* Value: The value of cluster in FAT.
|
||||
*
|
||||
*/
|
||||
typedef struct FX_FAULT_TOLERANT_FAT_LOG_STRUCT
|
||||
{
|
||||
USHORT fx_fault_tolerant_FAT_log_type;
|
||||
USHORT fx_fault_tolerant_FAT_log_size;
|
||||
ULONG fx_fault_tolerant_FAT_log_cluster;
|
||||
ULONG fx_fault_tolerant_FAT_log_value;
|
||||
} FX_FAULT_TOLERANT_FAT_LOG;
|
||||
|
||||
/* DIR log format
|
||||
* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
* + type + size +
|
||||
* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
* + sector offset +
|
||||
* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
* + log sector +
|
||||
* + +
|
||||
* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
* + log data +
|
||||
* + . +
|
||||
* + . +
|
||||
* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
*
|
||||
* Fields description,
|
||||
*
|
||||
* Type: FX_FAULT_TOLERANT_DIRECTORY_LOG
|
||||
* Size: The size of this log entry.
|
||||
* Sector Offset: The offset in original sector this DIR is trying to write to.
|
||||
* Log Sector: The original sector this DIR is trying to write to.
|
||||
* Log Data: Content of DIR entries.
|
||||
*
|
||||
*/
|
||||
typedef struct FX_FAULT_TOLERANT_DIR_LOG_STRUCT
|
||||
{
|
||||
USHORT fx_fault_tolerant_dir_log_type;
|
||||
USHORT fx_fault_tolerant_dir_log_size;
|
||||
ULONG fx_fault_tolerant_dir_log_offset;
|
||||
ULONG64 fx_fault_tolerant_dir_log_sector;
|
||||
} FX_FAULT_TOLERANT_DIR_LOG;
|
||||
|
||||
/* Bitmap log format
|
||||
* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
* + type + size +
|
||||
* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
* + cluster +
|
||||
* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
* + value +
|
||||
* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
*
|
||||
* Description,
|
||||
*
|
||||
* Type: FX_FAULT_TOLERANT_BITMAP_LOG.
|
||||
* Size: The size of this log entry.
|
||||
* Cluster: The cluster number in FAT.
|
||||
* Value: The value of cluster in FAT.
|
||||
*/
|
||||
typedef struct FX_FAULT_TOLERANT_BITMAP_LOG_STRUCT
|
||||
{
|
||||
USHORT fx_fault_tolerant_bitmap_log_type;
|
||||
USHORT fx_fault_tolerant_bitmap_log_size;
|
||||
ULONG fx_fault_tolerant_bitmap_log_cluster;
|
||||
ULONG fx_fault_tolerant_bitmap_log_value;
|
||||
} FX_FAULT_TOLERANT_BITMAP_LOG;
|
||||
|
||||
|
||||
/* This function checks whether or not the log file exists, and creates the log file if it does not exist. */
|
||||
UINT _fx_fault_tolerant_enable(FX_MEDIA *media_ptr, VOID *memory_buffer, UINT memory_size);
|
||||
UINT _fxe_fault_tolerant_enable(FX_MEDIA *media_ptr, VOID *memory_buffer, UINT memory_size);
|
||||
|
||||
/* This function resets statistics and marks the start of a transaction. */
|
||||
UINT _fx_fault_tolerant_transaction_start(FX_MEDIA *media_ptr);
|
||||
|
||||
/* This function marks the end of a transaction and completes the log file.
|
||||
* Then it applies all data in the log file to the file system.
|
||||
* Finally it resets the log header section. */
|
||||
UINT _fx_fault_tolerant_transaction_end(FX_MEDIA *media_ptr);
|
||||
|
||||
/* This function resets the log file. */
|
||||
UINT _fx_fault_tolerant_reset_log_file(FX_MEDIA *media_ptr);
|
||||
|
||||
/* This function applies the log file to the file system. */
|
||||
UINT _fx_fault_tolerant_apply_logs(FX_MEDIA *media_ptr);
|
||||
|
||||
/* This function recovers FAT chain. */
|
||||
UINT _fx_fault_tolerant_recover(FX_MEDIA *media_ptr);
|
||||
|
||||
/* This function adds a FAT log entry. */
|
||||
UINT _fx_fault_tolerant_add_FAT_log(FX_MEDIA *media_ptr, ULONG cluster, ULONG value);
|
||||
|
||||
/* This function adds a directory log entry. */
|
||||
UINT _fx_fault_tolerant_add_dir_log(FX_MEDIA *media_ptr, ULONG64 logical_sector, ULONG offset,
|
||||
UCHAR *data, ULONG data_size);
|
||||
|
||||
/* This function sets the FAT chain. */
|
||||
UINT _fx_fault_tolerant_set_FAT_chain(FX_MEDIA *media_ptr, UINT use_bitmap, ULONG insertion_front,
|
||||
ULONG new_head_cluster, ULONG original_head_cluster, ULONG insertion_back);
|
||||
|
||||
/* This function reads a FAT entry from log file. If it doesn't exist in log file, return and read from FAT entry directly. */
|
||||
UINT _fx_fault_tolerant_read_FAT(FX_MEDIA *media_ptr, ULONG cluster, ULONG *value, ULONG log_type);
|
||||
|
||||
/* This function reads directory sector from log file. */
|
||||
UINT _fx_fault_tolerant_read_directory_sector(FX_MEDIA *media_ptr, ULONG64 logical_sector,
|
||||
VOID *buffer_ptr, ULONG64 sectors);
|
||||
|
||||
/* This function calculates the checksum of the log header. */
|
||||
USHORT _fx_fault_tolerant_calculate_checksum(UCHAR *data, UINT len);
|
||||
|
||||
/* This function cleans up FAT chain. */
|
||||
UINT _fx_fault_tolerant_cleanup_FAT_chain(FX_MEDIA *media_ptr, UINT operation);
|
||||
|
||||
/* This function reads log file from file system to memory buffer. */
|
||||
UINT _fx_fault_tolerant_read_log_file(FX_MEDIA *media_ptr);
|
||||
|
||||
/* This function writes data of one sector from memory to log file in file system. */
|
||||
UINT _fx_fault_tolerant_write_log_file(FX_MEDIA *media_ptr, ULONG relative_sector);
|
||||
|
||||
/* This function creates log file. */
|
||||
UINT _fx_fault_tolerant_create_log_file(FX_MEDIA *media_ptr);
|
||||
|
||||
#ifdef FX_FAULT_TOLERANT_TRANSACTION_FAIL_FUNCTION
|
||||
/* This function cleans up resources created by fault tolerant when transaction fails. */
|
||||
UINT _fx_fault_tolerant_transaction_fail(FX_MEDIA *media_ptr);
|
||||
#endif /* FX_FAULT_TOLERANT_TRANSACTION_FAIL_FUNCTION */
|
||||
|
||||
|
||||
#endif /* FX_ENABLE_FAULT_TOLERANT */
|
||||
|
||||
#endif /* _FX_FAULT_TOLERANT_H_ */
|
||||
|
||||
@@ -0,0 +1,125 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** FileX Component */
|
||||
/** */
|
||||
/** File */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* COMPONENT DEFINITION RELEASE */
|
||||
/* */
|
||||
/* fx_file.h PORTABLE C */
|
||||
/* 6.1 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This file defines the FileX File component constants, data */
|
||||
/* definitions, and external references. It is assumed that fx_api.h */
|
||||
/* (and fx_port.h) have already been included. */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 05-19-2020 William E. Lamie Initial Version 6.0 */
|
||||
/* 09-30-2020 William E. Lamie Modified comment(s), and */
|
||||
/* added conditional to */
|
||||
/* disable one line function, */
|
||||
/* resulting in version 6.1 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
#ifndef FX_FILE_H
|
||||
#define FX_FILE_H
|
||||
|
||||
|
||||
/* Define the external File component function prototypes. */
|
||||
|
||||
#ifndef FX_DISABLE_ONE_LINE_FUNCTION
|
||||
UINT _fx_file_allocate(FX_FILE *file_ptr, ULONG size);
|
||||
#else
|
||||
#define _fx_file_allocate(f, s) _fx_file_extended_allocate(f, (ULONG64)s);
|
||||
#endif /* FX_DISABLE_ONE_LINE_FUNCTION */
|
||||
UINT _fx_file_attributes_read(FX_MEDIA *media_ptr, CHAR *file_name, UINT *attributes_ptr);
|
||||
UINT _fx_file_attributes_set(FX_MEDIA *media_ptr, CHAR *file_name, UINT attributes);
|
||||
UINT _fx_file_best_effort_allocate(FX_FILE *file_ptr, ULONG size, ULONG *actual_size_allocated);
|
||||
UINT _fx_file_close(FX_FILE *file_ptr);
|
||||
UINT _fx_file_create(FX_MEDIA *media_ptr, CHAR *file_name);
|
||||
UINT _fx_file_date_time_set(FX_MEDIA *media_ptr, CHAR *file_name,
|
||||
UINT year, UINT month, UINT day, UINT hour, UINT minute, UINT second);
|
||||
UINT _fx_file_delete(FX_MEDIA *media_ptr, CHAR *file_name);
|
||||
UINT _fx_file_open(FX_MEDIA *media_ptr, FX_FILE *file_ptr, CHAR *file_name,
|
||||
UINT open_type);
|
||||
UINT _fx_file_read(FX_FILE *file_ptr, VOID *buffer_ptr, ULONG request_size, ULONG *actual_size);
|
||||
#ifndef FX_DISABLE_ONE_LINE_FUNCTION
|
||||
UINT _fx_file_relative_seek(FX_FILE *file_ptr, ULONG byte_offset, UINT seek_from);
|
||||
#else
|
||||
#define _fx_file_relative_seek(f, b, sf) _fx_file_extended_relative_seek(f, (ULONG64)b, sf);
|
||||
#endif /* FX_DISABLE_ONE_LINE_FUNCTION */
|
||||
UINT _fx_file_rename(FX_MEDIA *media_ptr, CHAR *old_file_name, CHAR *new_file_name);
|
||||
#ifndef FX_DISABLE_ONE_LINE_FUNCTION
|
||||
UINT _fx_file_seek(FX_FILE *file_ptr, ULONG byte_offset);
|
||||
UINT _fx_file_truncate(FX_FILE *file_ptr, ULONG size);
|
||||
UINT _fx_file_truncate_release(FX_FILE *file_ptr, ULONG size);
|
||||
#else
|
||||
#define _fx_file_seek(f, b) _fx_file_extended_seek(f, (ULONG64)b)
|
||||
#define _fx_file_truncate(f, s) _fx_file_extended_truncate(f, (ULONG64)s);
|
||||
#define _fx_file_truncate_release(f, s) _fx_file_extended_truncate_release(f, (ULONG64)s);
|
||||
#endif /* FX_DISABLE_ONE_LINE_FUNCTION */
|
||||
UINT _fx_file_write(FX_FILE *file_ptr, VOID *buffer_ptr, ULONG size);
|
||||
UINT _fx_file_write_notify_set(FX_FILE *file_ptr, VOID (*file_write_notify)(FX_FILE *));
|
||||
UINT _fx_file_extended_allocate(FX_FILE *file_ptr, ULONG64 size);
|
||||
UINT _fx_file_extended_best_effort_allocate(FX_FILE *file_ptr, ULONG64 size, ULONG64 *actual_size_allocated);
|
||||
UINT _fx_file_extended_relative_seek(FX_FILE *file_ptr, ULONG64 byte_offset, UINT seek_from);
|
||||
UINT _fx_file_extended_seek(FX_FILE *file_ptr, ULONG64 byte_offset);
|
||||
UINT _fx_file_extended_truncate(FX_FILE *file_ptr, ULONG64 size);
|
||||
UINT _fx_file_extended_truncate_release(FX_FILE *file_ptr, ULONG64 size);
|
||||
|
||||
UINT _fxe_file_allocate(FX_FILE *file_ptr, ULONG size);
|
||||
UINT _fxe_file_attributes_read(FX_MEDIA *media_ptr, CHAR *file_name, UINT *attributes_ptr);
|
||||
UINT _fxe_file_attributes_set(FX_MEDIA *media_ptr, CHAR *file_name, UINT attributes);
|
||||
UINT _fxe_file_best_effort_allocate(FX_FILE *file_ptr, ULONG size, ULONG *actual_size_allocated);
|
||||
UINT _fxe_file_close(FX_FILE *file_ptr);
|
||||
UINT _fxe_file_create(FX_MEDIA *media_ptr, CHAR *file_name);
|
||||
UINT _fxe_file_date_time_set(FX_MEDIA *media_ptr, CHAR *file_name,
|
||||
UINT year, UINT month, UINT day, UINT hour, UINT minute, UINT second);
|
||||
UINT _fxe_file_delete(FX_MEDIA *media_ptr, CHAR *file_name);
|
||||
UINT _fxe_file_open(FX_MEDIA *media_ptr, FX_FILE *file_ptr, CHAR *file_name,
|
||||
UINT open_type, UINT file_control_block_size);
|
||||
UINT _fxe_file_read(FX_FILE *file_ptr, VOID *buffer_ptr, ULONG request_size, ULONG *actual_size);
|
||||
UINT _fxe_file_relative_seek(FX_FILE *file_ptr, ULONG byte_offset, UINT seek_from);
|
||||
UINT _fxe_file_rename(FX_MEDIA *media_ptr, CHAR *old_file_name, CHAR *new_file_name);
|
||||
UINT _fxe_file_seek(FX_FILE *file_ptr, ULONG byte_offset);
|
||||
UINT _fxe_file_truncate(FX_FILE *file_ptr, ULONG size);
|
||||
UINT _fxe_file_truncate_release(FX_FILE *file_ptr, ULONG size);
|
||||
UINT _fxe_file_write(FX_FILE *file_ptr, VOID *buffer_ptr, ULONG size);
|
||||
UINT _fxe_file_write_notify_set(FX_FILE *file_ptr, VOID (*file_write_notify)(FX_FILE *));
|
||||
UINT _fxe_file_extended_allocate(FX_FILE *file_ptr, ULONG64 size);
|
||||
UINT _fxe_file_extended_best_effort_allocate(FX_FILE *file_ptr, ULONG64 size, ULONG64 *actual_size_allocated);
|
||||
UINT _fxe_file_extended_relative_seek(FX_FILE *file_ptr, ULONG64 byte_offset, UINT seek_from);
|
||||
UINT _fxe_file_extended_seek(FX_FILE *file_ptr, ULONG64 byte_offset);
|
||||
UINT _fxe_file_extended_truncate(FX_FILE *file_ptr, ULONG64 size);
|
||||
UINT _fxe_file_extended_truncate_release(FX_FILE *file_ptr, ULONG64 size);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,109 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** FileX Component */
|
||||
/** */
|
||||
/** Media */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* COMPONENT DEFINITION RELEASE */
|
||||
/* */
|
||||
/* fx_media.h PORTABLE C */
|
||||
/* 6.1 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This file defines the FileX Media component constants, data */
|
||||
/* definitions, and external references. It is assumed that fx_api.h */
|
||||
/* (and fx_port.h) have already been included. */
|
||||
/* */
|
||||
/* 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 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
#ifndef FX_MEDIA_H
|
||||
#define FX_MEDIA_H
|
||||
|
||||
|
||||
/* Define the external Media component function prototypes. */
|
||||
|
||||
UINT _fx_media_abort(FX_MEDIA *media_ptr);
|
||||
UINT _fx_media_cache_invalidate(FX_MEDIA *media_ptr);
|
||||
UINT _fx_media_check(FX_MEDIA *media_ptr, UCHAR *scratch_memory_ptr, ULONG scratch_memory_size, ULONG error_correction_option, ULONG *errors_detected);
|
||||
UINT _fx_media_close(FX_MEDIA *media_ptr);
|
||||
UINT _fx_media_flush(FX_MEDIA *media_ptr);
|
||||
UINT _fx_media_format(FX_MEDIA *media_ptr, VOID (*driver)(FX_MEDIA *media), VOID *driver_info_ptr, UCHAR *memory_ptr, UINT memory_size,
|
||||
CHAR *volume_name, UINT number_of_fats, UINT directory_entries, UINT hidden_sectors,
|
||||
ULONG total_sectors, UINT bytes_per_sector, UINT sectors_per_cluster,
|
||||
UINT heads, UINT sectors_per_track);
|
||||
UINT _fx_media_open(FX_MEDIA *media_ptr, CHAR *media_name,
|
||||
VOID (*media_driver)(FX_MEDIA *), VOID *driver_info_ptr,
|
||||
VOID *memory_ptr, ULONG memory_size);
|
||||
UINT _fx_media_read(FX_MEDIA *media_ptr, ULONG logical_sector, VOID *buffer_ptr);
|
||||
UINT _fx_media_space_available(FX_MEDIA *media_ptr, ULONG *available_bytes_ptr);
|
||||
UINT _fx_media_volume_get(FX_MEDIA *media_ptr, CHAR *volume_name, UINT volume_source);
|
||||
UINT _fx_media_volume_get_extended(FX_MEDIA *media_ptr, CHAR *volume_name, UINT volume_name_buffer_length, UINT volume_source);
|
||||
UINT _fx_media_volume_set(FX_MEDIA *media_ptr, CHAR *volume_name);
|
||||
UINT _fx_media_write(FX_MEDIA *media_ptr, ULONG logical_sector, VOID *buffer_ptr);
|
||||
UINT _fx_media_open_notify_set(FX_MEDIA *media_ptr, VOID (*media_open_notify)(FX_MEDIA *));
|
||||
UINT _fx_media_close_notify_set(FX_MEDIA *media_ptr, VOID (*media_close_notify)(FX_MEDIA *));
|
||||
UINT _fx_media_extended_space_available(FX_MEDIA *media_ptr, ULONG64 *available_bytes_ptr);
|
||||
|
||||
|
||||
UINT _fxe_media_abort(FX_MEDIA *media_ptr);
|
||||
UINT _fxe_media_cache_invalidate(FX_MEDIA *media_ptr);
|
||||
UINT _fxe_media_check(FX_MEDIA *media_ptr, UCHAR *scratch_memory_ptr, ULONG scratch_memory_size, ULONG error_correction_option, ULONG *errors_detected);
|
||||
UINT _fxe_media_close(FX_MEDIA *media_ptr);
|
||||
UINT _fxe_media_flush(FX_MEDIA *media_ptr);
|
||||
UINT _fxe_media_format(FX_MEDIA *media_ptr, VOID (*driver)(FX_MEDIA *media), VOID *driver_info_ptr, UCHAR *memory_ptr, UINT memory_size,
|
||||
CHAR *volume_name, UINT number_of_fats, UINT directory_entries, UINT hidden_sectors,
|
||||
ULONG total_sectors, UINT bytes_per_sector, UINT sectors_per_cluster,
|
||||
UINT heads, UINT sectors_per_track);
|
||||
UINT _fxe_media_open(FX_MEDIA *media_ptr, CHAR *media_name,
|
||||
VOID (*media_driver)(FX_MEDIA *), VOID *driver_info_ptr,
|
||||
VOID *memory_ptr, ULONG memory_size, UINT media_control_block_size);
|
||||
UINT _fxe_media_read(FX_MEDIA *media_ptr, ULONG logical_sector, VOID *buffer_ptr);
|
||||
UINT _fxe_media_space_available(FX_MEDIA *media_ptr, ULONG *available_bytes_ptr);
|
||||
UINT _fxe_media_volume_get(FX_MEDIA *media_ptr, CHAR *volume_name, UINT volume_source);
|
||||
UINT _fxe_media_volume_get_extended(FX_MEDIA *media_ptr, CHAR *volume_name, UINT volume_name_buffer_length, UINT volume_source);
|
||||
UINT _fxe_media_volume_set(FX_MEDIA *media_ptr, CHAR *volume_name);
|
||||
UINT _fxe_media_write(FX_MEDIA *media_ptr, ULONG logical_sector, VOID *buffer_ptr);
|
||||
UINT _fxe_media_open_notify_set(FX_MEDIA *media_ptr, VOID (*media_open_notify)(FX_MEDIA *));
|
||||
UINT _fxe_media_close_notify_set(FX_MEDIA *media_ptr, VOID (*media_close_notify)(FX_MEDIA *));
|
||||
UINT _fxe_media_extended_space_available(FX_MEDIA *media_ptr, ULONG64 *available_bytes_ptr);
|
||||
|
||||
|
||||
/* Define the internal Media component function prototypes. */
|
||||
|
||||
ULONG _fx_media_check_FAT_chain_check(FX_MEDIA *media_ptr, ULONG starting_cluster, ULONG *last_valid_cluster, ULONG *total_valid_clusters, UCHAR *logical_fat);
|
||||
ULONG _fx_media_check_lost_cluster_check(FX_MEDIA *media_ptr, UCHAR *logical_fat, ULONG total_clusters, ULONG error_correction_option);
|
||||
UINT _fx_media_boot_info_extract(FX_MEDIA *media_ptr);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,175 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** FileX Component */
|
||||
/** */
|
||||
/** System */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* COMPONENT DEFINITION RELEASE */
|
||||
/* */
|
||||
/* fx_system.h PORTABLE C */
|
||||
/* 6.1 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This file defines the FileX system constants and global data */
|
||||
/* definitions, including external references. It is assumed that */
|
||||
/* fx_api.h (and fx_port.h) have already been included. */
|
||||
/* */
|
||||
/* 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 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
#ifndef FX_SYSTEM_H
|
||||
#define FX_SYSTEM_H
|
||||
|
||||
|
||||
/* Define System component constants. */
|
||||
|
||||
#define FX_TIMER_ID ((ULONG) 0x46585359)
|
||||
|
||||
|
||||
/* Define the external System component function prototypes. */
|
||||
|
||||
VOID _fx_system_initialize(VOID);
|
||||
UINT _fx_system_date_set(UINT year, UINT month, UINT day);
|
||||
UINT _fx_system_time_set(UINT hour, UINT minute, UINT second);
|
||||
UINT _fx_system_date_get(UINT *year, UINT *month, UINT *day);
|
||||
UINT _fx_system_time_get(UINT *hour, UINT *minute, UINT *second);
|
||||
VOID _fx_system_timer_entry(ULONG id);
|
||||
|
||||
UINT _fxe_system_date_set(UINT year, UINT month, UINT day);
|
||||
UINT _fxe_system_time_set(UINT hour, UINT minute, UINT second);
|
||||
UINT _fxe_system_date_get(UINT *year, UINT *month, UINT *day);
|
||||
UINT _fxe_system_time_get(UINT *hour, UINT *minute, UINT *second);
|
||||
|
||||
|
||||
/* System Component data declarations follow. */
|
||||
|
||||
/* Determine if the initialization function of this component is including
|
||||
this file. If so, make the data definitions really happen. Otherwise,
|
||||
make them extern so other functions in the component can access them. */
|
||||
|
||||
#ifdef FX_SYSTEM_INIT
|
||||
#define SYSTEM_DECLARE
|
||||
#else
|
||||
#define SYSTEM_DECLARE extern
|
||||
#endif
|
||||
|
||||
|
||||
/* Define the head pointer of the opened media list. */
|
||||
|
||||
SYSTEM_DECLARE FX_MEDIA *_fx_system_media_opened_ptr;
|
||||
|
||||
|
||||
/* Define the variable that holds the number of open media. */
|
||||
|
||||
SYSTEM_DECLARE ULONG _fx_system_media_opened_count;
|
||||
|
||||
|
||||
/* Define the system date variable. */
|
||||
|
||||
SYSTEM_DECLARE UINT _fx_system_date;
|
||||
|
||||
|
||||
/* Define the system time variable. */
|
||||
|
||||
SYSTEM_DECLARE UINT _fx_system_time;
|
||||
|
||||
|
||||
/* Define the variable that holds the maximum size of the sector cache. */
|
||||
|
||||
SYSTEM_DECLARE ULONG _fx_system_media_max_sector_cache;
|
||||
|
||||
|
||||
/* Define the variable that holds the maximum size of the FAT cache. */
|
||||
|
||||
SYSTEM_DECLARE ULONG _fx_system_media_max_fat_cache;
|
||||
|
||||
|
||||
/* Define the global FileX build options variables. These variables contain a bit
|
||||
map representing how the FileX library was built. The following are the bit
|
||||
field definitions:
|
||||
|
||||
_fx_system_build_options_1:
|
||||
|
||||
Bit(s) Meaning
|
||||
|
||||
31-24 FX_MAX_LONG_NAME_LEN
|
||||
23-16 FX_MAX_LAST_NAME_LEN
|
||||
15-11 Reserved
|
||||
10 FX_NO_TIMER defined
|
||||
9 FX_SINGLE_THREAD defined
|
||||
8 FX_DONT_UPDATE_OPEN_FILES defined
|
||||
7 FX_MEDIA_DISABLE_SEARCH_CACHE defined
|
||||
6 FX_MEDIA_STATISTICS_DISABLE defined
|
||||
5 Reserved
|
||||
4 FX_SINGLE_OPEN_LEGACY defined
|
||||
3 FX_RENAME_PATH_INHERIT defined
|
||||
2 FX_NO_LOCAL_PATH defined
|
||||
1 FX_FAULT_TOLERANT_DATA defined
|
||||
0 FX_FAULT_TOLERANT defined
|
||||
|
||||
_fx_system_build_options_2:
|
||||
|
||||
Bit(s) Meaning
|
||||
|
||||
31-16 FX_MAX_SECTOR_CACHE
|
||||
15-8 FX_FAT_MAP_SIZE
|
||||
7-0 FX_MAX_FAT_CACHE
|
||||
|
||||
_fx_system_build_options_3:
|
||||
|
||||
Bit(s) Meaning
|
||||
|
||||
31-24 Reserved
|
||||
23-16 FX_UPDATE_RATE_IN_SECONDS
|
||||
15-0 FX_UPDATE_RATE_IN_TICKS
|
||||
|
||||
Note that values greater than the value that can be represented in the build options
|
||||
bit field are represented as all ones in the bit field. For example, if FX_MAX_LONG_NAME_LEN
|
||||
is 256, the value in the bits 31-24 of _fx_system_build_options_1 is 0xFF, which is 255
|
||||
decimal. */
|
||||
|
||||
SYSTEM_DECLARE ULONG _fx_system_build_options_1;
|
||||
SYSTEM_DECLARE ULONG _fx_system_build_options_2;
|
||||
SYSTEM_DECLARE ULONG _fx_system_build_options_3;
|
||||
|
||||
|
||||
/* Define system timer control block. If accurate date/time stamps on
|
||||
files is not needed, the define FX_NO_TIMER should be used when
|
||||
compiling fx_system_initialize.c to eliminate the FileX timer. */
|
||||
|
||||
#ifndef FX_NO_TIMER
|
||||
SYSTEM_DECLARE TX_TIMER _fx_system_timer;
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,110 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** FileX Component */
|
||||
/** */
|
||||
/** Unicode */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* COMPONENT DEFINITION RELEASE */
|
||||
/* */
|
||||
/* fx_unicode.h PORTABLE C */
|
||||
/* 6.1 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This file defines the FileX Unicode component constants, data */
|
||||
/* definitions, and external references. It is assumed that fx_api.h */
|
||||
/* (and fx_port.h) have already been included. */
|
||||
/* */
|
||||
/* 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 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
#ifndef FX_UNICODE_H
|
||||
#define FX_UNICODE_H
|
||||
|
||||
|
||||
/* Define external data for the Unicode component. */
|
||||
|
||||
extern UCHAR _fx_unicode_temp_long_file_name[FX_MAX_LONG_NAME_LEN];
|
||||
extern UCHAR _fx_unicode_search_name[FX_MAX_LONG_NAME_LEN * 2];
|
||||
|
||||
|
||||
/* Define the external Unicode component function prototypes. */
|
||||
|
||||
UINT _fx_unicode_directory_create(FX_MEDIA *media_ptr, UCHAR *source_unicode_name, ULONG source_unicode_length,
|
||||
CHAR *short_name);
|
||||
UINT _fx_unicode_directory_rename(FX_MEDIA *media_ptr, UCHAR *old_unicode_name, ULONG old_unicode_length,
|
||||
UCHAR *new_unicode_name, ULONG new_unicode_length, CHAR *new_short_name);
|
||||
UINT _fx_unicode_file_create(FX_MEDIA *media_ptr, UCHAR *source_unicode_name, ULONG source_unicode_length,
|
||||
CHAR *short_name);
|
||||
ULONG _fx_unicode_length_get(UCHAR *unicode_name);
|
||||
ULONG _fx_unicode_length_get_extended(UCHAR *unicode_name, UINT buffer_length);
|
||||
UINT _fx_unicode_name_get(FX_MEDIA *media_ptr, CHAR *source_short_name,
|
||||
UCHAR *destination_unicode_name, ULONG *destination_unicode_length);
|
||||
UINT _fx_unicode_name_get_extended(FX_MEDIA *media_ptr, CHAR *source_short_name,
|
||||
UCHAR *destination_unicode_name, ULONG *destination_unicode_length, ULONG unicode_name_buffer_length);
|
||||
UINT _fx_unicode_file_rename(FX_MEDIA *media_ptr, UCHAR *old_unicode_name, ULONG old_unicode_length,
|
||||
UCHAR *new_unicode_name, ULONG new_unicode_length, CHAR *new_short_name);
|
||||
UINT _fx_unicode_short_name_get(FX_MEDIA *media_ptr, UCHAR *source_unicode_name, ULONG source_unicode_length,
|
||||
CHAR *destination_short_name);
|
||||
UINT _fx_unicode_short_name_get_extended(FX_MEDIA *media_ptr, UCHAR *source_unicode_name, ULONG source_unicode_length,
|
||||
CHAR *destination_short_name, ULONG short_name_buffer_length);
|
||||
|
||||
UINT _fxe_unicode_directory_create(FX_MEDIA *media_ptr, UCHAR *source_unicode_name, ULONG source_unicode_length,
|
||||
CHAR *short_name);
|
||||
UINT _fxe_unicode_directory_rename(FX_MEDIA *media_ptr, UCHAR *old_unicode_name, ULONG old_unicode_length,
|
||||
UCHAR *new_unicode_name, ULONG new_unicode_length, CHAR *new_short_name);
|
||||
UINT _fxe_unicode_file_create(FX_MEDIA *media_ptr, UCHAR *source_unicode_name, ULONG source_unicode_length,
|
||||
CHAR *short_name);
|
||||
UINT _fxe_unicode_file_rename(FX_MEDIA *media_ptr, UCHAR *old_unicode_name, ULONG old_unicode_length,
|
||||
UCHAR *new_unicode_name, ULONG new_unicode_length, CHAR *new_short_name);
|
||||
UINT _fxe_unicode_name_get(FX_MEDIA *media_ptr, CHAR *source_short_name,
|
||||
UCHAR *destination_unicode_name, ULONG *destination_unicode_length);
|
||||
UINT _fxe_unicode_name_get_extended(FX_MEDIA *media_ptr, CHAR *source_short_name,
|
||||
UCHAR *destination_unicode_name, ULONG *destination_unicode_length, ULONG unicode_name_buffer_length);
|
||||
UINT _fxe_unicode_short_name_get(FX_MEDIA *media_ptr, UCHAR *source_unicode_name, ULONG source_unicode_length,
|
||||
CHAR *destination_short_name);
|
||||
UINT _fxe_unicode_short_name_get_extended(FX_MEDIA *media_ptr, UCHAR *source_unicode_name, ULONG source_unicode_length,
|
||||
CHAR *destination_short_name, ULONG short_name_buffer_length);
|
||||
|
||||
/* Define the internal Unicode component function prototypes. */
|
||||
|
||||
UINT _fx_unicode_directory_search(FX_MEDIA *media_ptr, FX_DIR_ENTRY *entry_ptr,
|
||||
UCHAR *short_name, ULONG short_name_buffer_length,
|
||||
UCHAR *unicode_name, ULONG *unicode_name_length, ULONG unicode_name_buffer_length);
|
||||
UINT _fx_unicode_directory_entry_read(FX_MEDIA *media_ptr, FX_DIR_ENTRY *source_dir,
|
||||
ULONG *entry_ptr, FX_DIR_ENTRY *destination_ptr,
|
||||
UCHAR *unicode_name, ULONG *unicode_size);
|
||||
UINT _fx_unicode_directory_entry_change(FX_MEDIA *media_ptr, FX_DIR_ENTRY *entry_ptr, UCHAR *unicode_name, ULONG unicode_name_length);
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,236 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** FileX Component */
|
||||
/** */
|
||||
/** User Specific */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* PORT SPECIFIC C INFORMATION RELEASE */
|
||||
/* */
|
||||
/* fx_user.h PORTABLE C */
|
||||
/* 6.1.5 */
|
||||
/* */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This file contains user defines for configuring FileX in specific */
|
||||
/* ways. This file will have an effect only if the application and */
|
||||
/* FileX library are built with FX_INCLUDE_USER_DEFINE_FILE defined. */
|
||||
/* Note that all the defines in this file may also be made on the */
|
||||
/* command line when building FileX library and application objects. */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 05-19-2020 William E. Lamie Initial Version 6.0 */
|
||||
/* 09-30-2020 William E. Lamie Modified comment(s), and */
|
||||
/* added product constants */
|
||||
/* to enable code */
|
||||
/* size optimization, */
|
||||
/* resulting in version 6.1 */
|
||||
/* 03-02-2021 William E. Lamie Modified comment(s), and */
|
||||
/* added standalone support, */
|
||||
/* resulting in version 6.1.5 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
#ifndef FX_USER_H
|
||||
#define FX_USER_H
|
||||
|
||||
|
||||
/* Define various build options for the FileX port. The application should either make changes
|
||||
here by commenting or un-commenting the conditional compilation defined OR supply the defines
|
||||
though the compiler's equivalent of the -D option. */
|
||||
|
||||
|
||||
/* Override various options with default values already assigned in fx_api.h or fx_port.h. Please
|
||||
also refer to fx_port.h for descriptions on each of these options. */
|
||||
|
||||
|
||||
/* Defines the maximum size of long file names supported by FileX. The default value is 33. The
|
||||
minimum value is 13 and the maximum value is 256. */
|
||||
|
||||
/*#define FX_MAX_LONG_NAME_LEN 256 */
|
||||
/*#define FX_MAX_LAST_NAME_LEN 256 */ /* Must be as large or larger than FX_MAX_LONG_NAME_LEN */
|
||||
|
||||
|
||||
/* Defines the maximum number of logical sectors that can be cached by FileX. The cache memory
|
||||
supplied to FileX at fx_media_open determines how many sectors can actually be cached. */
|
||||
|
||||
/*#define FX_MAX_SECTOR_CACHE 256 */ /* Minimum value is 2, all other values must be power of 2. */
|
||||
|
||||
|
||||
/* Defines the size in bytes of the bit map used to update the secondary FAT sectors. The larger the value the
|
||||
less unnecessary secondary FAT sector writes. */
|
||||
|
||||
/*#define FX_FAT_MAP_SIZE 128 */ /* Minimum value is 1, no maximum value. */
|
||||
|
||||
|
||||
/* Defines the number of entries in the FAT cache. */
|
||||
|
||||
/*#define FX_MAX_FAT_CACHE 16 */ /* Minimum value is 8, all values must be a power of 2. */
|
||||
|
||||
|
||||
/* Defines the number of seconds the time parameters are updated in FileX. */
|
||||
|
||||
/*#define FX_UPDATE_RATE_IN_SECONDS 10 */
|
||||
|
||||
|
||||
/* Defines the number of ThreadX timer ticks required to achieve the update rate specified by
|
||||
FX_UPDATE_RATE_IN_SECONDS defined previously. By default, the ThreadX timer tick is 10ms,
|
||||
so the default value for this constant is 1000. */
|
||||
|
||||
/*#define FX_UPDATE_RATE_IN_TICKS 1000 */
|
||||
|
||||
|
||||
/* Defined, FileX is built without update to the time parameters. */
|
||||
|
||||
/*#define FX_NO_TIMER */
|
||||
|
||||
|
||||
/* Defined, FileX does not update already opened files. */
|
||||
|
||||
/*#define FX_DONT_UPDATE_OPEN_FILES */
|
||||
|
||||
|
||||
/* Defined, the file search cache optimization is disabled. */
|
||||
|
||||
/*#define FX_MEDIA_DISABLE_SEARCH_CACHE */
|
||||
|
||||
|
||||
/* Defined, the direct read sector update of cache is disabled. */
|
||||
|
||||
/*#define FX_DISABLE_DIRECT_DATA_READ_CACHE_FILL */
|
||||
|
||||
|
||||
/* Defined, gathering of media statistics is disabled. */
|
||||
|
||||
/*#define FX_MEDIA_STATISTICS_DISABLE */
|
||||
|
||||
|
||||
/* Defined, legacy single open logic for the same file is enabled. */
|
||||
|
||||
/*#define FX_SINGLE_OPEN_LEGACY */
|
||||
|
||||
|
||||
/* Defined, renaming inherits path information. */
|
||||
|
||||
/*#define FX_RENAME_PATH_INHERIT */
|
||||
|
||||
|
||||
/* Defined, local path logic is disabled. */
|
||||
|
||||
/*#define FX_NO_LOCAL_PATH */
|
||||
|
||||
|
||||
/* Define FileX internal protection macros. If FX_SINGLE_THREAD is defined,
|
||||
these protection macros are effectively disabled. However, for multi-thread
|
||||
uses, the macros are setup to utilize a ThreadX mutex for multiple thread
|
||||
access control into an open media. */
|
||||
|
||||
/* #define FX_SINGLE_THREAD */
|
||||
|
||||
|
||||
/* Defined, Filex will be used in standalone mode (without ThreadX) */
|
||||
|
||||
/* #define FX_STANDALONE_ENABLE */
|
||||
|
||||
|
||||
/* Defined, data sector write requests are flushed immediately to the driver. */
|
||||
|
||||
/*#define FX_FAULT_TOLERANT_DATA */
|
||||
|
||||
|
||||
/* Defined, system sector write requests (including FAT and directory entry requests)
|
||||
are flushed immediately to the driver. */
|
||||
|
||||
/*#define FX_FAULT_TOLERANT */
|
||||
|
||||
|
||||
/* Defined, enables 64-bits sector addresses used in I/O driver. */
|
||||
|
||||
/*#define FX_DRIVER_USE_64BIT_LBA */
|
||||
|
||||
|
||||
/* Defined, enables FileX fault tolerant service. */
|
||||
|
||||
/*#define FX_ENABLE_FAULT_TOLERANT */
|
||||
|
||||
|
||||
/* Define byte offset in boot sector where the cluster number of the Fault Tolerant Log file is.
|
||||
Note that this field (byte 116 to 119) is marked as reserved by FAT 12/16/32 specification. */
|
||||
|
||||
/*#define FX_FAULT_TOLERANT_BOOT_INDEX 116 */
|
||||
|
||||
/* Below FX_DISABLE_XXX macros can be used for code size optimization required for memory
|
||||
critical aplications */
|
||||
|
||||
/* Defined, error checking is disabled. */
|
||||
|
||||
/*#define FX_DISABLE_ERROR_CHECKING */
|
||||
|
||||
|
||||
/* Defined, cache is disabled. */
|
||||
|
||||
/*#define FX_DISABLE_CACHE */
|
||||
|
||||
|
||||
/* Defined, file close is disabled. */
|
||||
|
||||
/*#define FX_DISABLE_FILE_CLOSE */
|
||||
|
||||
|
||||
/* Defined, fast open is disabled. */
|
||||
|
||||
/*#define FX_DISABLE_FAST_OPEN */
|
||||
|
||||
|
||||
/* Defined, force memory operations are disabled. */
|
||||
|
||||
/*#define FX_DISABLE_FORCE_MEMORY_OPERATION */
|
||||
|
||||
|
||||
/* Defined, build options is disabled. */
|
||||
|
||||
/*#define FX_DISABLE_BUILD_OPTIONS */
|
||||
|
||||
|
||||
/* Defined, one line function is disabled. */
|
||||
|
||||
/*#define FX_DISABLE_ONE_LINE_FUNCTION */
|
||||
|
||||
|
||||
/* Defined, FAT entry refresh is disabled. */
|
||||
|
||||
/*#define FX_DIABLE_FAT_ENTRY_REFRESH */
|
||||
|
||||
|
||||
/* Defined, consecutive detect is disabled. */
|
||||
|
||||
/*#define FX_DISABLE_CONSECUTIVE_DETECT */
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,82 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** FileX Component */
|
||||
/** */
|
||||
/** Utility */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* COMPONENT DEFINITION RELEASE */
|
||||
/* */
|
||||
/* fx_utility.h PORTABLE C */
|
||||
/* 6.1 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This file defines the FileX Utility component constants, data */
|
||||
/* definitions, and external references. It is assumed that fx_api.h */
|
||||
/* (and fx_port.h) have already been included. */
|
||||
/* */
|
||||
/* 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 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
#ifndef FX_UTILITY_H
|
||||
#define FX_UTILITY_H
|
||||
|
||||
|
||||
/* Define the internal Utility component function prototypes. */
|
||||
|
||||
UINT _fx_utility_16_unsigned_read(UCHAR *source_ptr);
|
||||
VOID _fx_utility_16_unsigned_write(UCHAR *dest_ptr, UINT value);
|
||||
ULONG _fx_utility_32_unsigned_read(UCHAR *source_ptr);
|
||||
VOID _fx_utility_32_unsigned_write(UCHAR *dest_ptr, ULONG value);
|
||||
ULONG64 _fx_utility_64_unsigned_read(UCHAR *source_ptr);
|
||||
VOID _fx_utility_64_unsigned_write(UCHAR *dest_ptr, ULONG64 value);
|
||||
VOID _fx_utility_memory_copy(UCHAR *source_ptr, UCHAR *dest_ptr, ULONG size);
|
||||
VOID _fx_utility_memory_set(UCHAR *dest_ptr, UCHAR value, ULONG size);
|
||||
FX_CACHED_SECTOR
|
||||
*_fx_utility_logical_sector_cache_entry_read(FX_MEDIA *media_ptr, ULONG64 logical_sector, FX_CACHED_SECTOR **previous_cache_entry);
|
||||
UINT _fx_utility_logical_sector_read(FX_MEDIA *media_ptr, ULONG64 logical_sector,
|
||||
VOID *buffer_ptr, ULONG sectors, UCHAR sector_type);
|
||||
UINT _fx_utility_logical_sector_write(FX_MEDIA *media_ptr, ULONG64 logical_sector,
|
||||
VOID *buffer_ptr, ULONG sectors, UCHAR sector_type);
|
||||
UINT _fx_utility_logical_sector_flush(FX_MEDIA *media_ptr, ULONG64 starting_sector, ULONG64 sectors, UINT invalidate);
|
||||
UINT _fx_utility_FAT_entry_read(FX_MEDIA *media_ptr, ULONG cluster, ULONG *entry_ptr);
|
||||
UINT _fx_utility_FAT_entry_write(FX_MEDIA *media_ptr, ULONG cluster, ULONG next_cluster);
|
||||
UINT _fx_utility_FAT_flush(FX_MEDIA *media_ptr);
|
||||
UINT _fx_utility_FAT_map_flush(FX_MEDIA *media_ptr);
|
||||
ULONG _fx_utility_FAT_sector_get(FX_MEDIA *media_ptr, ULONG cluster);
|
||||
UINT _fx_utility_string_length_get(CHAR *string, UINT max_length);
|
||||
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,156 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** 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"
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _fx_directory_attributes_read PORTABLE C */
|
||||
/* 6.1 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function first attempts to find the specified directory. If */
|
||||
/* found, the attribute read request is valid and the directory entry */
|
||||
/* will be read in order to pickup the directory's attributes. */
|
||||
/* Otherwise, if the directory is not found, the appropriate error */
|
||||
/* code is returned to the caller. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* media_ptr Media control block pointer */
|
||||
/* directory_name Directory name pointer */
|
||||
/* attributes_ptr Return attributes pointer */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* return status */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* _fx_directory_search Search for the file name in */
|
||||
/* the directory structure */
|
||||
/* */
|
||||
/* 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_attributes_read(FX_MEDIA *media_ptr, CHAR *directory_name, UINT *attributes_ptr)
|
||||
{
|
||||
|
||||
UINT status;
|
||||
FX_DIR_ENTRY dir_entry;
|
||||
|
||||
#ifdef TX_ENABLE_EVENT_TRACE
|
||||
TX_TRACE_BUFFER_ENTRY *trace_event;
|
||||
ULONG trace_timestamp;
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef FX_MEDIA_STATISTICS_DISABLE
|
||||
|
||||
/* Increment the number of times this service has been called. */
|
||||
media_ptr -> fx_media_directory_attributes_reads++;
|
||||
#endif
|
||||
|
||||
/* Setup pointer to media name buffer. */
|
||||
dir_entry.fx_dir_entry_name = media_ptr -> fx_media_name_buffer + FX_MAX_LONG_NAME_LEN;
|
||||
|
||||
/* Clear the short name string. */
|
||||
dir_entry.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_ATTRIBUTES_READ, media_ptr, directory_name, 0, 0, FX_TRACE_DIRECTORY_EVENTS, &trace_event, &trace_timestamp)
|
||||
|
||||
/* Protect against other threads accessing the media. */
|
||||
FX_PROTECT
|
||||
|
||||
/* Search the system for the supplied file name. */
|
||||
status = _fx_directory_search(media_ptr, directory_name, &dir_entry, FX_NULL, FX_NULL);
|
||||
|
||||
/* Determine if the search was successful. */
|
||||
if (status != FX_SUCCESS)
|
||||
{
|
||||
|
||||
/* Release media protection. */
|
||||
FX_UNPROTECT
|
||||
|
||||
/* Return the error code. */
|
||||
return(status);
|
||||
}
|
||||
|
||||
/* Check to make sure the found entry is a file. */
|
||||
if ((dir_entry.fx_dir_entry_attributes & (UCHAR)(FX_DIRECTORY)) == 0)
|
||||
{
|
||||
|
||||
/* Release media protection. */
|
||||
FX_UNPROTECT
|
||||
|
||||
/* Return the not a file error code. */
|
||||
return(FX_NOT_DIRECTORY);
|
||||
}
|
||||
|
||||
/* Place the current attributes into the destination. */
|
||||
*attributes_ptr = (UINT)dir_entry.fx_dir_entry_attributes;
|
||||
|
||||
/* Update the trace event with the attributes read. */
|
||||
FX_TRACE_EVENT_UPDATE(trace_event, trace_timestamp, FX_TRACE_DIRECTORY_ATTRIBUTES_READ, 0, 0, dir_entry.fx_dir_entry_attributes, 0)
|
||||
|
||||
/* Release media protection. */
|
||||
FX_UNPROTECT
|
||||
|
||||
/* File attribute read is complete, return successful status. */
|
||||
return(FX_SUCCESS);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,193 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** 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_attributes_set PORTABLE C */
|
||||
/* 6.1 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function first attempts to find the specified directory. If */
|
||||
/* found, the attribute set request is valid and the directory will */
|
||||
/* be modified with the new attributes. Otherwise, if the directory */
|
||||
/* is not found, the appropriate error code is returned to the caller. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* media_ptr Media control block pointer */
|
||||
/* directory_name Directory name pointer */
|
||||
/* attributes New dir attributes */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* return status */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* _fx_directory_entry_write Write the new directory entry */
|
||||
/* _fx_directory_search Search for the file name in */
|
||||
/* the directory structure */
|
||||
/* _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_attributes_set(FX_MEDIA *media_ptr, CHAR *directory_name, UINT attributes)
|
||||
{
|
||||
|
||||
UINT status;
|
||||
FX_DIR_ENTRY dir_entry;
|
||||
|
||||
#ifndef FX_MEDIA_STATISTICS_DISABLE
|
||||
|
||||
/* Increment the number of times this service has been called. */
|
||||
media_ptr -> fx_media_directory_attributes_sets++;
|
||||
#endif
|
||||
|
||||
/* Setup pointer to media name buffer. */
|
||||
dir_entry.fx_dir_entry_name = media_ptr -> fx_media_name_buffer + FX_MAX_LONG_NAME_LEN;
|
||||
|
||||
/* Clear the short name string. */
|
||||
dir_entry.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_ATTRIBUTES_SET, media_ptr, directory_name, attributes, 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);
|
||||
}
|
||||
|
||||
/* Search the system for the supplied file name. */
|
||||
status = _fx_directory_search(media_ptr, directory_name, &dir_entry, FX_NULL, FX_NULL);
|
||||
|
||||
/* Determine if the search was successful. */
|
||||
if (status != FX_SUCCESS)
|
||||
{
|
||||
|
||||
/* Release media protection. */
|
||||
FX_UNPROTECT
|
||||
|
||||
/* Return the error code. */
|
||||
return(status);
|
||||
}
|
||||
|
||||
/* Check to make sure the found entry is a directory. */
|
||||
if ((dir_entry.fx_dir_entry_attributes & (UCHAR)(FX_DIRECTORY)) == 0)
|
||||
{
|
||||
|
||||
/* Release media protection. */
|
||||
FX_UNPROTECT
|
||||
|
||||
/* Return the not a file error code. */
|
||||
return(FX_NOT_DIRECTORY);
|
||||
}
|
||||
|
||||
/* Place the new attributes in the directory entry. Make sure that the
|
||||
directory bit of the attributes is never changed. */
|
||||
dir_entry.fx_dir_entry_attributes = (UCHAR)(attributes | FX_DIRECTORY);
|
||||
|
||||
#ifdef FX_ENABLE_FAULT_TOLERANT
|
||||
/* Start transaction. */
|
||||
_fx_fault_tolerant_transaction_start(media_ptr);
|
||||
#endif /* FX_ENABLE_FAULT_TOLERANT */
|
||||
|
||||
/* Now write out the directory entry. */
|
||||
|
||||
status = _fx_directory_entry_write(media_ptr, &dir_entry);
|
||||
|
||||
|
||||
#ifdef FX_ENABLE_FAULT_TOLERANT
|
||||
/* Check for a bad status. If the return status is not FX_SUCCESS, finish
|
||||
the fault tolerant transaction without flushing the logs. */
|
||||
if (status != FX_SUCCESS)
|
||||
{
|
||||
FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* End transaction. */
|
||||
status = _fx_fault_tolerant_transaction_end(media_ptr);
|
||||
}
|
||||
|
||||
#endif /* FX_ENABLE_FAULT_TOLERANT */
|
||||
|
||||
/* Release media protection. */
|
||||
FX_UNPROTECT
|
||||
|
||||
/* File attribute set is complete, return status. */
|
||||
return(status);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,711 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** 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);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,106 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** FileX Component */
|
||||
/** */
|
||||
/** Directory */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
#define FX_SOURCE_CODE
|
||||
|
||||
|
||||
/* Include necessary system files. */
|
||||
|
||||
#include "fx_api.h"
|
||||
#include "fx_directory.h"
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _fx_directory_default_get PORTABLE C */
|
||||
/* 6.1 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function returns the pointer of the last path provided to the */
|
||||
/* fx_directory_default_set function. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* media_ptr Media control block pointer */
|
||||
/* return_path_name Destination string pointer */
|
||||
/* address */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* return status */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* 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_default_get(FX_MEDIA *media_ptr, CHAR **return_path_name)
|
||||
{
|
||||
|
||||
#ifndef FX_MEDIA_STATISTICS_DISABLE
|
||||
|
||||
/* Increment the number of times this service has been called. */
|
||||
media_ptr -> fx_media_directory_default_gets++;
|
||||
#endif
|
||||
|
||||
/* 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_DEFAULT_GET, media_ptr, return_path_name, 0, 0, FX_TRACE_DIRECTORY_EVENTS, 0, 0)
|
||||
|
||||
/* Protect against other threads accessing the media. */
|
||||
FX_PROTECT
|
||||
|
||||
/* Return the last pointer supplied to the set default directory function. */
|
||||
*return_path_name = media_ptr -> fx_media_default_path.fx_path_string;
|
||||
|
||||
/* Release media protection. */
|
||||
FX_UNPROTECT
|
||||
|
||||
/* Return successful status. */
|
||||
return(FX_SUCCESS);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,114 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** FileX Component */
|
||||
/** */
|
||||
/** Directory */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
#define FX_SOURCE_CODE
|
||||
|
||||
|
||||
/* Include necessary system files. */
|
||||
|
||||
#include "fx_api.h"
|
||||
#include "fx_directory.h"
|
||||
#include "fx_utility.h"
|
||||
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _fx_directory_default_get_copy PORTABLE C */
|
||||
/* 6.1.6 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function copies the last path provided to the */
|
||||
/* fx_directory_default_set function into the specified buffer. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* media_ptr Media control block pointer */
|
||||
/* return_path_name_buffer Destination buffer for name */
|
||||
/* return_path_name_buffer_size Size of buffer pointed to by */
|
||||
/* return_path_name_buffer */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* return status */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* 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), verified */
|
||||
/* memcpy usage, */
|
||||
/* resulting in version 6.1 */
|
||||
/* 04-02-2021 William E. Lamie Modified comment(s), verified */
|
||||
/* memcpy usage, */
|
||||
/* resulting in version 6.1.6 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
UINT _fx_directory_default_get_copy(FX_MEDIA *media_ptr, CHAR *return_path_name_buffer, UINT return_path_name_buffer_size)
|
||||
{
|
||||
|
||||
UINT status;
|
||||
CHAR *return_path_name;
|
||||
UINT path_name_length_with_null_terminator;
|
||||
|
||||
|
||||
/* Get the pointer to the path. */
|
||||
status = _fx_directory_default_get(media_ptr, &return_path_name);
|
||||
if (status == FX_SUCCESS)
|
||||
{
|
||||
|
||||
/* Get the length of the path. */
|
||||
path_name_length_with_null_terminator = _fx_utility_string_length_get(return_path_name, FX_MAXIMUM_PATH) + 1;
|
||||
|
||||
/* Can it fit in the user's buffer? */
|
||||
if (path_name_length_with_null_terminator <= return_path_name_buffer_size)
|
||||
{
|
||||
|
||||
/* Copy the path name into the user's buffer. */
|
||||
_fx_utility_memory_copy((UCHAR *) return_path_name, (UCHAR *) return_path_name_buffer, path_name_length_with_null_terminator); /* Use case of memcpy is verified. */
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* Buffer is too small. Return error. */
|
||||
return(FX_BUFFER_ERROR);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* Return successful status. */
|
||||
return(status);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,422 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** FileX Component */
|
||||
/** */
|
||||
/** Directory */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
#define FX_SOURCE_CODE
|
||||
|
||||
|
||||
/* Include necessary system files. */
|
||||
|
||||
#include "fx_api.h"
|
||||
#include "fx_system.h"
|
||||
#include "fx_file.h"
|
||||
#include "fx_utility.h"
|
||||
#include "fx_directory.h"
|
||||
|
||||
#ifndef FX_NO_LOCAL_PATH
|
||||
FX_LOCAL_PATH_SETUP
|
||||
#endif
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _fx_directory_default_set PORTABLE C */
|
||||
/* 6.1 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function sets the default directory of the media to the path */
|
||||
/* specified by the caller. If this path is not found, an error code */
|
||||
/* is returned. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* media_ptr Media control block pointer */
|
||||
/* new_path_name New path to set current */
|
||||
/* working directory to */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* return status */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* _fx_directory_search Search for the directory name */
|
||||
/* in the directory structure */
|
||||
/* _fx_utility_absolute_path_get Get absolute path */
|
||||
/* */
|
||||
/* 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_default_set(FX_MEDIA *media_ptr, CHAR *new_path_name)
|
||||
{
|
||||
|
||||
UINT status;
|
||||
FX_DIR_ENTRY dir_entry;
|
||||
CHAR *path_string_ptr;
|
||||
UINT path_string_capacity;
|
||||
FX_PATH *path_ptr;
|
||||
UINT i;
|
||||
|
||||
|
||||
|
||||
#ifndef FX_MEDIA_STATISTICS_DISABLE
|
||||
|
||||
/* Increment the number of times this service has been called. */
|
||||
media_ptr -> fx_media_directory_default_sets++;
|
||||
#endif
|
||||
|
||||
/* Setup pointer to media name buffer. */
|
||||
dir_entry.fx_dir_entry_name = media_ptr -> fx_media_name_buffer + FX_MAX_LONG_NAME_LEN;
|
||||
|
||||
/* Clear the short name string. */
|
||||
dir_entry.fx_dir_entry_short_name[0] = 0;
|
||||
|
||||
/* Clear the long name string. */
|
||||
dir_entry.fx_dir_entry_name[0] = (CHAR)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_DEFAULT_SET, media_ptr, new_path_name, 0, 0, FX_TRACE_DIRECTORY_EVENTS, 0, 0)
|
||||
|
||||
/* Protect against other threads accessing the media. */
|
||||
FX_PROTECT
|
||||
|
||||
/* Setup the path string pointer to the start of the current path. */
|
||||
path_string_ptr = &(media_ptr -> fx_media_default_path.fx_path_string[0]);
|
||||
|
||||
|
||||
/* Look for a root directory selection. */
|
||||
if ((!new_path_name) || (((new_path_name[0] == '\\') || (new_path_name[0] == '/')) && (new_path_name[1] == (CHAR)0)))
|
||||
{
|
||||
|
||||
/* Set the media current working directory to the root. */
|
||||
media_ptr -> fx_media_default_path.fx_path_directory.fx_dir_entry_name[0] = (CHAR) 0;
|
||||
media_ptr -> fx_media_default_path.fx_path_string[0] = (CHAR) 0;
|
||||
media_ptr -> fx_media_default_path.fx_path_string[FX_MAXIMUM_PATH - 2] = (CHAR) 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* Search the system for the supplied path and directory name. */
|
||||
status = _fx_directory_search(media_ptr, new_path_name, &dir_entry, FX_NULL, FX_NULL);
|
||||
|
||||
/* Determine if the search failed or if the entry found is not a
|
||||
directory. */
|
||||
if ((status != FX_SUCCESS) || (!(dir_entry.fx_dir_entry_attributes & FX_DIRECTORY)))
|
||||
{
|
||||
|
||||
/* Release media protection. */
|
||||
FX_UNPROTECT
|
||||
|
||||
/* Invalid Path - Return the error code. */
|
||||
return(FX_INVALID_PATH);
|
||||
}
|
||||
|
||||
/* Now update the current path string. */
|
||||
|
||||
/* Setup the path string's capacity. */
|
||||
path_string_capacity = FX_MAXIMUM_PATH - 1;
|
||||
|
||||
/* Determine if the new path is relative from the current path. */
|
||||
if ((new_path_name[0] != '\\') && (new_path_name[0] != '/'))
|
||||
{
|
||||
|
||||
/* Yes, a relative path was found. */
|
||||
|
||||
/* First check for a local path pointer stored in the thread control block.
|
||||
This is only available in ThreadX Version 4 and above. */
|
||||
#ifndef FX_NO_LOCAL_PATH
|
||||
if (_tx_thread_current_ptr -> tx_thread_filex_ptr)
|
||||
{
|
||||
|
||||
CHAR *saved_name_ptr;
|
||||
|
||||
/* First, save the name pointer of the default path. */
|
||||
saved_name_ptr = media_ptr -> fx_media_default_path.fx_path_directory.fx_dir_entry_name;
|
||||
|
||||
/* Setup the default path pointer to the local path. */
|
||||
path_ptr = (FX_PATH *)_tx_thread_current_ptr -> tx_thread_filex_ptr;
|
||||
|
||||
/* Copy the local path to the default path. */
|
||||
media_ptr -> fx_media_default_path = *path_ptr;
|
||||
|
||||
/* Restore the name pointer of the default path. */
|
||||
media_ptr -> fx_media_default_path.fx_path_directory.fx_dir_entry_name = saved_name_ptr;
|
||||
|
||||
/* Set the path pointer to the default pointer. */
|
||||
path_ptr = &media_ptr -> fx_media_default_path;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* Setup the default path to the global media path. */
|
||||
path_ptr = &media_ptr -> fx_media_default_path;
|
||||
}
|
||||
#else
|
||||
|
||||
/* Setup the default path to the global media path. */
|
||||
path_ptr = &media_ptr -> fx_media_default_path;
|
||||
#endif
|
||||
|
||||
/* First, check the current path for string overflow. If this is set,
|
||||
don't attempt to update the current path with relative information.
|
||||
The path won't be valid again until a complete path is given. */
|
||||
if (path_ptr -> fx_path_string[FX_MAXIMUM_PATH - 2] == '*')
|
||||
{
|
||||
|
||||
/* Yes, don't update the string, just finish the path set processing. */
|
||||
|
||||
/* Determine if we are at the root directory. */
|
||||
if (!dir_entry.fx_dir_entry_cluster)
|
||||
{
|
||||
/* Set the current directory back to the root directory. */
|
||||
path_ptr -> fx_path_directory.fx_dir_entry_name[0] = (CHAR) 0;
|
||||
|
||||
/* Set name to NULL. */
|
||||
dir_entry.fx_dir_entry_name[0] = (CHAR) 0;
|
||||
|
||||
/* Clear the current path string. */
|
||||
path_ptr -> fx_path_string[0] = (CHAR)0;
|
||||
|
||||
/* Clear the overflow flag in the current path string... just in
|
||||
case! */
|
||||
path_ptr -> fx_path_string[FX_MAXIMUM_PATH - 2] = (CHAR)0;
|
||||
}
|
||||
|
||||
/* Copy the new directory entry into the media control block. */
|
||||
path_ptr -> fx_path_directory = dir_entry;
|
||||
|
||||
/* Copy the name into the path name buffer. */
|
||||
for (i = 0; dir_entry.fx_dir_entry_name[i]; i++)
|
||||
{
|
||||
path_ptr -> fx_path_name_buffer[i] = dir_entry.fx_dir_entry_name[i];
|
||||
}
|
||||
|
||||
/* Reassign the pointer. */
|
||||
path_ptr -> fx_path_directory.fx_dir_entry_name = path_ptr -> fx_path_name_buffer;
|
||||
|
||||
/* Release media protection. */
|
||||
FX_UNPROTECT
|
||||
|
||||
/* Default directory set is complete, return status. */
|
||||
return(FX_SUCCESS);
|
||||
}
|
||||
|
||||
/* Move the current path starting pointer to the end of the current
|
||||
path string. */
|
||||
while ((path_string_capacity) && (*path_string_ptr != FX_NULL))
|
||||
{
|
||||
path_string_ptr++;
|
||||
path_string_capacity--;
|
||||
}
|
||||
|
||||
/* If room, place the \ character in the path string. */
|
||||
if (path_string_capacity)
|
||||
{
|
||||
|
||||
/* There is room, place the directory marker in the string. */
|
||||
*path_string_ptr++ = '\\';
|
||||
path_string_capacity--;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* Setup the default path pointer. */
|
||||
|
||||
/* First check for a local path pointer stored in the thread control block.
|
||||
This is only available in ThreadX Version 4 and above. */
|
||||
#ifndef FX_NO_LOCAL_PATH
|
||||
if (_tx_thread_current_ptr -> tx_thread_filex_ptr)
|
||||
{
|
||||
|
||||
CHAR *saved_name_ptr;
|
||||
|
||||
/* First, save the name pointer of the default path. */
|
||||
saved_name_ptr = media_ptr -> fx_media_default_path.fx_path_directory.fx_dir_entry_name;
|
||||
|
||||
/* Setup the default path pointer to the local path. */
|
||||
path_ptr = (FX_PATH *)_tx_thread_current_ptr -> tx_thread_filex_ptr;
|
||||
|
||||
/* Copy the local path to the default path. */
|
||||
media_ptr -> fx_media_default_path = *path_ptr;
|
||||
|
||||
/* Restore the name pointer of the default path. */
|
||||
media_ptr -> fx_media_default_path.fx_path_directory.fx_dir_entry_name = saved_name_ptr;
|
||||
|
||||
/* Set the path pointer to the default pointer. */
|
||||
path_ptr = &media_ptr -> fx_media_default_path;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* Setup the default path to the global media path. */
|
||||
path_ptr = &media_ptr -> fx_media_default_path;
|
||||
}
|
||||
#else
|
||||
|
||||
/* Setup the default path to the global media path. */
|
||||
path_ptr = &media_ptr -> fx_media_default_path;
|
||||
#endif
|
||||
|
||||
/* Complete path name given. Check to see if we need to clear an
|
||||
overflow character from a previous current path string update. */
|
||||
if (path_ptr -> fx_path_string[FX_MAXIMUM_PATH - 2] == '*')
|
||||
{
|
||||
path_ptr -> fx_path_string[FX_MAXIMUM_PATH - 2] = (CHAR)0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Copy what we can into the current path. */
|
||||
while (*new_path_name)
|
||||
{
|
||||
|
||||
/* Determine if there is a ".." character sequence that specifies the
|
||||
previous path. */
|
||||
if ((*new_path_name == '.') && (*(new_path_name + 1) == '.'))
|
||||
{
|
||||
|
||||
/* Yes, a backward path is found. The current path pointer
|
||||
must be moved back to just after the previous \ character. */
|
||||
|
||||
/* Skip the current \0 that is at the end of the current path. */
|
||||
path_string_capacity = path_string_capacity + 2;
|
||||
path_string_ptr = path_string_ptr - 2;
|
||||
|
||||
while (path_string_capacity <= (FX_MAXIMUM_PATH - 1))
|
||||
{
|
||||
|
||||
/* Move the current path pointer backwards until
|
||||
a \ character is found. */
|
||||
|
||||
if ((*path_string_ptr == '\\') || (*path_string_ptr == '/'))
|
||||
{
|
||||
|
||||
/* Yes, we have successfully backed up one directory. */
|
||||
break;
|
||||
}
|
||||
|
||||
/* Backup another character. */
|
||||
path_string_capacity++;
|
||||
path_string_ptr--;
|
||||
}
|
||||
|
||||
/* Adjust the new directory pointer past the .. characters */
|
||||
new_path_name = new_path_name + 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* Normal characters that need to be copied into the current path. */
|
||||
|
||||
if (path_string_capacity)
|
||||
{
|
||||
|
||||
/* Copy character from the new path into the current path string. */
|
||||
*path_string_ptr++ = *new_path_name++;
|
||||
|
||||
path_string_capacity--;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* No more room in the current path string! */
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Determine if there is still room in the current path string. */
|
||||
if (path_string_capacity)
|
||||
{
|
||||
|
||||
/* Yes, there is still room, place a NULL character at the
|
||||
end of the path. */
|
||||
*path_string_ptr = (CHAR)FX_NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* No more room. Determine if the entire path was successfully
|
||||
copied into the current path. */
|
||||
if (*new_path_name)
|
||||
{
|
||||
|
||||
/* No, we couldn't fit the entire path. Place a "*" character
|
||||
at the end to indicate that we had overflow. Note that
|
||||
the path is kept just the the directory default get call, so
|
||||
the new default path is valid. */
|
||||
path_ptr -> fx_path_string[FX_MAXIMUM_PATH - 2] = '*';
|
||||
}
|
||||
}
|
||||
|
||||
/* Determine if we are at the root directory. */
|
||||
if (!dir_entry.fx_dir_entry_cluster)
|
||||
{
|
||||
|
||||
/* Set the current directory back to the root directory. */
|
||||
dir_entry.fx_dir_entry_name[0] = (CHAR)0;
|
||||
path_ptr -> fx_path_name_buffer[0] = (CHAR)0;
|
||||
}
|
||||
|
||||
/* Copy the new directory entry into the media control block. */
|
||||
path_ptr -> fx_path_directory = dir_entry;
|
||||
|
||||
/* Copy the name. */
|
||||
for (i = 0; dir_entry.fx_dir_entry_name[i]; i++)
|
||||
{
|
||||
path_ptr -> fx_path_name_buffer[i] = dir_entry.fx_dir_entry_name[i];
|
||||
}
|
||||
|
||||
/* Reassign the pointer. */
|
||||
path_ptr -> fx_path_directory.fx_dir_entry_name = path_ptr -> fx_path_name_buffer;
|
||||
}
|
||||
|
||||
/* Release media protection. */
|
||||
FX_UNPROTECT
|
||||
|
||||
/* Default directory set is complete, return status. */
|
||||
return(FX_SUCCESS);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,451 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** 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_delete PORTABLE C */
|
||||
/* 6.1 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function first attempts to find the specified directory. */
|
||||
/* If found, the directory is examined to make sure it is empty. If */
|
||||
/* the directory is not empty, an error code is returned to the */
|
||||
/* caller. Otherwise, the directory will be deleted and its clusters */
|
||||
/* will be made available. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* media_ptr Media control block pointer */
|
||||
/* directory_name Directory name to delete */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* return status */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* _fx_directory_entry_read Read a directory entry */
|
||||
/* _fx_directory_entry_write Write the new directory entry */
|
||||
/* _fx_directory_search Search for the file name in */
|
||||
/* the directory structure */
|
||||
/* _fx_utility_logical_sector_flush Flush the written log sector */
|
||||
/* _fx_utility_FAT_entry_read Read FAT entries to calculate */
|
||||
/* the sub-directory size */
|
||||
/* _fx_utility_FAT_entry_write Write FAT entry */
|
||||
/* _fx_utility_FAT_flush Flush FAT cache */
|
||||
/* _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_delete(FX_MEDIA *media_ptr, CHAR *directory_name)
|
||||
{
|
||||
|
||||
UINT status;
|
||||
ULONG cluster, next_cluster;
|
||||
ULONG i, directory_size;
|
||||
FX_DIR_ENTRY dir_entry;
|
||||
FX_DIR_ENTRY search_directory;
|
||||
FX_DIR_ENTRY search_entry;
|
||||
|
||||
|
||||
|
||||
#ifndef FX_MEDIA_STATISTICS_DISABLE
|
||||
|
||||
/* Increment the number of times this service has been called. */
|
||||
media_ptr -> fx_media_directory_deletes++;
|
||||
#endif
|
||||
|
||||
/* 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 pointer to media name buffer. */
|
||||
search_directory.fx_dir_entry_name = media_ptr -> fx_media_name_buffer + FX_MAX_LONG_NAME_LEN * 2;
|
||||
|
||||
/* Setup search entry pointer to media name buffer. */
|
||||
search_entry.fx_dir_entry_name = media_ptr -> fx_media_name_buffer + FX_MAX_LONG_NAME_LEN * 3;
|
||||
|
||||
/* Clear the short name string of the three file names that will be worked with. */
|
||||
dir_entry.fx_dir_entry_short_name[0] = 0;
|
||||
search_directory.fx_dir_entry_short_name[0] = 0;
|
||||
search_entry.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_DELETE, media_ptr, directory_name, 0, 0, FX_TRACE_DIRECTORY_EVENTS, 0, 0)
|
||||
|
||||
/* Protect against other threads accessing the media. */
|
||||
FX_PROTECT
|
||||
|
||||
#ifdef FX_ENABLE_FAULT_TOLERANT
|
||||
/* Start transaction. */
|
||||
_fx_fault_tolerant_transaction_start(media_ptr);
|
||||
#endif /* FX_ENABLE_FAULT_TOLERANT */
|
||||
|
||||
/* Check for write protect at the media level (set by driver). */
|
||||
if (media_ptr -> fx_media_driver_write_protect)
|
||||
{
|
||||
|
||||
#ifdef FX_ENABLE_FAULT_TOLERANT
|
||||
FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
|
||||
#endif /* FX_ENABLE_FAULT_TOLERANT */
|
||||
|
||||
/* Release media protection. */
|
||||
FX_UNPROTECT
|
||||
|
||||
/* Return write protect error. */
|
||||
return(FX_WRITE_PROTECT);
|
||||
}
|
||||
|
||||
/* Search the system for the supplied directory name. */
|
||||
status = _fx_directory_search(media_ptr, directory_name, &dir_entry, FX_NULL, FX_NULL);
|
||||
|
||||
/* 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);
|
||||
}
|
||||
|
||||
/* Check to make sure the found entry is a directory. */
|
||||
if (!(dir_entry.fx_dir_entry_attributes & (UCHAR)(FX_DIRECTORY)))
|
||||
{
|
||||
|
||||
#ifdef FX_ENABLE_FAULT_TOLERANT
|
||||
FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
|
||||
#endif /* FX_ENABLE_FAULT_TOLERANT */
|
||||
|
||||
/* Release media protection. */
|
||||
FX_UNPROTECT
|
||||
|
||||
/* Return the not a directory error code. */
|
||||
return(FX_NOT_DIRECTORY);
|
||||
}
|
||||
|
||||
/* Check if the entry is read only */
|
||||
if (dir_entry.fx_dir_entry_attributes & (UCHAR)(FX_READ_ONLY))
|
||||
{
|
||||
#ifdef FX_ENABLE_FAULT_TOLERANT
|
||||
FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
|
||||
#endif /* FX_ENABLE_FAULT_TOLERANT */
|
||||
|
||||
/* Release media protection. */
|
||||
FX_UNPROTECT
|
||||
|
||||
/* Return the not a directory error code. */
|
||||
return(FX_WRITE_PROTECT);
|
||||
}
|
||||
|
||||
/* Copy the directory entry to the search directory structure for
|
||||
looking at the specified sub-directory contents. */
|
||||
search_directory = dir_entry;
|
||||
|
||||
/* Ensure that the search directory's last search cluster is cleared. */
|
||||
search_directory.fx_dir_entry_last_search_cluster = 0;
|
||||
|
||||
|
||||
/* Calculate the directory size by counting the allocated
|
||||
clusters for it. */
|
||||
i = 0;
|
||||
cluster = search_directory.fx_dir_entry_cluster;
|
||||
while (cluster < media_ptr -> fx_media_fat_reserved)
|
||||
{
|
||||
|
||||
/* Increment the cluster count. */
|
||||
i++;
|
||||
|
||||
/* Read the next FAT entry. */
|
||||
status = _fx_utility_FAT_entry_read(media_ptr, cluster, &next_cluster);
|
||||
|
||||
/* Check the return 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);
|
||||
}
|
||||
|
||||
if ((cluster < FX_FAT_ENTRY_START) || (cluster == next_cluster) || (i > media_ptr -> fx_media_total_clusters))
|
||||
{
|
||||
#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(FX_FAT_READ_ERROR);
|
||||
}
|
||||
|
||||
cluster = next_cluster;
|
||||
}
|
||||
|
||||
/* Now we can calculate the directory size. */
|
||||
directory_size = (((ULONG)media_ptr -> fx_media_bytes_per_sector) *
|
||||
((ULONG)media_ptr -> fx_media_sectors_per_cluster) * i) /
|
||||
(ULONG)FX_DIR_ENTRY_SIZE;
|
||||
|
||||
/* Also save this in the directory entry so we don't have to
|
||||
calculate it later. */
|
||||
search_directory.fx_dir_entry_file_size = directory_size;
|
||||
|
||||
/* Make sure the new name is not in the current directory. */
|
||||
/* The first two entries are skipped because they are just part of the sub-directory. */
|
||||
i = 2;
|
||||
|
||||
do
|
||||
{
|
||||
|
||||
/* Read an entry from the directory. */
|
||||
status = _fx_directory_entry_read(media_ptr, &search_directory, &i, &search_entry);
|
||||
|
||||
/* Check for error 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 error condition. */
|
||||
return(status);
|
||||
}
|
||||
|
||||
/* Determine if this is the last directory entry. */
|
||||
if (search_entry.fx_dir_entry_name[0] == FX_DIR_ENTRY_DONE)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
/* Determine if this is an empty entry. */
|
||||
if ((UCHAR)search_entry.fx_dir_entry_name[0] != (UCHAR)FX_DIR_ENTRY_FREE)
|
||||
{
|
||||
|
||||
#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(FX_DIR_NOT_EMPTY);
|
||||
}
|
||||
|
||||
i++;
|
||||
} while (i < directory_size);
|
||||
|
||||
/* At this point, we are going to delete the empty directory. */
|
||||
|
||||
#ifndef FX_MEDIA_DISABLE_SEARCH_CACHE
|
||||
|
||||
/* Invalidate the directory search saved information. */
|
||||
media_ptr -> fx_media_last_found_name[0] = FX_NULL;
|
||||
#endif
|
||||
|
||||
/* Mark the sub-directory entry as available. */
|
||||
dir_entry.fx_dir_entry_name[0] = (CHAR)FX_DIR_ENTRY_FREE;
|
||||
dir_entry.fx_dir_entry_short_name[0] = (CHAR)FX_DIR_ENTRY_FREE;
|
||||
|
||||
/* Now write out the directory entry. */
|
||||
status = _fx_directory_entry_write(media_ptr, &dir_entry);
|
||||
|
||||
/* 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);
|
||||
}
|
||||
|
||||
|
||||
/* Walk through the directory's clusters and release them. */
|
||||
cluster = search_directory.fx_dir_entry_cluster;
|
||||
|
||||
while (cluster < media_ptr -> fx_media_fat_reserved)
|
||||
{
|
||||
|
||||
/* Increment the cluster count. */
|
||||
i++;
|
||||
|
||||
|
||||
/* Read the next FAT entry. */
|
||||
status = _fx_utility_FAT_entry_read(media_ptr, cluster, &next_cluster);
|
||||
|
||||
/* Check the return 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);
|
||||
}
|
||||
|
||||
if ((cluster < FX_FAT_ENTRY_START) || (cluster == next_cluster) || (i > media_ptr -> fx_media_total_clusters))
|
||||
{
|
||||
|
||||
#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(FX_FAT_READ_ERROR);
|
||||
}
|
||||
|
||||
/* Release the current cluster. */
|
||||
|
||||
status = _fx_utility_FAT_entry_write(media_ptr, cluster, FX_FREE_CLUSTER);
|
||||
|
||||
/* Check the return 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);
|
||||
}
|
||||
|
||||
/* Increment the number of available clusters for the media. */
|
||||
media_ptr -> fx_media_available_clusters++;
|
||||
|
||||
/* Copy next cluster to current cluster. */
|
||||
cluster = next_cluster;
|
||||
}
|
||||
|
||||
#ifdef FX_FAULT_TOLERANT
|
||||
|
||||
/* Flush the cached individual FAT entries */
|
||||
_fx_utility_FAT_flush(media_ptr);
|
||||
#endif
|
||||
|
||||
/* Flush the logical sector cache. */
|
||||
status = _fx_utility_logical_sector_flush(media_ptr, ((ULONG64) 1), (ULONG64)(media_ptr -> fx_media_sectors_per_FAT), FX_FALSE);
|
||||
|
||||
#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 delete is complete, return status. */
|
||||
return(status);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,722 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** 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_utility.h"
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _fx_directory_entry_read PORTABLE C */
|
||||
/* 6.1 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function reads the supplied directory entry from the supplied */
|
||||
/* source directory. If the supplied directory entry is NULL, then */
|
||||
/* the root directory is assumed. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* media_ptr Media control block pointer */
|
||||
/* source_dir Source directory entry */
|
||||
/* entry_ptr Directory entry number */
|
||||
/* destination_ptr Pointer to destination for */
|
||||
/* the directory entry */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* return status */
|
||||
/* *entry_ptr should point to the 8:3 entry if it is a long name */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* _fx_utility_FAT_entry_read Read a FAT entry */
|
||||
/* _fx_utility_logical_sector_read Read directory sector */
|
||||
/* _fx_utility_16_unsigned_read Read a UINT from memory */
|
||||
/* _fx_utility_32_unsigned_read Read a ULONG from memory */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* FileX System Functions */
|
||||
/* */
|
||||
/* 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_entry_read(FX_MEDIA *media_ptr, FX_DIR_ENTRY *source_dir,
|
||||
ULONG *entry_ptr, FX_DIR_ENTRY *destination_ptr)
|
||||
{
|
||||
|
||||
UINT i, j, card, dotflag, get_short_name;
|
||||
UINT number_of_lfns;
|
||||
UINT status;
|
||||
ULONG cluster, next_cluster = 0;
|
||||
UINT relative_cluster;
|
||||
UINT relative_sector;
|
||||
ULONG logical_sector;
|
||||
ULONG byte_offset;
|
||||
ULONG bytes_per_cluster;
|
||||
UCHAR *read_ptr;
|
||||
CHAR *short_name_ptr;
|
||||
ULONG entry = *entry_ptr;
|
||||
|
||||
|
||||
#ifndef FX_MEDIA_STATISTICS_DISABLE
|
||||
|
||||
/* Increment the number of directory entry read requests. */
|
||||
media_ptr -> fx_media_directory_entry_reads++;
|
||||
#endif
|
||||
|
||||
/* Extended port-specific processing macro, which is by default defined to white space. */
|
||||
FX_DIRECTORY_ENTRY_READ_EXTENSION
|
||||
|
||||
/* If trace is enabled, insert this event into the trace buffer. */
|
||||
FX_TRACE_IN_LINE_INSERT(FX_TRACE_INTERNAL_DIR_ENTRY_READ, media_ptr, 0, 0, 0, FX_TRACE_INTERNAL_EVENTS, 0, 0)
|
||||
|
||||
/* Calculate the byte offset of this directory entry. */
|
||||
byte_offset = entry * FX_DIR_ENTRY_SIZE;
|
||||
|
||||
/* Determine if a sub-directory or FAT32 root directory is specified. */
|
||||
if ((source_dir) || (media_ptr -> fx_media_32_bit_FAT))
|
||||
{
|
||||
|
||||
/* Yes, a sub-directory is present. */
|
||||
|
||||
/* Calculate the number of bytes per cluster. */
|
||||
bytes_per_cluster = ((ULONG)media_ptr -> fx_media_bytes_per_sector) *
|
||||
((ULONG)media_ptr -> fx_media_sectors_per_cluster);
|
||||
|
||||
/* Check for invalid value. */
|
||||
if (bytes_per_cluster == 0)
|
||||
{
|
||||
|
||||
/* Invalid media, return error. */
|
||||
return(FX_MEDIA_INVALID);
|
||||
}
|
||||
|
||||
/* Now determine the relative cluster in the sub-directory file. */
|
||||
relative_cluster = (UINT)(byte_offset / bytes_per_cluster);
|
||||
|
||||
/* Calculate the byte offset within the cluster. */
|
||||
byte_offset = byte_offset % bytes_per_cluster;
|
||||
|
||||
/* Now figure out the relative sector within the cluster. */
|
||||
relative_sector = (UINT)(byte_offset / ((ULONG)media_ptr -> fx_media_bytes_per_sector));
|
||||
|
||||
/* Read the directory sector into the internal memory buffer. */
|
||||
|
||||
/* Determine if there is a sub-directory. */
|
||||
if (source_dir)
|
||||
{
|
||||
|
||||
/* Determine if this source directory has valid information from the previous call. */
|
||||
if ((source_dir -> fx_dir_entry_last_search_cluster) &&
|
||||
(source_dir -> fx_dir_entry_last_search_relative_cluster <= relative_cluster) &&
|
||||
(source_dir -> fx_dir_entry_last_search_log_sector == source_dir -> fx_dir_entry_log_sector) &&
|
||||
(source_dir -> fx_dir_entry_last_search_byte_offset == source_dir -> fx_dir_entry_byte_offset))
|
||||
{
|
||||
|
||||
/* Use the previous information to start the search. */
|
||||
cluster = source_dir -> fx_dir_entry_last_search_cluster;
|
||||
|
||||
/* Setup the relative cluster index to the saved relative cluster. */
|
||||
i = source_dir -> fx_dir_entry_last_search_relative_cluster;
|
||||
|
||||
/* Clear the search cluster. It will be updated prior to successful return. */
|
||||
source_dir -> fx_dir_entry_last_search_cluster = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* Nothing from the previous directory read, just setup the starting cluster to the
|
||||
beginning of the sub-directory. */
|
||||
cluster = source_dir -> fx_dir_entry_cluster;
|
||||
|
||||
/* Setup the relative cluster index to zero. */
|
||||
i = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* No, setup the starting cluster to the FAT32 root cluster. */
|
||||
cluster = media_ptr -> fx_media_root_cluster_32;
|
||||
|
||||
/* Setup the relative cluster index to zero. */
|
||||
i = 0;
|
||||
}
|
||||
|
||||
/* Loop to position to the appropriate cluster. */
|
||||
while (i < relative_cluster)
|
||||
{
|
||||
|
||||
/* Check the value of the new cluster - it must be a valid cluster number
|
||||
or something is really wrong! */
|
||||
if ((cluster < FX_FAT_ENTRY_START) || (cluster >= media_ptr -> fx_media_fat_reserved))
|
||||
{
|
||||
|
||||
/* Send error message back to caller. */
|
||||
return(FX_FILE_CORRUPT);
|
||||
}
|
||||
|
||||
/* Read the next cluster. */
|
||||
status = _fx_utility_FAT_entry_read(media_ptr, cluster, &next_cluster);
|
||||
|
||||
/* There is a potential for loop, but hardly anything can be done */
|
||||
|
||||
/* Check for I/O error. */
|
||||
if (status != FX_SUCCESS)
|
||||
{
|
||||
|
||||
/* Return error code. */
|
||||
return(status);
|
||||
}
|
||||
|
||||
/* Setup the actual cluster. */
|
||||
cluster = next_cluster;
|
||||
|
||||
/* Increment the relative cluster number. */
|
||||
i++;
|
||||
}
|
||||
|
||||
/* At this point, the directory data sector needs to be read. */
|
||||
logical_sector = ((ULONG)media_ptr -> fx_media_data_sector_start) +
|
||||
(((ULONG)cluster - FX_FAT_ENTRY_START) *
|
||||
((ULONG)media_ptr -> fx_media_sectors_per_cluster)) +
|
||||
relative_sector;
|
||||
|
||||
/* Read the logical directory sector. */
|
||||
status = _fx_utility_logical_sector_read(media_ptr, (ULONG64) logical_sector,
|
||||
media_ptr -> fx_media_memory_buffer, ((ULONG) 1), FX_DIRECTORY_SECTOR);
|
||||
|
||||
/* Determine if an error occurred. */
|
||||
if (status != FX_SUCCESS)
|
||||
{
|
||||
|
||||
/* Return error code. */
|
||||
return(status);
|
||||
}
|
||||
|
||||
/* Calculate the byte offset within this sector. */
|
||||
byte_offset = byte_offset % media_ptr -> fx_media_bytes_per_sector;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* Read the entry from the root directory. */
|
||||
|
||||
/* Determine which sector the requested root directory entry is in. */
|
||||
logical_sector = (byte_offset / media_ptr -> fx_media_bytes_per_sector) +
|
||||
(ULONG)media_ptr -> fx_media_root_sector_start;
|
||||
|
||||
/* Read the logical directory sector. */
|
||||
status = _fx_utility_logical_sector_read(media_ptr, (ULONG64) logical_sector,
|
||||
media_ptr -> fx_media_memory_buffer, ((ULONG) 1), FX_DIRECTORY_SECTOR);
|
||||
|
||||
/* Determine if an error occurred. */
|
||||
if (status != FX_SUCCESS)
|
||||
{
|
||||
|
||||
/* Return error code. */
|
||||
return(status);
|
||||
}
|
||||
|
||||
/* Set the cluster and relative variables (not used in this case) to avoid any compiler
|
||||
warnings. */
|
||||
relative_cluster = relative_sector = cluster = 0;
|
||||
|
||||
/* Now calculate the byte offset into this sector. */
|
||||
byte_offset = byte_offset -
|
||||
((logical_sector - (ULONG)media_ptr -> fx_media_root_sector_start) *
|
||||
media_ptr -> fx_media_bytes_per_sector);
|
||||
}
|
||||
|
||||
/* Setup a pointer into the buffer. */
|
||||
read_ptr = (UCHAR *)media_ptr -> fx_media_memory_buffer + (UINT)byte_offset;
|
||||
|
||||
/* Save the logical sector and byte offset in the returned directory entry. */
|
||||
destination_ptr -> fx_dir_entry_log_sector = logical_sector;
|
||||
destination_ptr -> fx_dir_entry_byte_offset = byte_offset;
|
||||
|
||||
/* Clear the short file name information. */
|
||||
destination_ptr -> fx_dir_entry_long_name_shorted = 0;
|
||||
destination_ptr -> fx_dir_entry_short_name[0] = 0;
|
||||
|
||||
/* Setup short name pointer. */
|
||||
short_name_ptr = destination_ptr -> fx_dir_entry_name;
|
||||
|
||||
/* Check if long file name exists. */
|
||||
get_short_name = 0;
|
||||
if ((*(read_ptr + 11) == (UCHAR)FX_LONG_NAME) && (*read_ptr != (UCHAR)FX_DIR_ENTRY_FREE))
|
||||
{
|
||||
|
||||
/* Collate the long name. */
|
||||
|
||||
/* Pickup the file name length. */
|
||||
i = (((UINT)(*read_ptr & (UCHAR)0x1f) - 1) * FX_LONG_NAME_ENTRY_LEN) & 0xFFFFFFFF;
|
||||
|
||||
/* Save the number of LFN entries. */
|
||||
number_of_lfns = (UINT)(*read_ptr & (UCHAR)0x1f);
|
||||
|
||||
/* Check the file name size. */
|
||||
if (i >= (FX_MAX_LONG_NAME_LEN - 1))
|
||||
{
|
||||
|
||||
/* Name is too big, shorten it. */
|
||||
get_short_name = 1;
|
||||
destination_ptr -> fx_dir_entry_long_name_shorted = (UINT)(*read_ptr & (UCHAR)0x1f);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* Size of name is fine, save pointer to short file name. */
|
||||
short_name_ptr = destination_ptr -> fx_dir_entry_short_name;
|
||||
|
||||
/* Loop to make sure the long file name is NULL terminated. */
|
||||
j = i + FX_LONG_NAME_ENTRY_LEN + 1;
|
||||
do
|
||||
{
|
||||
/* Place a NULL in the long name. */
|
||||
destination_ptr -> fx_dir_entry_name[i] = 0;
|
||||
|
||||
/* Position to the next entry. */
|
||||
i++;
|
||||
} while ((i < j) && (i < FX_MAX_LONG_NAME_LEN));
|
||||
}
|
||||
|
||||
/* Loop to pickup the rest of the name. */
|
||||
do
|
||||
{
|
||||
|
||||
/* Get the lower 5 bit containing the cardinality. */
|
||||
card = (UINT)(*read_ptr & (UCHAR)0x1f) - 1;
|
||||
|
||||
/* For simplicity no checksum or cardinality checking is done */
|
||||
if (get_short_name == 0)
|
||||
{
|
||||
|
||||
/* Loop to pickup name. */
|
||||
for (i = 1, j = 0; i < FX_DIR_ENTRY_SIZE; i += 2)
|
||||
{
|
||||
|
||||
if ((i == 11) || (i == 26))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
/* i = 12, 27 is not generated due to +=2 */
|
||||
if (i == 13)
|
||||
{
|
||||
i = 12;
|
||||
continue; /* this time next unicode is byte offset 14*/
|
||||
}
|
||||
|
||||
/* Determine if there is an actual unicode character present. */
|
||||
if (read_ptr[i + 1])
|
||||
{
|
||||
|
||||
/* Extended byte is non-zero, make sure both bytes of the unicode entry are not
|
||||
all ones, since this is a normal case. */
|
||||
if ((read_ptr[i + 1] != (UCHAR)0xFF) || (read_ptr[i] != (UCHAR)0xFF))
|
||||
{
|
||||
|
||||
/* Name is an actual unicode name, shorten it. */
|
||||
get_short_name = 1;
|
||||
|
||||
/* Save the number of directory entries the LFN has. This will be
|
||||
used later when updating the 8.3 portion of the LFN. */
|
||||
destination_ptr -> fx_dir_entry_long_name_shorted = number_of_lfns;
|
||||
|
||||
/* Setup short name pointer. */
|
||||
short_name_ptr = destination_ptr -> fx_dir_entry_name;
|
||||
}
|
||||
}
|
||||
|
||||
/* Determine if the character is NULL. */
|
||||
if ((read_ptr[i] == FX_NULL) || (read_ptr[i] == (UCHAR)0xFF))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Determine if the name is too big. */
|
||||
if ((card * 13 + j) >= (FX_MAX_LONG_NAME_LEN - 1))
|
||||
{
|
||||
|
||||
/* Name is actually too big, shorten it. */
|
||||
get_short_name = 1;
|
||||
|
||||
/* Save the number of directory entries the LFN has. This will be
|
||||
used later when updating the 8.3 portion of the LFN. */
|
||||
destination_ptr -> fx_dir_entry_long_name_shorted = number_of_lfns;
|
||||
|
||||
/* Also reposition the short name pointer. */
|
||||
short_name_ptr = destination_ptr -> fx_dir_entry_name;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
/* Each entry contains 13 unicode and first byte ASCII, second byte is extended. */
|
||||
destination_ptr -> fx_dir_entry_name[13 * card + j] = (CHAR)read_ptr[i];
|
||||
|
||||
j++;
|
||||
}
|
||||
}
|
||||
|
||||
/* Determine if a new sector needs to be read. */
|
||||
if (byte_offset + FX_DIR_ENTRY_SIZE >= media_ptr -> fx_media_bytes_per_sector)
|
||||
{
|
||||
|
||||
/* Determine if a sub-directory or FAT32 root directory is specified. */
|
||||
if ((source_dir) || (media_ptr -> fx_media_32_bit_FAT))
|
||||
{
|
||||
|
||||
/* Determine the next sector of the directory entry. */
|
||||
if (relative_sector < (media_ptr -> fx_media_sectors_per_cluster - 1))
|
||||
{
|
||||
|
||||
/* More sectors in this cluster. */
|
||||
|
||||
/* Simply increment the logical sector. */
|
||||
logical_sector++;
|
||||
|
||||
/* Increment the relative sector. */
|
||||
relative_sector++;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* We need to move to the next cluster. */
|
||||
|
||||
/* Pickup the next cluster. */
|
||||
status = _fx_utility_FAT_entry_read(media_ptr, cluster, &next_cluster);
|
||||
|
||||
/* Check for I/O error. */
|
||||
if (status != FX_SUCCESS)
|
||||
{
|
||||
|
||||
/* Return error code. */
|
||||
return(status);
|
||||
}
|
||||
|
||||
/* Copy next cluster to the current cluster. */
|
||||
cluster = next_cluster;
|
||||
|
||||
/* Check the value of the new cluster - it must be a valid cluster number
|
||||
or something is really wrong! */
|
||||
if ((cluster < FX_FAT_ENTRY_START) || (cluster >= media_ptr -> fx_media_fat_reserved))
|
||||
{
|
||||
|
||||
/* Send error message back to caller. */
|
||||
return(FX_FILE_CORRUPT);
|
||||
}
|
||||
|
||||
/* Now increment the relative cluster. */
|
||||
relative_cluster++;
|
||||
|
||||
/* Setup the relative sector (this is zero for subsequent cluster. */
|
||||
relative_sector = 0;
|
||||
|
||||
/* Calculate the next logical sector. */
|
||||
logical_sector = ((ULONG)media_ptr -> fx_media_data_sector_start) +
|
||||
(((ULONG)cluster - FX_FAT_ENTRY_START) *
|
||||
((ULONG)media_ptr -> fx_media_sectors_per_cluster));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* Non-FAT 32 root directory. */
|
||||
|
||||
/* Advance to the next sector. */
|
||||
logical_sector++;
|
||||
|
||||
/* Determine if the logical sector is valid. */
|
||||
if (logical_sector >= (ULONG)(media_ptr -> fx_media_root_sector_start + media_ptr -> fx_media_root_sectors))
|
||||
{
|
||||
|
||||
/* Trying to read past root directory - send error message back to caller. */
|
||||
return(FX_FILE_CORRUPT);
|
||||
}
|
||||
}
|
||||
|
||||
/* Read the new sector. */
|
||||
status = _fx_utility_logical_sector_read(media_ptr, (ULONG64) logical_sector,
|
||||
media_ptr -> fx_media_memory_buffer, ((ULONG) 1), FX_DIRECTORY_SECTOR);
|
||||
|
||||
/* Check I/O status. */
|
||||
if (status != FX_SUCCESS)
|
||||
{
|
||||
return(status);
|
||||
}
|
||||
|
||||
/* Set the byte offset to 0 for new sector. */
|
||||
byte_offset = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* Calculate the new byte offset. */
|
||||
byte_offset += FX_DIR_ENTRY_SIZE;
|
||||
}
|
||||
|
||||
/* Calculate the next read pointer. */
|
||||
read_ptr = (UCHAR *)media_ptr -> fx_media_memory_buffer + (UINT) byte_offset;
|
||||
|
||||
/* Move to the next entry. */
|
||||
entry++;
|
||||
} while (card > 0);
|
||||
|
||||
/* Set flag indicating long file name is present. */
|
||||
destination_ptr -> fx_dir_entry_long_name_present = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* No long file name is present. */
|
||||
get_short_name = 1;
|
||||
}
|
||||
|
||||
/* Determine if we need to clear the long name flag. */
|
||||
if (get_short_name == 1)
|
||||
{
|
||||
|
||||
/* Clear the long name flag. */
|
||||
destination_ptr -> fx_dir_entry_long_name_present = 0;
|
||||
}
|
||||
|
||||
/* Pickup the short file name. */
|
||||
short_name_ptr[0] = 0;
|
||||
dotflag = 0;
|
||||
for (i = 0, j = 0; i < (FX_DIR_NAME_SIZE + FX_DIR_EXT_SIZE); i++)
|
||||
{
|
||||
|
||||
/* Check for a NULL. */
|
||||
if ((CHAR)read_ptr[i] == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
/* Check for a dot. This happens for the first two directory entries, no
|
||||
extra dot is needed. */
|
||||
if ((CHAR)read_ptr[i] == '.')
|
||||
{
|
||||
dotflag = 2;
|
||||
}
|
||||
|
||||
/* Check for a space. */
|
||||
if ((CHAR)read_ptr[i] == ' ')
|
||||
{
|
||||
/* Put a dot if a character comes after space. */
|
||||
if (dotflag == 0)
|
||||
{
|
||||
dotflag = 1;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Check for the main short file name size. */
|
||||
if (i == FX_DIR_NAME_SIZE)
|
||||
{
|
||||
/* Check to see if we need to insert a dot. */
|
||||
if (dotflag == 0)
|
||||
{
|
||||
dotflag = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Check to see if we need to add a dot. */
|
||||
if (dotflag == 1)
|
||||
{
|
||||
/* Add dot to short file name. */
|
||||
short_name_ptr[j++] = '.';
|
||||
dotflag = 2; /* no more dot for spaces */
|
||||
}
|
||||
|
||||
/* Copy a character. */
|
||||
short_name_ptr[j] = (CHAR)read_ptr[i];
|
||||
|
||||
/* Increment size. */
|
||||
j++;
|
||||
}
|
||||
|
||||
/* Determine if a long file name is present and its associated short file
|
||||
name is actually free. */
|
||||
if ((destination_ptr -> fx_dir_entry_long_name_present) && (((UCHAR)short_name_ptr[0]) == (UCHAR)FX_DIR_ENTRY_FREE))
|
||||
{
|
||||
|
||||
/* Yes, the short file name is really free even though long file name entries directly precede it.
|
||||
In this case, simply place the free directory marker at the front of the long file name. */
|
||||
destination_ptr -> fx_dir_entry_name[0] = (CHAR)FX_DIR_ENTRY_FREE;
|
||||
short_name_ptr[0] = (CHAR)0;
|
||||
}
|
||||
|
||||
/* Determine if the short name pointer is NULL while the read pointer is
|
||||
non-NULL. */
|
||||
if ((short_name_ptr[0] == 0) && (read_ptr[0] == ' '))
|
||||
{
|
||||
|
||||
/* This condition can occur with an all blank volume name. Simply
|
||||
copy the volume name to the short name in this case. */
|
||||
for (j = 0; j < (FX_DIR_NAME_SIZE + FX_DIR_EXT_SIZE); j++)
|
||||
{
|
||||
|
||||
/* Copy a byte of the volume name. */
|
||||
short_name_ptr[j] = (CHAR)read_ptr[j];
|
||||
}
|
||||
}
|
||||
|
||||
/* Set end of string to null. */
|
||||
short_name_ptr[j] = 0;
|
||||
|
||||
/* Load up the destination directory entry. */
|
||||
read_ptr += (FX_DIR_NAME_SIZE + FX_DIR_EXT_SIZE);
|
||||
|
||||
/* Copy the attribute into the destination. */
|
||||
destination_ptr -> fx_dir_entry_attributes = *read_ptr++;
|
||||
|
||||
/* Pickup the reserved byte. */
|
||||
destination_ptr -> fx_dir_entry_reserved = *read_ptr++;
|
||||
|
||||
/* Check for an undocumented NT file name feature for optimizing the storage
|
||||
of all lower case file names that otherwise are valid 8.3 file names. The
|
||||
following reserved bit definitions are present:
|
||||
|
||||
BIT3 - set if 8.3 is all in lower case and no extended filename.
|
||||
BIT4 - set for file, clear for directory entry if no extended filename.
|
||||
|
||||
This is true for all NT systems. Prior to NT follows MSDOS FAT documentation and
|
||||
is set to 0x00, all bits cleared. Therefore if BIT3 is set force lowercase. */
|
||||
if ((get_short_name) && (destination_ptr -> fx_dir_entry_reserved & 0x08))
|
||||
{
|
||||
|
||||
/* Microsoft undocumented NT file name feature... convert short name to lower
|
||||
case. */
|
||||
for (j = 0; j <= (FX_DIR_NAME_SIZE + FX_DIR_EXT_SIZE) && (short_name_ptr[j] != 0x00); j++)
|
||||
{
|
||||
|
||||
/* Determine if an upper case character is present. */
|
||||
if ((short_name_ptr[j] >= 'A') && (short_name_ptr[j] <= 'Z'))
|
||||
{
|
||||
|
||||
/* Yes, an upper case character is present. Force it to lower case. */
|
||||
short_name_ptr[j] = (CHAR)(short_name_ptr[j] + 32);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Pickup the created time in milliseconds. */
|
||||
destination_ptr -> fx_dir_entry_created_time_ms = *read_ptr++;
|
||||
|
||||
/* Pickup the created time. */
|
||||
destination_ptr -> fx_dir_entry_created_time = _fx_utility_16_unsigned_read(read_ptr);
|
||||
read_ptr = read_ptr + 2; /* Always 2 bytes */
|
||||
|
||||
/* Pickup the created date. */
|
||||
destination_ptr -> fx_dir_entry_created_date = _fx_utility_16_unsigned_read(read_ptr);
|
||||
read_ptr = read_ptr + 2; /* Always 2 bytes */
|
||||
|
||||
/* Pickup the last accessed date. */
|
||||
destination_ptr -> fx_dir_entry_last_accessed_date = _fx_utility_16_unsigned_read(read_ptr);
|
||||
read_ptr = read_ptr + 2; /* Always 2 bytes */
|
||||
|
||||
/* read the upper 2 bytes of starting cluster - required only for 32 bit FAT */
|
||||
if (media_ptr -> fx_media_32_bit_FAT)
|
||||
{
|
||||
|
||||
/* FAT32 only. */
|
||||
destination_ptr -> fx_dir_entry_cluster = _fx_utility_16_unsigned_read(read_ptr);
|
||||
destination_ptr -> fx_dir_entry_cluster <<= 16;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Not required for non FAT32. */
|
||||
destination_ptr -> fx_dir_entry_cluster = 0;
|
||||
}
|
||||
|
||||
/* Advance the read pointer. */
|
||||
read_ptr = read_ptr + 2; /* Always 2 bytes */
|
||||
|
||||
/* Copy the time into the destination. */
|
||||
destination_ptr -> fx_dir_entry_time = _fx_utility_16_unsigned_read(read_ptr);
|
||||
read_ptr = read_ptr + 2; /* Always 2 bytes */
|
||||
|
||||
/* Copy the date into the destination. */
|
||||
destination_ptr -> fx_dir_entry_date = _fx_utility_16_unsigned_read(read_ptr);
|
||||
read_ptr = read_ptr + 2; /* Always 2 bytes */
|
||||
|
||||
/* Copy the starting cluster into the destination. */
|
||||
destination_ptr -> fx_dir_entry_cluster += _fx_utility_16_unsigned_read(read_ptr);
|
||||
read_ptr = read_ptr + 2; /* Always 2 bytes */
|
||||
|
||||
/* Copy the file size into the destination. */
|
||||
destination_ptr -> fx_dir_entry_file_size = _fx_utility_32_unsigned_read(read_ptr);
|
||||
|
||||
/* Clear the destination search specific fields. */
|
||||
destination_ptr -> fx_dir_entry_last_search_cluster = 0;
|
||||
destination_ptr -> fx_dir_entry_last_search_relative_cluster = 0;
|
||||
destination_ptr -> fx_dir_entry_last_search_log_sector = 0;
|
||||
destination_ptr -> fx_dir_entry_last_search_byte_offset = 0;
|
||||
|
||||
/* Remember the entry number. */
|
||||
destination_ptr -> fx_dir_entry_number = entry;
|
||||
|
||||
/* Return entry number. */
|
||||
*entry_ptr = entry;
|
||||
|
||||
/* Determine if we should remember the last cluster and relative cluster. */
|
||||
if (source_dir)
|
||||
{
|
||||
|
||||
/* Yes, remember the last cluster and relative cluster for a subsequent call
|
||||
to read a directory entry. */
|
||||
source_dir -> fx_dir_entry_last_search_cluster = cluster;
|
||||
source_dir -> fx_dir_entry_last_search_relative_cluster = relative_cluster;
|
||||
|
||||
/* Also remember several other items that are unique to the directory... just to verify that the
|
||||
search information can be used. */
|
||||
source_dir -> fx_dir_entry_last_search_log_sector = source_dir -> fx_dir_entry_log_sector;
|
||||
source_dir -> fx_dir_entry_last_search_byte_offset = source_dir -> fx_dir_entry_byte_offset;
|
||||
}
|
||||
|
||||
/* Return success to the caller. */
|
||||
return(FX_SUCCESS);
|
||||
}
|
||||
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,136 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** 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_utility.h"
|
||||
|
||||
#ifndef FX_NO_LOCAL_PATH
|
||||
FX_LOCAL_PATH_SETUP
|
||||
#endif
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _fx_directory_first_entry_find PORTABLE C */
|
||||
/* 6.1 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function returns the first directory entry of the current */
|
||||
/* working directory. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* media_ptr Media control block pointer */
|
||||
/* directory_name Destination for directory */
|
||||
/* name */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* return status */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* _fx_directory_next_entry_find Find next directory entry */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* FileX System Functions */
|
||||
/* */
|
||||
/* 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_first_entry_find(FX_MEDIA *media_ptr, CHAR *directory_name)
|
||||
{
|
||||
|
||||
UINT status;
|
||||
|
||||
|
||||
#ifndef FX_MEDIA_STATISTICS_DISABLE
|
||||
|
||||
/* Increment the number of times this service has been called. */
|
||||
media_ptr -> fx_media_directory_first_entry_finds++;
|
||||
#endif
|
||||
|
||||
/* 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_FIRST_ENTRY_FIND, media_ptr, directory_name, 0, 0, FX_TRACE_DIRECTORY_EVENTS, 0, 0)
|
||||
|
||||
/* Protect against other threads accessing the media. */
|
||||
FX_PROTECT
|
||||
|
||||
/* Determine if a local path is in effect at this point. */
|
||||
#ifndef FX_NO_LOCAL_PATH
|
||||
if (_tx_thread_current_ptr -> tx_thread_filex_ptr)
|
||||
{
|
||||
|
||||
/* Yes, there is a local path. Set the current entry to zero. */
|
||||
((FX_PATH *)_tx_thread_current_ptr -> tx_thread_filex_ptr) -> fx_path_current_entry = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* Use global default directory. Set the current entry to 0 in
|
||||
order to pickup the first entry. */
|
||||
media_ptr -> fx_media_default_path.fx_path_current_entry = 0;
|
||||
}
|
||||
#else
|
||||
|
||||
/* Set the current entry to 0 in order to pickup the first entry. */
|
||||
media_ptr -> fx_media_default_path.fx_path_current_entry = 0;
|
||||
#endif
|
||||
|
||||
/* Release media protection. */
|
||||
FX_UNPROTECT
|
||||
|
||||
/* Call the next directory entry to pickup the first entry. */
|
||||
status = _fx_directory_next_entry_find(media_ptr, directory_name);
|
||||
|
||||
/* Return status to the caller. */
|
||||
return(status);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,146 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** 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_utility.h"
|
||||
|
||||
#ifndef FX_NO_LOCAL_PATH
|
||||
FX_LOCAL_PATH_SETUP
|
||||
#endif
|
||||
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _fx_directory_first_full_entry_find PORTABLE C */
|
||||
/* 6.1 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function returns the first directory entry of the current */
|
||||
/* working directory and selected information about the entry. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* media_ptr Media control block pointer */
|
||||
/* directory_name Destination for directory */
|
||||
/* name */
|
||||
/* attributes Destination for attributes */
|
||||
/* size Destination for size */
|
||||
/* year Destination for year */
|
||||
/* month Destination for month */
|
||||
/* day Destination for day */
|
||||
/* hour Destination for hour */
|
||||
/* minute Destination for minute */
|
||||
/* second Destination for second */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* return status */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* _fx_directory_next_full_entry_find Find next full directory entry*/
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* FileX System Functions */
|
||||
/* */
|
||||
/* 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_first_full_entry_find(FX_MEDIA *media_ptr,
|
||||
CHAR *directory_name, UINT *attributes, ULONG *size,
|
||||
UINT *year, UINT *month, UINT *day, UINT *hour, UINT *minute, UINT *second)
|
||||
{
|
||||
|
||||
UINT status;
|
||||
|
||||
|
||||
#ifndef FX_MEDIA_STATISTICS_DISABLE
|
||||
|
||||
/* Increment the number of times this service has been called. */
|
||||
media_ptr -> fx_media_directory_first_full_entry_finds++;
|
||||
#endif
|
||||
|
||||
/* 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_FIRST_FULL_ENTRY_FIND, media_ptr, directory_name, 0, 0, FX_TRACE_DIRECTORY_EVENTS, 0, 0)
|
||||
|
||||
/* Protect against other threads accessing the media. */
|
||||
FX_PROTECT
|
||||
|
||||
/* Determine if a local path is in effect at this point. */
|
||||
#ifndef FX_NO_LOCAL_PATH
|
||||
if (_tx_thread_current_ptr -> tx_thread_filex_ptr)
|
||||
{
|
||||
|
||||
/* Yes, there is a local path. Set the current entry to zero. */
|
||||
((FX_PATH *)_tx_thread_current_ptr -> tx_thread_filex_ptr) -> fx_path_current_entry = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* Use global default directory. Set the current entry to 0 in
|
||||
order to pickup the first entry. */
|
||||
media_ptr -> fx_media_default_path.fx_path_current_entry = 0;
|
||||
}
|
||||
#else
|
||||
|
||||
/* Set the current entry to 0 in order to pickup the first entry. */
|
||||
media_ptr -> fx_media_default_path.fx_path_current_entry = 0;
|
||||
#endif
|
||||
|
||||
/* Release media protection. */
|
||||
FX_UNPROTECT
|
||||
|
||||
/* Call the next directory full entry service to pickup the first entry. */
|
||||
status = _fx_directory_next_full_entry_find(media_ptr, directory_name, attributes,
|
||||
size, year, month, day, hour, minute, second);
|
||||
|
||||
/* Return status to the caller. */
|
||||
return(status);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,770 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** 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_utility.h"
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _fx_directory_free_search PORTABLE C */
|
||||
/* 6.1.12 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function searches the media for a free directory entry. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* media_ptr Media control block pointer */
|
||||
/* directory_ptr Pointer to directory to */
|
||||
/* search in */
|
||||
/* entry_ptr Pointer to directory entry */
|
||||
/* record */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* return status */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* _fx_directory_entry_read Read entries from directory */
|
||||
/* _fx_directory_entry_write Write entries to directory */
|
||||
/* _fx_utility_FAT_entry_read Read a FAT entry */
|
||||
/* _fx_utility_FAT_entry_write Write a FAT entry */
|
||||
/* _fx_utility_FAT_flush Flush written FAT entries */
|
||||
/* _fx_utility_logical_sector_flush Flush logical sector cache */
|
||||
/* _fx_utility_logical_sector_read Read logical sector */
|
||||
/* _fx_utility_logical_sector_write Write logical sector */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* FileX System Functions */
|
||||
/* */
|
||||
/* 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 */
|
||||
/* 07-29-2022 Bhupendra Naphade Modified comment(s), */
|
||||
/* updated available cluster */
|
||||
/* check for sub directory, */
|
||||
/* resulting in version 6.1.12 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
UINT _fx_directory_free_search(FX_MEDIA *media_ptr, FX_DIR_ENTRY *directory_ptr, FX_DIR_ENTRY *entry_ptr)
|
||||
{
|
||||
|
||||
ULONG i, j;
|
||||
UCHAR *work_ptr;
|
||||
UINT status, total_entries;
|
||||
ULONG entry_sector, entry_offset;
|
||||
ULONG FAT_index, FAT_value;
|
||||
ULONG cluster, total_clusters, clusters_needed;
|
||||
ULONG first_new_cluster, last_cluster, clusters;
|
||||
ULONG directory_index;
|
||||
ULONG directory_entries;
|
||||
ULONG logical_sector;
|
||||
FX_DIR_ENTRY *search_dir_ptr;
|
||||
ULONG free_entry_start;
|
||||
UINT sectors;
|
||||
|
||||
FX_INT_SAVE_AREA
|
||||
|
||||
|
||||
|
||||
#ifndef FX_MEDIA_STATISTICS_DISABLE
|
||||
|
||||
/* Increment the number of directory free entry search requests. */
|
||||
media_ptr -> fx_media_directory_free_searches++;
|
||||
#endif
|
||||
|
||||
/* Initialize the entry sector values. */
|
||||
entry_sector = entry_offset = 0;
|
||||
|
||||
/* Set the long file name flag to false. */
|
||||
entry_ptr -> fx_dir_entry_long_name_present = 0;
|
||||
|
||||
/* Are there leading dots? */
|
||||
if (entry_ptr -> fx_dir_entry_name[0] == '.')
|
||||
{
|
||||
|
||||
/* Is there more than 1 dot? */
|
||||
if (entry_ptr -> fx_dir_entry_name[1] == '.')
|
||||
{
|
||||
/* Yes, consider the name invalid. */
|
||||
return(FX_INVALID_NAME);
|
||||
}
|
||||
}
|
||||
|
||||
/* Determine if a long file name is present. */
|
||||
for (i = 0, j = 0; entry_ptr -> fx_dir_entry_name[i]; i++)
|
||||
{
|
||||
|
||||
/* Check for upper-case characters. */
|
||||
if ((entry_ptr -> fx_dir_entry_name[i] >= 'A') && (entry_ptr -> fx_dir_entry_name[i] <= 'Z'))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
/* Check for numeric characters. */
|
||||
else if ((entry_ptr -> fx_dir_entry_name[i] >= '0') && (entry_ptr -> fx_dir_entry_name[i] <= '9'))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
/* Check for any lower-case characters. */
|
||||
else if ((entry_ptr -> fx_dir_entry_name[i] >= 'a') && (entry_ptr -> fx_dir_entry_name[i] <= 'z'))
|
||||
{
|
||||
entry_ptr -> fx_dir_entry_long_name_present = 1;
|
||||
}
|
||||
/* Check for a space in the middle of the name. */
|
||||
else if (entry_ptr -> fx_dir_entry_name[i] == ' ')
|
||||
{
|
||||
entry_ptr -> fx_dir_entry_long_name_present = 1;
|
||||
}
|
||||
/* Check for a dot in the name. */
|
||||
else if (entry_ptr -> fx_dir_entry_name[i] == '.')
|
||||
{
|
||||
/* Determine if this is the first dot detected. */
|
||||
if (j == 0)
|
||||
{
|
||||
/* First dot, remember where it was. */
|
||||
j = i;
|
||||
|
||||
/* Determine if this is a leading dot. */
|
||||
if (i == 0)
|
||||
{
|
||||
|
||||
/* Leading dot detected, treat as a long filename. */
|
||||
entry_ptr -> fx_dir_entry_long_name_present = 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Second dot detected, must have a long file name. */
|
||||
entry_ptr -> fx_dir_entry_long_name_present = 1;
|
||||
}
|
||||
}
|
||||
/* Check for a special 0xE5 character. */
|
||||
else if ((UCHAR)entry_ptr -> fx_dir_entry_name[i] == (UCHAR)0xE5)
|
||||
{
|
||||
entry_ptr -> fx_dir_entry_long_name_present = 1;
|
||||
}
|
||||
/* Check for code point value greater than 127. */
|
||||
else if ((UCHAR)entry_ptr -> fx_dir_entry_name[i] > (UCHAR)127)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
/* Check for any special characters. */
|
||||
else if ((entry_ptr -> fx_dir_entry_name[i] == '~') ||
|
||||
(entry_ptr -> fx_dir_entry_name[i] == '-') ||
|
||||
(entry_ptr -> fx_dir_entry_name[i] == '_') ||
|
||||
(entry_ptr -> fx_dir_entry_name[i] == '}') ||
|
||||
(entry_ptr -> fx_dir_entry_name[i] == '{') ||
|
||||
(entry_ptr -> fx_dir_entry_name[i] == '(') ||
|
||||
(entry_ptr -> fx_dir_entry_name[i] == ')') ||
|
||||
(entry_ptr -> fx_dir_entry_name[i] == '`') ||
|
||||
(entry_ptr -> fx_dir_entry_name[i] == '\'') ||
|
||||
(entry_ptr -> fx_dir_entry_name[i] == '!') ||
|
||||
(entry_ptr -> fx_dir_entry_name[i] == '#') ||
|
||||
(entry_ptr -> fx_dir_entry_name[i] == '$') ||
|
||||
(entry_ptr -> fx_dir_entry_name[i] == '&') ||
|
||||
(entry_ptr -> fx_dir_entry_name[i] == '@') ||
|
||||
(entry_ptr -> fx_dir_entry_name[i] == '^') ||
|
||||
(entry_ptr -> fx_dir_entry_name[i] == '%'))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
/* Check for long filename special characters. */
|
||||
else if ((entry_ptr -> fx_dir_entry_name[i] == '+') ||
|
||||
(entry_ptr -> fx_dir_entry_name[i] == ',') ||
|
||||
(entry_ptr -> fx_dir_entry_name[i] == ';') ||
|
||||
(entry_ptr -> fx_dir_entry_name[i] == '=') ||
|
||||
(entry_ptr -> fx_dir_entry_name[i] == '[') ||
|
||||
(entry_ptr -> fx_dir_entry_name[i] == ']'))
|
||||
{
|
||||
entry_ptr -> fx_dir_entry_long_name_present = 1;
|
||||
}
|
||||
/* Something is wrong with the supplied name. */
|
||||
else
|
||||
{
|
||||
return(FX_INVALID_NAME);
|
||||
}
|
||||
}
|
||||
|
||||
/* Determine if a dot was found. */
|
||||
if (j != 0)
|
||||
{
|
||||
|
||||
/* Yes, Determine if the extension exceeds a 3 character extension. */
|
||||
if ((i - j) > 4)
|
||||
{
|
||||
|
||||
/* Yes, long file name is present. */
|
||||
entry_ptr -> fx_dir_entry_long_name_present = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Calculate the total entries needed. */
|
||||
if ((i <= 12) && (entry_ptr -> fx_dir_entry_long_name_present == 0))
|
||||
{
|
||||
|
||||
/* Initialize the total entries to 1. */
|
||||
total_entries = 1;
|
||||
|
||||
/* Check for special instance of long file name. */
|
||||
if ((j >= 9) || ((i - j) >= 9))
|
||||
{
|
||||
|
||||
/* The dot is after 8 character or there is no dot and the name
|
||||
is greater than 8 character. */
|
||||
entry_ptr -> fx_dir_entry_long_name_present = 1;
|
||||
total_entries = 2;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* Long file name is present, calculate how many entries are needed
|
||||
to represent it. */
|
||||
if (i % 13 == 0)
|
||||
{
|
||||
/* Exact fit, just add one for the 8.3 short name. */
|
||||
total_entries = i / 13 + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Non-exact fit, add two for 8.3 short name and overlap. */
|
||||
total_entries = i / 13 + 2;
|
||||
}
|
||||
}
|
||||
|
||||
/* Determine if the search is in the root directory or in a
|
||||
sub-directory. Note: the directory search function clears the
|
||||
first character of the name for the root directory. */
|
||||
if (directory_ptr -> fx_dir_entry_name[0])
|
||||
{
|
||||
|
||||
/* Search for a free entry in a sub-directory. */
|
||||
|
||||
/* Pickup the number of entries in this directory. This was placed
|
||||
into the unused file size field. */
|
||||
directory_entries = (ULONG)directory_ptr -> fx_dir_entry_file_size;
|
||||
|
||||
/* Point the search directory pointer to this entry. */
|
||||
search_dir_ptr = directory_ptr;
|
||||
|
||||
/* Ensure that the search directory's last search cluster is cleared. */
|
||||
search_dir_ptr -> fx_dir_entry_last_search_cluster = 0;
|
||||
|
||||
/* Set the initial index to 2, since the first two directory entries are
|
||||
always allocated. */
|
||||
directory_index = 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* Find a free entry in the root directory. */
|
||||
|
||||
/* Setup the number of directory entries. */
|
||||
directory_entries = (ULONG)media_ptr -> fx_media_root_directory_entries;
|
||||
|
||||
/* Set the search pointer to NULL since we are working off of the
|
||||
root directory. */
|
||||
search_dir_ptr = FX_NULL;
|
||||
|
||||
/* Set the initial index to 0, since the first entry of the root directory is valid. */
|
||||
directory_index = 0;
|
||||
}
|
||||
|
||||
/* Loop through entries in the search directory. Yes, this is a
|
||||
linear search! */
|
||||
free_entry_start = directory_entries;
|
||||
do
|
||||
{
|
||||
|
||||
/* Read an entry from the directory. */
|
||||
status = _fx_directory_entry_read(media_ptr, search_dir_ptr, &directory_index, entry_ptr);
|
||||
|
||||
/* Check for error status. */
|
||||
if (status != FX_SUCCESS)
|
||||
{
|
||||
return(status);
|
||||
}
|
||||
|
||||
/* Determine if this is an empty entry. */
|
||||
if ((((UCHAR)entry_ptr -> fx_dir_entry_name[0] == (UCHAR)FX_DIR_ENTRY_FREE) && (entry_ptr -> fx_dir_entry_short_name[0] == 0)) ||
|
||||
((UCHAR)entry_ptr -> fx_dir_entry_name[0] == (UCHAR)FX_DIR_ENTRY_DONE))
|
||||
{
|
||||
|
||||
/* Determine how many entries are needed. */
|
||||
if (total_entries > 1)
|
||||
{
|
||||
|
||||
/* Multiple entries are needed for long file names. Mark this
|
||||
entry as free. */
|
||||
if (entry_ptr -> fx_dir_entry_name[0] == FX_DIR_ENTRY_DONE)
|
||||
{
|
||||
|
||||
entry_ptr -> fx_dir_entry_long_name_present = 0;
|
||||
entry_ptr -> fx_dir_entry_name[0] = (CHAR)FX_DIR_ENTRY_FREE;
|
||||
entry_ptr -> fx_dir_entry_name[1] = (CHAR)0;
|
||||
|
||||
/* Write out the directory entry. */
|
||||
status = _fx_directory_entry_write(media_ptr, entry_ptr);
|
||||
if(status != FX_SUCCESS)
|
||||
{
|
||||
return(status);
|
||||
}
|
||||
|
||||
/* Note that for long names we need to avoid holes in the middle,
|
||||
i.e. entries must be logically contiguous. */
|
||||
}
|
||||
}
|
||||
|
||||
/* Determine if we are at the first free entry. */
|
||||
if (free_entry_start == directory_entries)
|
||||
{
|
||||
|
||||
/* Remember the start of the free entry. */
|
||||
free_entry_start = directory_index;
|
||||
entry_sector = (ULONG)entry_ptr -> fx_dir_entry_log_sector;
|
||||
entry_offset = entry_ptr -> fx_dir_entry_byte_offset;
|
||||
}
|
||||
|
||||
/* Determine if there are enough free entries to satisfy the request. */
|
||||
if ((directory_index - free_entry_start + 1) >= total_entries)
|
||||
{
|
||||
|
||||
/* Found an empty slot. Most pertinent information is already
|
||||
in the entry structure. */
|
||||
|
||||
/* Setup the the sector and the offset. */
|
||||
entry_ptr -> fx_dir_entry_log_sector = entry_sector;
|
||||
entry_ptr -> fx_dir_entry_byte_offset = entry_offset;
|
||||
|
||||
/* Initialize the additional directory entries. */
|
||||
entry_ptr -> fx_dir_entry_reserved = 0;
|
||||
entry_ptr -> fx_dir_entry_created_time_ms = 0;
|
||||
|
||||
/* Lockout interrupts for time/date access. */
|
||||
FX_DISABLE_INTS
|
||||
|
||||
entry_ptr -> fx_dir_entry_created_time = _fx_system_time;
|
||||
entry_ptr -> fx_dir_entry_created_date = _fx_system_date;
|
||||
entry_ptr -> fx_dir_entry_last_accessed_date = _fx_system_date;
|
||||
|
||||
/* Restore interrupts. */
|
||||
FX_RESTORE_INTS
|
||||
|
||||
/* Determine if a long file name is present. */
|
||||
if (total_entries == 1)
|
||||
{
|
||||
entry_ptr -> fx_dir_entry_long_name_present = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
entry_ptr -> fx_dir_entry_long_name_present = 1;
|
||||
}
|
||||
|
||||
/* Return a successful completion. */
|
||||
return(FX_SUCCESS);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* Reset the free entry start. */
|
||||
free_entry_start = directory_entries;
|
||||
}
|
||||
|
||||
/* Move to the next entry. */
|
||||
directory_index++;
|
||||
|
||||
/* Determine if we have exceeded the number of entries in the current directory. */
|
||||
if (directory_index >= directory_entries)
|
||||
{
|
||||
|
||||
/* Calculate how many sectors we need for the new directory entry. */
|
||||
sectors = ((total_entries * FX_DIR_ENTRY_SIZE) + (media_ptr -> fx_media_bytes_per_sector - 1))/
|
||||
media_ptr -> fx_media_bytes_per_sector;
|
||||
|
||||
/* Now calculate how many clusters we need for the new directory entry. */
|
||||
clusters_needed = (sectors + (media_ptr -> fx_media_sectors_per_cluster - 1)) / media_ptr -> fx_media_sectors_per_cluster;
|
||||
|
||||
/* Not enough empty entries were found. If the specified directory is a sub-directory,
|
||||
attempt to allocate another cluster to it. */
|
||||
if (((search_dir_ptr) || (media_ptr -> fx_media_32_bit_FAT)) && (media_ptr -> fx_media_available_clusters >= clusters_needed))
|
||||
{
|
||||
|
||||
/* Search for the additional clusters we need. */
|
||||
first_new_cluster = 0;
|
||||
total_clusters = media_ptr -> fx_media_total_clusters;
|
||||
last_cluster = 0;
|
||||
FAT_index = media_ptr -> fx_media_cluster_search_start;
|
||||
clusters = clusters_needed;
|
||||
|
||||
/* Loop to find the needed clusters. */
|
||||
while (clusters)
|
||||
{
|
||||
|
||||
/* Decrease the cluster count. */
|
||||
clusters--;
|
||||
|
||||
/* Loop to find the first available cluster. */
|
||||
do
|
||||
{
|
||||
|
||||
/* Make sure we stop looking after one pass through the FAT table. */
|
||||
if (!total_clusters)
|
||||
{
|
||||
|
||||
/* 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)
|
||||
{
|
||||
|
||||
/* 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);
|
||||
|
||||
/* We found an available cluster. We now need to clear all of entries in
|
||||
each of the cluster's sectors. */
|
||||
|
||||
/* Calculate the logical sector of this cluster. */
|
||||
logical_sector = ((ULONG) media_ptr -> fx_media_data_sector_start) +
|
||||
((((ULONG) FAT_index) - FX_FAT_ENTRY_START) *
|
||||
((ULONG) media_ptr -> fx_media_sectors_per_cluster));
|
||||
|
||||
/* Pickup the number of sectors for the next directory cluster. */
|
||||
sectors = media_ptr -> fx_media_sectors_per_cluster;
|
||||
|
||||
/* Read the logical sector just for cache reasons. */
|
||||
status = _fx_utility_logical_sector_read(media_ptr, (ULONG64) logical_sector,
|
||||
media_ptr -> fx_media_memory_buffer, ((ULONG) 1), FX_DIRECTORY_SECTOR);
|
||||
|
||||
/* Check the return value. */
|
||||
if (status != FX_SUCCESS)
|
||||
{
|
||||
|
||||
/* Return the error status. */
|
||||
return(status);
|
||||
}
|
||||
|
||||
/* Clear the entire first sector of the new sub-directory cluster. */
|
||||
work_ptr = (UCHAR *)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);
|
||||
}
|
||||
|
||||
/* Write the logical sector to ensure the zeros are written. */
|
||||
status = _fx_utility_logical_sector_write(media_ptr, (ULONG64) logical_sector,
|
||||
media_ptr -> fx_media_memory_buffer, ((ULONG) 1), FX_DIRECTORY_SECTOR);
|
||||
|
||||
/* Determine if the write was successful. */
|
||||
if (status != FX_SUCCESS)
|
||||
{
|
||||
|
||||
/* Return the error code. */
|
||||
return(status);
|
||||
}
|
||||
|
||||
/* 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. */
|
||||
|
||||
/* Flush the internal logical sector cache. */
|
||||
status = _fx_utility_logical_sector_flush(media_ptr, (ULONG64) (logical_sector + 1), (ULONG64) (sectors - 1), FX_TRUE);
|
||||
|
||||
/* Determine if the flush was successful. */
|
||||
if (status != FX_SUCCESS)
|
||||
{
|
||||
|
||||
/* 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;
|
||||
media_ptr -> fx_media_driver_logical_sector = (ULONG)logical_sector + ((ULONG)sectors);
|
||||
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)
|
||||
{
|
||||
|
||||
/* Return error code. */
|
||||
return(media_ptr -> fx_media_driver_status);
|
||||
}
|
||||
|
||||
/* Decrease the number of sectors to clear. */
|
||||
sectors--;
|
||||
}
|
||||
}
|
||||
|
||||
/* Determine if we have found the first new cluster yet. */
|
||||
if (first_new_cluster == 0)
|
||||
{
|
||||
|
||||
/* Remember the first new cluster. */
|
||||
first_new_cluster = FAT_index;
|
||||
}
|
||||
|
||||
/* Check for a valid last cluster to link. */
|
||||
if (last_cluster)
|
||||
{
|
||||
|
||||
/* Normal condition - link the last cluster with the new
|
||||
found cluster. */
|
||||
status = _fx_utility_FAT_entry_write(media_ptr, last_cluster, FAT_index);
|
||||
|
||||
/* Check for a bad FAT write status. */
|
||||
if (status != FX_SUCCESS)
|
||||
{
|
||||
|
||||
/* Return the bad status. */
|
||||
return(status);
|
||||
}
|
||||
}
|
||||
|
||||
/* Otherwise, remember the new FAT index as the last. */
|
||||
last_cluster = FAT_index;
|
||||
|
||||
/* Move to the next FAT entry. */
|
||||
FAT_index = media_ptr -> fx_media_cluster_search_start;
|
||||
}
|
||||
|
||||
/* Place an end-of-file marker on the last cluster. */
|
||||
status = _fx_utility_FAT_entry_write(media_ptr, last_cluster, media_ptr -> fx_media_fat_last);
|
||||
|
||||
/* Check for a bad FAT write status. */
|
||||
if (status != FX_SUCCESS)
|
||||
{
|
||||
|
||||
/* Return the bad status. */
|
||||
return(status);
|
||||
}
|
||||
|
||||
#ifdef FX_FAULT_TOLERANT
|
||||
|
||||
/* Ensure the new FAT chain is properly written to the media. */
|
||||
|
||||
/* Flush the cached individual FAT entries */
|
||||
_fx_utility_FAT_flush(media_ptr);
|
||||
#endif
|
||||
|
||||
/* Now the new cluster needs to be linked to the sub-directory. */
|
||||
if (search_dir_ptr)
|
||||
{
|
||||
cluster = search_dir_ptr -> fx_dir_entry_cluster;
|
||||
}
|
||||
else
|
||||
{
|
||||
cluster = media_ptr -> fx_media_root_cluster_32;
|
||||
}
|
||||
|
||||
/* Initialize loop variables. */
|
||||
last_cluster = 0;
|
||||
i = 0;
|
||||
|
||||
/* Follow the link of FAT entries. */
|
||||
while (cluster < media_ptr -> fx_media_fat_reserved)
|
||||
{
|
||||
|
||||
/* Read the current cluster entry from the FAT. */
|
||||
status = _fx_utility_FAT_entry_read(media_ptr, cluster, &FAT_value);
|
||||
i++;
|
||||
|
||||
/* Check the return value. */
|
||||
if (status != FX_SUCCESS)
|
||||
{
|
||||
|
||||
/* Return the error status. */
|
||||
return(status);
|
||||
}
|
||||
|
||||
/* Determine if the FAT read was invalid. */
|
||||
if ((cluster < FX_FAT_ENTRY_START) || (cluster == FAT_value) || (i > media_ptr -> fx_media_total_clusters))
|
||||
{
|
||||
|
||||
/* Return the bad status. */
|
||||
return(FX_FAT_READ_ERROR);
|
||||
}
|
||||
|
||||
/* Save the last valid cluster. */
|
||||
last_cluster = cluster;
|
||||
|
||||
/* Setup for the next cluster. */
|
||||
cluster = FAT_value;
|
||||
}
|
||||
|
||||
/* Decrease the available clusters in the media. */
|
||||
media_ptr -> fx_media_available_clusters = media_ptr -> fx_media_available_clusters - clusters_needed;
|
||||
|
||||
/* Increase the number of directory entries. */
|
||||
directory_entries = directory_entries + ((clusters_needed * media_ptr -> fx_media_sectors_per_cluster) * media_ptr -> fx_media_bytes_per_sector) / FX_DIR_ENTRY_SIZE;
|
||||
|
||||
/* Determine if we need to reset the free entry start since we changed the
|
||||
number of directory entries. If the last entry was not free, then we
|
||||
should definitely reset the free entry start. */
|
||||
if (!(((UCHAR)entry_ptr -> fx_dir_entry_name[0] == (UCHAR) FX_DIR_ENTRY_FREE) && (entry_ptr -> fx_dir_entry_short_name[0] == 0)))
|
||||
{
|
||||
|
||||
/* Reset the free entry start to indicate we haven't found a starting free entry yet. */
|
||||
free_entry_start = directory_entries;
|
||||
}
|
||||
|
||||
/* Update the directory size field. */
|
||||
directory_ptr -> fx_dir_entry_file_size = directory_entries;
|
||||
|
||||
/* Defer the update of the FAT entry and the last cluster of the current
|
||||
directory entry until after the new cluster is initialized and written out. */
|
||||
|
||||
/* Determine if a FAT32 is present. */
|
||||
if ((media_ptr -> fx_media_32_bit_FAT) && (search_dir_ptr == FX_NULL))
|
||||
{
|
||||
|
||||
/* Change root directory entry count - FAT32 has a variable sized root directory. */
|
||||
media_ptr -> fx_media_root_directory_entries = directory_entries;
|
||||
}
|
||||
|
||||
/* At this point, link up the last cluster with the new cluster. */
|
||||
status = _fx_utility_FAT_entry_write(media_ptr, last_cluster, first_new_cluster);
|
||||
|
||||
/* Check the return value. */
|
||||
if (status != FX_SUCCESS)
|
||||
{
|
||||
|
||||
/* Return the error status. */
|
||||
return(status);
|
||||
}
|
||||
|
||||
#ifdef FX_FAULT_TOLERANT
|
||||
|
||||
/* Flush the cached individual FAT entries */
|
||||
_fx_utility_FAT_flush(media_ptr);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
} while (directory_index < directory_entries);
|
||||
|
||||
/* Return FX_NO_MORE_SPACE status to the caller. */
|
||||
return(FX_NO_MORE_SPACE);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,235 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** 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"
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _fx_directory_information_get PORTABLE C */
|
||||
/* 6.1 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function first attempts to find the specified directory name. */
|
||||
/* If found, the complete file parameters are placed in all non-NULL */
|
||||
/* return parameters. If the file name is not found, the appropriate */
|
||||
/* error code is returned to the caller. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* media_ptr Media control block pointer */
|
||||
/* directory_name Directory name pointer */
|
||||
/* attributes Pointer to attributes */
|
||||
/* size Pointer to size */
|
||||
/* year Pointer to year */
|
||||
/* month Pointer to month */
|
||||
/* day Pointer to day */
|
||||
/* hour Pointer to hour */
|
||||
/* minute Pointer to minute */
|
||||
/* second Pointer to second */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* return status */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* _fx_directory_search Search for the file name in */
|
||||
/* the directory structure */
|
||||
/* */
|
||||
/* 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), verified */
|
||||
/* memcpy usage, */
|
||||
/* resulting in version 6.1 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
UINT _fx_directory_information_get(FX_MEDIA *media_ptr, CHAR *directory_name,
|
||||
UINT *attributes, ULONG *size,
|
||||
UINT *year, UINT *month, UINT *day,
|
||||
UINT *hour, UINT *minute, UINT *second)
|
||||
{
|
||||
|
||||
UINT status;
|
||||
FX_DIR_ENTRY dir_entry;
|
||||
ULONG open_count;
|
||||
FX_FILE *search_ptr;
|
||||
|
||||
|
||||
#ifndef FX_MEDIA_STATISTICS_DISABLE
|
||||
|
||||
/* Increment the number of times this service has been called. */
|
||||
media_ptr -> fx_media_directory_information_gets++;
|
||||
#endif
|
||||
|
||||
/* Setup pointer to media name buffer. */
|
||||
dir_entry.fx_dir_entry_name = media_ptr -> fx_media_name_buffer + FX_MAX_LONG_NAME_LEN;
|
||||
|
||||
/* Clear the short name string. */
|
||||
dir_entry.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_INFORMATION_GET, media_ptr, directory_name, 0, 0, FX_TRACE_DIRECTORY_EVENTS, 0, 0)
|
||||
|
||||
/* Protect against other threads accessing the media. */
|
||||
FX_PROTECT
|
||||
|
||||
/* Search the system for the supplied directory name. */
|
||||
status = _fx_directory_search(media_ptr, directory_name, &dir_entry, FX_NULL, FX_NULL);
|
||||
|
||||
/* Determine if the search was successful. */
|
||||
if (status != FX_SUCCESS)
|
||||
{
|
||||
|
||||
/* Release media protection. */
|
||||
FX_UNPROTECT
|
||||
|
||||
/* Return the error code. */
|
||||
return(status);
|
||||
}
|
||||
|
||||
/* Check the list of open files for others open for writing. */
|
||||
open_count = media_ptr -> fx_media_opened_file_count;
|
||||
search_ptr = media_ptr -> fx_media_opened_file_list;
|
||||
while (open_count)
|
||||
{
|
||||
|
||||
/* Look at each opened file to see if the same file is opened
|
||||
for writing. */
|
||||
if ((search_ptr -> fx_file_dir_entry.fx_dir_entry_log_sector == dir_entry.fx_dir_entry_log_sector) &&
|
||||
(search_ptr -> fx_file_dir_entry.fx_dir_entry_byte_offset == dir_entry.fx_dir_entry_byte_offset) &&
|
||||
(search_ptr -> fx_file_open_mode))
|
||||
{
|
||||
|
||||
/* The file has been opened for writing by a previous call. Use the information used by
|
||||
the writer instead of what is currently on the media. */
|
||||
_fx_utility_memory_copy((UCHAR *)&search_ptr -> fx_file_dir_entry, (UCHAR *)&dir_entry, sizeof(FX_DIR_ENTRY)); /* Use case of memcpy is verified. */
|
||||
break;
|
||||
}
|
||||
|
||||
/* Adjust the pointer and decrement the search count. */
|
||||
search_ptr = search_ptr -> fx_file_opened_next;
|
||||
open_count--;
|
||||
}
|
||||
|
||||
/* Check to see if attributes are required. */
|
||||
if (attributes)
|
||||
{
|
||||
|
||||
/* Pickup the attributes. */
|
||||
*attributes = dir_entry.fx_dir_entry_attributes;
|
||||
}
|
||||
|
||||
/* Check to see if the size is required. */
|
||||
if (size)
|
||||
{
|
||||
|
||||
/* Pickup the size. */
|
||||
*size = (ULONG)dir_entry.fx_dir_entry_file_size;
|
||||
}
|
||||
|
||||
/* Check to see if the year is required. */
|
||||
if (year)
|
||||
{
|
||||
|
||||
/* Pickup the year. */
|
||||
*year = ((dir_entry.fx_dir_entry_date >> FX_YEAR_SHIFT) & FX_YEAR_MASK) +
|
||||
FX_BASE_YEAR;
|
||||
}
|
||||
|
||||
/* Check to see if the month is required. */
|
||||
if (month)
|
||||
{
|
||||
|
||||
/* Pickup the month. */
|
||||
*month = (dir_entry.fx_dir_entry_date >> FX_MONTH_SHIFT) & FX_MONTH_MASK;
|
||||
}
|
||||
|
||||
/* Check to see if the day is required. */
|
||||
if (day)
|
||||
{
|
||||
|
||||
/* Pickup the day. */
|
||||
*day = dir_entry.fx_dir_entry_date & FX_DAY_MASK;
|
||||
}
|
||||
|
||||
/* Check to see if the hour is required. */
|
||||
if (hour)
|
||||
{
|
||||
|
||||
/* Pickup the hour. */
|
||||
*hour = (dir_entry.fx_dir_entry_time >> FX_HOUR_SHIFT) & FX_HOUR_MASK;
|
||||
}
|
||||
|
||||
/* Check to see if the minute is required. */
|
||||
if (minute)
|
||||
{
|
||||
|
||||
/* Pickup the minute. */
|
||||
*minute = (dir_entry.fx_dir_entry_time >> FX_MINUTE_SHIFT) & FX_MINUTE_MASK;
|
||||
}
|
||||
|
||||
/* Check to see if the second is required. */
|
||||
if (second)
|
||||
{
|
||||
|
||||
/* Pickup the second. */
|
||||
*second = (dir_entry.fx_dir_entry_time & FX_SECOND_MASK) * 2;
|
||||
}
|
||||
|
||||
/* Release media protection. */
|
||||
FX_UNPROTECT
|
||||
|
||||
/* Directory information get is complete, return successful status. */
|
||||
return(FX_SUCCESS);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,114 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** FileX Component */
|
||||
/** */
|
||||
/** Directory */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
#define FX_SOURCE_CODE
|
||||
|
||||
|
||||
/* Include necessary system files. */
|
||||
|
||||
#include "fx_api.h"
|
||||
#include "fx_system.h"
|
||||
#include "fx_file.h"
|
||||
#include "fx_utility.h"
|
||||
#include "fx_directory.h"
|
||||
|
||||
#ifndef FX_NO_LOCAL_PATH
|
||||
FX_LOCAL_PATH_SETUP
|
||||
#endif
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _fx_directory_local_path_clear PORTABLE C */
|
||||
/* 6.1 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function clears the local default directory of the media so */
|
||||
/* any path relative operations will start using the media's global */
|
||||
/* default path again. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* media_ptr Media control block pointer */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* return status */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* 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_local_path_clear(FX_MEDIA *media_ptr)
|
||||
{
|
||||
|
||||
|
||||
#ifndef FX_MEDIA_STATISTICS_DISABLE
|
||||
|
||||
/* Increment the number of times this service has been called. */
|
||||
media_ptr -> fx_media_directory_local_path_clears++;
|
||||
#endif
|
||||
|
||||
/* 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);
|
||||
}
|
||||
|
||||
#ifdef FX_NO_LOCAL_PATH
|
||||
|
||||
/* Error, return to caller. */
|
||||
return(FX_NOT_IMPLEMENTED);
|
||||
#else
|
||||
|
||||
/* If trace is enabled, insert this event into the trace buffer. */
|
||||
FX_TRACE_IN_LINE_INSERT(FX_TRACE_DIRECTORY_LOCAL_PATH_CLEAR, media_ptr, 0, 0, 0, FX_TRACE_DIRECTORY_EVENTS, 0, 0)
|
||||
|
||||
/* Clear this thread's local path pointer. */
|
||||
_tx_thread_current_ptr -> tx_thread_filex_ptr = FX_NULL;
|
||||
|
||||
/* Local default directory clear is complete, return status. */
|
||||
return(FX_SUCCESS);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -0,0 +1,129 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** FileX Component */
|
||||
/** */
|
||||
/** Directory */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
#define FX_SOURCE_CODE
|
||||
|
||||
|
||||
/* Include necessary system files. */
|
||||
|
||||
#include "fx_api.h"
|
||||
#include "fx_system.h"
|
||||
#include "fx_file.h"
|
||||
#include "fx_utility.h"
|
||||
#include "fx_directory.h"
|
||||
|
||||
#ifndef FX_NO_LOCAL_PATH
|
||||
FX_LOCAL_PATH_SETUP
|
||||
#endif
|
||||
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _fx_directory_local_path_get PORTABLE C */
|
||||
/* 6.1.5 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function returns a pointer to the local default directory */
|
||||
/* for this thread. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* media_ptr Media control block pointer */
|
||||
/* return_path_name Return local path name */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* return status */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* 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 */
|
||||
/* 03-02-2021 William E. Lamie Modified comment(s), */
|
||||
/* resulting in version 6.1.5 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
UINT _fx_directory_local_path_get(FX_MEDIA *media_ptr, CHAR **return_path_name)
|
||||
{
|
||||
|
||||
|
||||
#ifndef FX_MEDIA_STATISTICS_DISABLE
|
||||
|
||||
/* Increment the number of times this service has been called. */
|
||||
media_ptr -> fx_media_directory_local_path_gets++;
|
||||
#endif
|
||||
|
||||
/* 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);
|
||||
}
|
||||
|
||||
#ifdef FX_NO_LOCAL_PATH
|
||||
|
||||
FX_PARAMETER_NOT_USED(return_path_name);
|
||||
|
||||
/* Error, return to caller. */
|
||||
return(FX_NOT_IMPLEMENTED);
|
||||
#else
|
||||
|
||||
/* Determine if there is a local path. */
|
||||
if (_tx_thread_current_ptr -> tx_thread_filex_ptr)
|
||||
{
|
||||
|
||||
/* Return a pointer to the current local directory path string. */
|
||||
*return_path_name = ((FX_LOCAL_PATH *)_tx_thread_current_ptr -> tx_thread_filex_ptr) -> fx_path_string;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* Just set the return value to FX_NULL to indicate there is no
|
||||
local path setup. */
|
||||
*return_path_name = FX_NULL;
|
||||
}
|
||||
|
||||
/* If trace is enabled, insert this event into the trace buffer. */
|
||||
FX_TRACE_IN_LINE_INSERT(FX_TRACE_DIRECTORY_LOCAL_PATH_GET, media_ptr, return_path_name, 0, 0, FX_TRACE_DIRECTORY_EVENTS, 0, 0)
|
||||
|
||||
/* Local default directory has been returned, return status. */
|
||||
return(FX_SUCCESS);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -0,0 +1,123 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** FileX Component */
|
||||
/** */
|
||||
/** Directory */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
#define FX_SOURCE_CODE
|
||||
|
||||
|
||||
/* Include necessary system files. */
|
||||
|
||||
#include "fx_api.h"
|
||||
#include "fx_system.h"
|
||||
#include "fx_file.h"
|
||||
#include "fx_utility.h"
|
||||
#include "fx_directory.h"
|
||||
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _fx_directory_local_path_get_copy PORTABLE C */
|
||||
/* 6.1 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function copies the local default directory for this thread */
|
||||
/* into the specified buffer. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* media_ptr Media control block pointer */
|
||||
/* return_path_name_buffer Destination buffer for name */
|
||||
/* return_path_name_buffer_size Size of buffer pointed to by */
|
||||
/* return_path_name_buffer */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* return status */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* 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), verified */
|
||||
/* memcpy usage, */
|
||||
/* resulting in version 6.1 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
UINT _fx_directory_local_path_get_copy(FX_MEDIA *media_ptr, CHAR *return_path_name_buffer, UINT return_path_name_buffer_size)
|
||||
{
|
||||
|
||||
UINT status;
|
||||
CHAR *return_path_name;
|
||||
UINT path_name_length_with_null_terminator;
|
||||
|
||||
|
||||
/* Get the pointer to the path. */
|
||||
status = _fx_directory_local_path_get(media_ptr, &return_path_name);
|
||||
if (status == FX_SUCCESS)
|
||||
{
|
||||
|
||||
/* Was a path set? */
|
||||
if (return_path_name != FX_NULL)
|
||||
{
|
||||
|
||||
/* Get the length of the path. */
|
||||
path_name_length_with_null_terminator = _fx_utility_string_length_get(return_path_name, FX_MAXIMUM_PATH) + 1;
|
||||
|
||||
/* Can it fit in the user's buffer? */
|
||||
if (path_name_length_with_null_terminator <= return_path_name_buffer_size)
|
||||
{
|
||||
|
||||
/* Copy the path name into the user's buffer. */
|
||||
_fx_utility_memory_copy((UCHAR *) return_path_name, (UCHAR *) return_path_name_buffer, path_name_length_with_null_terminator); /* Use case of memcpy is verified. */
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* Buffer is too small. Return error. */
|
||||
return(FX_BUFFER_ERROR);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* Set zero-length string. */
|
||||
return_path_name_buffer[0] = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
/* Return status. */
|
||||
return(status);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,117 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** FileX Component */
|
||||
/** */
|
||||
/** Directory */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
#define FX_SOURCE_CODE
|
||||
|
||||
|
||||
/* Include necessary system files. */
|
||||
|
||||
#include "fx_api.h"
|
||||
#include "fx_system.h"
|
||||
#include "fx_file.h"
|
||||
#include "fx_utility.h"
|
||||
#include "fx_directory.h"
|
||||
|
||||
#ifndef FX_NO_LOCAL_PATH
|
||||
FX_LOCAL_PATH_SETUP
|
||||
#endif
|
||||
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _fx_directory_local_path_restore PORTABLE C */
|
||||
/* 6.1.5 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function restores the local default directory of the media to */
|
||||
/* the previous path specified by the caller. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* media_ptr Media control block pointer */
|
||||
/* local_path_ptr Local path control block ptr */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* return status */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* 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 */
|
||||
/* 03-02-2021 William E. Lamie Modified comment(s), */
|
||||
/* resulting in version 6.1.5 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
UINT _fx_directory_local_path_restore(FX_MEDIA *media_ptr, FX_LOCAL_PATH *local_path_ptr)
|
||||
{
|
||||
|
||||
|
||||
#ifndef FX_MEDIA_STATISTICS_DISABLE
|
||||
|
||||
/* Increment the number of times this service has been called. */
|
||||
media_ptr -> fx_media_directory_local_path_restores++;
|
||||
#endif
|
||||
|
||||
/* 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);
|
||||
}
|
||||
|
||||
#ifdef FX_NO_LOCAL_PATH
|
||||
|
||||
FX_PARAMETER_NOT_USED(local_path_ptr);
|
||||
|
||||
/* Error, return to caller. */
|
||||
return(FX_NOT_IMPLEMENTED);
|
||||
#else
|
||||
|
||||
/* If trace is enabled, insert this event into the trace buffer. */
|
||||
FX_TRACE_IN_LINE_INSERT(FX_TRACE_DIRECTORY_LOCAL_PATH_RESTORE, media_ptr, local_path_ptr, 0, 0, FX_TRACE_DIRECTORY_EVENTS, 0, 0)
|
||||
|
||||
/* Setup thread control block to use this local path pointer. */
|
||||
_tx_thread_current_ptr -> tx_thread_filex_ptr = (VOID *)local_path_ptr;
|
||||
|
||||
/* Default directory restore is complete, return status. */
|
||||
return(FX_SUCCESS);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -0,0 +1,451 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** FileX Component */
|
||||
/** */
|
||||
/** Directory */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
#define FX_SOURCE_CODE
|
||||
|
||||
|
||||
/* Include necessary system files. */
|
||||
|
||||
#include "fx_api.h"
|
||||
#include "fx_system.h"
|
||||
#include "fx_file.h"
|
||||
#include "fx_utility.h"
|
||||
#include "fx_directory.h"
|
||||
|
||||
#ifndef FX_NO_LOCAL_PATH
|
||||
FX_LOCAL_PATH_SETUP
|
||||
#endif
|
||||
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _fx_directory_local_path_set PORTABLE C */
|
||||
/* 6.1.5 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function sets the local default directory of the media to the */
|
||||
/* path specified by the caller. If this path is not found, an error */
|
||||
/* code is returned. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* media_ptr Media control block pointer */
|
||||
/* local_path Local path control block ptr */
|
||||
/* new_path_name New path to set current local */
|
||||
/* working directory to */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* return status */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* _fx_directory_search Search for the directory name */
|
||||
/* in the directory structure */
|
||||
/* */
|
||||
/* 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 */
|
||||
/* 03-02-2021 William E. Lamie Modified comment(s), */
|
||||
/* resulting in version 6.1.5 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
UINT _fx_directory_local_path_set(FX_MEDIA *media_ptr, FX_LOCAL_PATH *local_path_ptr, CHAR *new_path_name)
|
||||
{
|
||||
|
||||
#ifndef FX_NO_LOCAL_PATH
|
||||
UINT status;
|
||||
CHAR *path_string_ptr;
|
||||
UINT path_string_capacity;
|
||||
FX_PATH *path_ptr;
|
||||
UINT i, j;
|
||||
#endif
|
||||
FX_DIR_ENTRY dir_entry;
|
||||
|
||||
|
||||
#ifndef FX_MEDIA_STATISTICS_DISABLE
|
||||
|
||||
/* Increment the number of times this service has been called. */
|
||||
media_ptr -> fx_media_directory_local_path_sets++;
|
||||
#endif
|
||||
|
||||
/* Setup pointer to a name buffer. */
|
||||
dir_entry.fx_dir_entry_name = media_ptr -> fx_media_name_buffer + FX_MAX_LONG_NAME_LEN;
|
||||
|
||||
/* Setup the local path name buffer pointer. */
|
||||
local_path_ptr -> fx_path_directory.fx_dir_entry_name = local_path_ptr -> fx_path_name_buffer;
|
||||
|
||||
/* Clear the short name string. */
|
||||
dir_entry.fx_dir_entry_short_name[0] = (CHAR)0;
|
||||
|
||||
/* Clear the long name string. */
|
||||
dir_entry.fx_dir_entry_name[0] = (CHAR)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);
|
||||
}
|
||||
|
||||
#ifdef FX_NO_LOCAL_PATH
|
||||
|
||||
FX_PARAMETER_NOT_USED(new_path_name);
|
||||
|
||||
/* Error, return to caller. */
|
||||
return(FX_NOT_IMPLEMENTED);
|
||||
#else
|
||||
|
||||
/* If trace is enabled, insert this event into the trace buffer. */
|
||||
FX_TRACE_IN_LINE_INSERT(FX_TRACE_DIRECTORY_LOCAL_PATH_SET, media_ptr, local_path_ptr, new_path_name, 0, FX_TRACE_DIRECTORY_EVENTS, 0, 0)
|
||||
|
||||
/* Protect against other threads accessing the media. */
|
||||
FX_PROTECT
|
||||
|
||||
/* Look for a root directory selection. */
|
||||
if ((!new_path_name) || (((new_path_name[0] == '\\') || (new_path_name[0] == '/')) && (new_path_name[1] == (CHAR)0)))
|
||||
{
|
||||
|
||||
/* Set the default local directory to the root. */
|
||||
local_path_ptr -> fx_path_directory.fx_dir_entry_name[0] = (CHAR)0;
|
||||
local_path_ptr -> fx_path_string[0] = (CHAR)0;
|
||||
local_path_ptr -> fx_path_string[FX_MAXIMUM_PATH - 2] = (CHAR)0;
|
||||
|
||||
/* Setup thread control block to use this local path pointer. */
|
||||
_tx_thread_current_ptr -> tx_thread_filex_ptr = (VOID *)local_path_ptr;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* Search the system for the supplied path and directory name. */
|
||||
status = _fx_directory_search(media_ptr, new_path_name, &dir_entry, FX_NULL, FX_NULL);
|
||||
|
||||
/* Determine if the search failed or if the entry found is not a
|
||||
directory. */
|
||||
if ((status != FX_SUCCESS) || (!(dir_entry.fx_dir_entry_attributes & FX_DIRECTORY)))
|
||||
{
|
||||
|
||||
/* Release media protection. */
|
||||
FX_UNPROTECT
|
||||
|
||||
/* Invalid Path - Return the error code. */
|
||||
return(FX_INVALID_PATH);
|
||||
}
|
||||
|
||||
/* Now update the current path string. */
|
||||
|
||||
/* Setup the path string pointer to the start of the current path. */
|
||||
path_string_ptr = &(local_path_ptr -> fx_path_string[0]);
|
||||
|
||||
/* Setup the path string's capacity. */
|
||||
path_string_capacity = FX_MAXIMUM_PATH - 1;
|
||||
|
||||
/* Determine if the new path is relative from the current path. */
|
||||
if ((new_path_name[0] != '\\') && (new_path_name[0] != '/'))
|
||||
{
|
||||
|
||||
/* Yes, a relative path was found. */
|
||||
|
||||
/* Setup the default path pointer to the local path. */
|
||||
path_ptr = local_path_ptr;
|
||||
|
||||
/* Determine if the local path is different than the current local path. */
|
||||
if (local_path_ptr != (FX_LOCAL_PATH *)_tx_thread_current_ptr -> tx_thread_filex_ptr)
|
||||
{
|
||||
|
||||
/* Yes, there is a difference. */
|
||||
|
||||
/* Should we copy from the default media path or from the previous default
|
||||
path. */
|
||||
if (_tx_thread_current_ptr -> tx_thread_filex_ptr)
|
||||
{
|
||||
|
||||
/* There is a local path so copy the relative path info from it. */
|
||||
i = 0;
|
||||
do
|
||||
{
|
||||
|
||||
/* Copy from previous local to new local path. */
|
||||
local_path_ptr -> fx_path_string[i] =
|
||||
((FX_LOCAL_PATH *)_tx_thread_current_ptr -> tx_thread_filex_ptr) -> fx_path_string[i];
|
||||
|
||||
/* Determine if we are done. */
|
||||
if (local_path_ptr -> fx_path_string[i] == 0)
|
||||
{
|
||||
|
||||
/* Are we not at the end of the string? */
|
||||
if (i < (FX_MAXIMUM_PATH - 1))
|
||||
{
|
||||
|
||||
/* Yes, break the loop. */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Move to the next character. */
|
||||
i++;
|
||||
|
||||
} while (i < FX_MAXIMUM_PATH);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* No local path, so copy the relative path information from the media
|
||||
default. */
|
||||
i = 0;
|
||||
do
|
||||
{
|
||||
|
||||
/* Copy from the media default to new local path. */
|
||||
local_path_ptr -> fx_path_string[i] =
|
||||
media_ptr -> fx_media_default_path.fx_path_string[i];
|
||||
|
||||
/* Determine if we are done. */
|
||||
if (local_path_ptr -> fx_path_string[i] == 0)
|
||||
{
|
||||
|
||||
/* Are we not at the end of the string? */
|
||||
if (i < (FX_MAXIMUM_PATH - 1))
|
||||
{
|
||||
|
||||
/* Yes, break the loop. */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Move to the next character. */
|
||||
i++;
|
||||
|
||||
} while (i < FX_MAXIMUM_PATH);
|
||||
}
|
||||
}
|
||||
|
||||
/* First, check the current path for string overflow. If this is set,
|
||||
don't attempt to update the current path with relative information.
|
||||
The path won't be valid again until a complete path is given. */
|
||||
if (path_ptr -> fx_path_string[FX_MAXIMUM_PATH - 2] == '*')
|
||||
{
|
||||
|
||||
/* Yes, don't update the string, just finish the path set processing. */
|
||||
|
||||
/* Determine if we are at the root directory. */
|
||||
if (!dir_entry.fx_dir_entry_cluster)
|
||||
{
|
||||
/* Set the current directory back to the root directory. */
|
||||
dir_entry.fx_dir_entry_name[0] = (CHAR)0;
|
||||
|
||||
/* Clear the current path string. */
|
||||
path_ptr -> fx_path_string[0] = (CHAR)0;
|
||||
|
||||
/* Clear the overflow flag in the current path string... just in
|
||||
case! */
|
||||
path_ptr -> fx_path_string[FX_MAXIMUM_PATH - 2] = (CHAR)0;
|
||||
}
|
||||
|
||||
/* Copy the new directory entry into the media control block. */
|
||||
path_ptr -> fx_path_directory = dir_entry;
|
||||
|
||||
/* Reset the local path name buffer pointer, since it was clobbered earlier. */
|
||||
local_path_ptr -> fx_path_directory.fx_dir_entry_name = local_path_ptr -> fx_path_name_buffer;
|
||||
|
||||
/* Copy the directory name entry to the local path name area. */
|
||||
for (j = 0; j < FX_MAX_LONG_NAME_LEN; j++)
|
||||
{
|
||||
|
||||
/* Copy the name buffer. */
|
||||
local_path_ptr -> fx_path_directory.fx_dir_entry_name[j] = dir_entry.fx_dir_entry_name[j];
|
||||
}
|
||||
|
||||
/* Setup thread control block to use this local path pointer. */
|
||||
_tx_thread_current_ptr -> tx_thread_filex_ptr = (VOID *)local_path_ptr;
|
||||
|
||||
/* Release media protection. */
|
||||
FX_UNPROTECT
|
||||
|
||||
/* Default directory set is complete, return status. */
|
||||
return(FX_SUCCESS);
|
||||
}
|
||||
|
||||
/* Move the current path starting pointer to the end of the current
|
||||
path string. */
|
||||
while ((path_string_capacity) && (*path_string_ptr != FX_NULL))
|
||||
{
|
||||
path_string_ptr++;
|
||||
path_string_capacity--;
|
||||
}
|
||||
|
||||
/* If room, place the \ character in the path string. */
|
||||
if (path_string_capacity)
|
||||
{
|
||||
|
||||
/* There is room, place the directory marker in the string. */
|
||||
*path_string_ptr++ = '\\';
|
||||
path_string_capacity--;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* Setup the default path pointer. */
|
||||
|
||||
/* Setup the default path pointer to the local path. */
|
||||
path_ptr = local_path_ptr;
|
||||
|
||||
/* Complete path name given. Check to see if we need to clear an
|
||||
overflow character from a previous current path string update. */
|
||||
if (path_ptr -> fx_path_string[FX_MAXIMUM_PATH - 2] == '*')
|
||||
{
|
||||
path_ptr -> fx_path_string[FX_MAXIMUM_PATH - 2] = (CHAR)0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Copy what we can into the current path. */
|
||||
while (*new_path_name)
|
||||
{
|
||||
|
||||
/* Determine if there is a ".." character sequence that specifies the
|
||||
previous path. */
|
||||
if ((*new_path_name == '.') && (*(new_path_name + 1) == '.'))
|
||||
{
|
||||
|
||||
/* Yes, a backward path is found. The current path pointer
|
||||
must be moved back to just after the previous \ character. */
|
||||
|
||||
/* Skip the current \0 that is at the end of the current path. */
|
||||
path_string_capacity = path_string_capacity + 2;
|
||||
path_string_ptr = path_string_ptr - 2;
|
||||
|
||||
while (path_string_capacity <= (FX_MAXIMUM_PATH - 1))
|
||||
{
|
||||
|
||||
/* Move the current path pointer backwards until
|
||||
a \ character is found. */
|
||||
|
||||
if ((*path_string_ptr == '\\') || (*path_string_ptr == '/'))
|
||||
{
|
||||
|
||||
/* Yes, we have successfully backed up one directory. */
|
||||
break;
|
||||
}
|
||||
|
||||
/* Backup another character. */
|
||||
path_string_capacity++;
|
||||
path_string_ptr--;
|
||||
}
|
||||
|
||||
/* Adjust the new directory pointer past the .. characters */
|
||||
new_path_name = new_path_name + 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* Normal characters that need to be copied into the current path. */
|
||||
|
||||
if (path_string_capacity)
|
||||
{
|
||||
|
||||
/* Copy character from the new path into the current path string. */
|
||||
*path_string_ptr++ = *new_path_name++;
|
||||
|
||||
path_string_capacity--;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* No more room in the current path string! */
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Determine if there is still room in the current path string. */
|
||||
if (path_string_capacity)
|
||||
{
|
||||
|
||||
/* Yes, there is still room, place a NULL character at the
|
||||
end of the path. */
|
||||
*path_string_ptr = (CHAR)FX_NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* No more room. Determine if the entire path was successfully
|
||||
copied into the current path. */
|
||||
if (*new_path_name)
|
||||
{
|
||||
|
||||
/* No, we couldn't fit the entire path. Place a "*" character
|
||||
at the end to indicate that we had overflow. Note that
|
||||
the path is kept just the the directory default get call, so
|
||||
the new default path is valid. */
|
||||
path_ptr -> fx_path_string[FX_MAXIMUM_PATH - 2] = '*';
|
||||
}
|
||||
}
|
||||
|
||||
/* Determine if we are at the root directory. */
|
||||
if (!dir_entry.fx_dir_entry_cluster)
|
||||
{
|
||||
/* Set the current directory back to the root directory. */
|
||||
dir_entry.fx_dir_entry_name[0] = (CHAR)0;
|
||||
local_path_ptr -> fx_path_name_buffer[0] = (CHAR)0;
|
||||
}
|
||||
|
||||
/* Copy the new directory entry into the media control block. */
|
||||
path_ptr -> fx_path_directory = dir_entry;
|
||||
|
||||
/* Reset the local path name buffer pointer, since it was clobbered earlier. */
|
||||
local_path_ptr -> fx_path_directory.fx_dir_entry_name = local_path_ptr -> fx_path_name_buffer;
|
||||
|
||||
/* Copy the directory name entry to the local path name area. */
|
||||
for (j = 0; j < FX_MAX_LONG_NAME_LEN; j++)
|
||||
{
|
||||
|
||||
/* Copy the name buffer. */
|
||||
local_path_ptr -> fx_path_directory.fx_dir_entry_name[j] = dir_entry.fx_dir_entry_name[j];
|
||||
}
|
||||
|
||||
/* Setup thread control block to use this local path pointer. */
|
||||
_tx_thread_current_ptr -> tx_thread_filex_ptr = (VOID *)local_path_ptr;
|
||||
}
|
||||
|
||||
/* Release media protection. */
|
||||
FX_UNPROTECT
|
||||
|
||||
/* Default directory set is complete, return status. */
|
||||
return(FX_SUCCESS);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -0,0 +1,85 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** FileX Component */
|
||||
/** */
|
||||
/** Directory */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
#define FX_SOURCE_CODE
|
||||
|
||||
|
||||
/* Include necessary system files. */
|
||||
|
||||
#include "fx_api.h"
|
||||
#include "fx_directory.h"
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _fx_directory_long_name_get PORTABLE C */
|
||||
/* 6.1 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function gets the long file name via the supplied short file */
|
||||
/* name. If there is no long file name, the short file name will be */
|
||||
/* returned. */
|
||||
/* */
|
||||
/* Note, this API is deprecated as fx_directory_long_name_get_extended */
|
||||
/* should be used. The maximum written size to long_file_name could be */
|
||||
/* FX_MAX_LONG_NAME_LEN. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* media_ptr Media control block pointer */
|
||||
/* short_file_name Pointer to short (8.3) name */
|
||||
/* long_file_name Pointer to long (max 255) name*/
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* return status */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* _fx_directory_long_name_get_extended Actual long name get service */
|
||||
/* */
|
||||
/* 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_long_name_get(FX_MEDIA *media_ptr, CHAR *short_file_name, CHAR *long_file_name)
|
||||
{
|
||||
|
||||
/* Call the extended version with maximum long name length. */
|
||||
return(_fx_directory_long_name_get_extended(media_ptr, short_file_name, long_file_name, FX_MAX_LONG_NAME_LEN));
|
||||
}
|
||||
|
||||
@@ -0,0 +1,139 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** FileX Component */
|
||||
/** */
|
||||
/** Directory */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
#define FX_SOURCE_CODE
|
||||
|
||||
|
||||
/* Include necessary system files. */
|
||||
|
||||
#include "fx_api.h"
|
||||
#include "fx_directory.h"
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _fx_directory_long_name_get_extended PORTABLE C */
|
||||
/* 6.1 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function gets the long file name via the supplied short file */
|
||||
/* name. If there is no long file name, the short file name will be */
|
||||
/* returned. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* media_ptr Media control block pointer */
|
||||
/* short_file_name Pointer to short (8.3) name */
|
||||
/* long_file_name Pointer to long (max 255) name*/
|
||||
/* long_file_name_buffer_length Buffer length for long name */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* return status */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* _fx_directory_search Search for the file name in */
|
||||
/* */
|
||||
/* 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_long_name_get_extended(FX_MEDIA *media_ptr, CHAR *short_file_name, CHAR *long_file_name, UINT long_file_name_buffer_length)
|
||||
{
|
||||
|
||||
UINT status;
|
||||
UINT i;
|
||||
FX_DIR_ENTRY dir_entry;
|
||||
|
||||
|
||||
/* Setup pointer to media name buffer. */
|
||||
dir_entry.fx_dir_entry_name = media_ptr -> fx_media_name_buffer + FX_MAX_LONG_NAME_LEN;
|
||||
|
||||
/* Clear the short name string. */
|
||||
dir_entry.fx_dir_entry_short_name[0] = 0;
|
||||
|
||||
/* If trace is enabled, insert this event into the trace buffer. */
|
||||
FX_TRACE_IN_LINE_INSERT(FX_TRACE_DIRECTORY_LONG_NAME_GET, media_ptr, short_file_name, long_file_name, 0, FX_TRACE_DIRECTORY_EVENTS, 0, 0)
|
||||
|
||||
/* Protect against other threads accessing the media. */
|
||||
FX_PROTECT
|
||||
|
||||
/* Search the system for the supplied short directory name. */
|
||||
status = _fx_directory_search(media_ptr, short_file_name, &dir_entry, FX_NULL, FX_NULL);
|
||||
|
||||
/* Determine if the search was successful. */
|
||||
if (status != FX_SUCCESS)
|
||||
{
|
||||
|
||||
/* Release media protection. */
|
||||
FX_UNPROTECT
|
||||
|
||||
/* Return the error code. */
|
||||
return(status);
|
||||
}
|
||||
|
||||
/* Copy the long name portion into the destination string. */
|
||||
i = 0;
|
||||
while ((i < (FX_MAX_LONG_NAME_LEN - 1)) && (dir_entry.fx_dir_entry_name[i]) && (i < (long_file_name_buffer_length - 1)))
|
||||
{
|
||||
|
||||
/* Copy a character of the long name into the destination name. */
|
||||
long_file_name[i] = dir_entry.fx_dir_entry_name[i];
|
||||
|
||||
/* Move to next character. */
|
||||
i++;
|
||||
}
|
||||
|
||||
/* Ensure the long file name is NULL terminated. */
|
||||
long_file_name[i] = FX_NULL;
|
||||
|
||||
/* Check if the buffer is too short for the name. */
|
||||
if ((i == (long_file_name_buffer_length - 1)) && (dir_entry.fx_dir_entry_name[i]))
|
||||
{
|
||||
|
||||
/* Buffer too short, return error. */
|
||||
status = FX_BUFFER_ERROR;
|
||||
}
|
||||
|
||||
/* Release media protection. */
|
||||
FX_UNPROTECT
|
||||
|
||||
/* Return the completion status. */
|
||||
return(status);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,161 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** 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_utility.h"
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _fx_directory_name_extract PORTABLE C */
|
||||
/* 6.1 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function extracts the file name from the supplied input */
|
||||
/* string. If there is nothing left after the extracted name, a NULL */
|
||||
/* is returned to the caller. Otherwise, if something is left, a */
|
||||
/* pointer to it is returned. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* source_ptr Source string pointer */
|
||||
/* dest_ptr Destination string pointer */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* Pointer to Next Name (if multiple directories) */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* FileX System Functions */
|
||||
/* */
|
||||
/* 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 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
CHAR *_fx_directory_name_extract(CHAR *source_ptr, CHAR *dest_ptr)
|
||||
{
|
||||
|
||||
UINT i;
|
||||
|
||||
|
||||
/* Set the destination string to NULL. */
|
||||
dest_ptr[0] = 0;
|
||||
|
||||
/* Is a backslash present? */
|
||||
if ((*source_ptr == '\\') || (*source_ptr == '/'))
|
||||
{
|
||||
|
||||
/* Advance the string pointer. */
|
||||
source_ptr++;
|
||||
}
|
||||
|
||||
/* Loop to remove any leading spaces. */
|
||||
while (*source_ptr == ' ')
|
||||
{
|
||||
|
||||
/* Position past leading space. */
|
||||
source_ptr++;
|
||||
}
|
||||
|
||||
/* Loop to extract the name. */
|
||||
i = 0;
|
||||
while (*source_ptr)
|
||||
{
|
||||
|
||||
/* If another backslash is present, break the loop. */
|
||||
if ((*source_ptr == '\\') || (*source_ptr == '/'))
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
/* Long name can be at most 255 characters, but are further limited by the
|
||||
FX_MAX_LONG_NAME_LEN define. */
|
||||
if (i == FX_MAX_LONG_NAME_LEN - 1)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
/* Store the character. */
|
||||
dest_ptr[i] = *source_ptr++;
|
||||
|
||||
/* Increment the character counter. */
|
||||
i++;
|
||||
}
|
||||
|
||||
/* NULL-terminate the string. */
|
||||
dest_ptr[i] = 0;
|
||||
|
||||
/* Determine if we can backup to the previous character. */
|
||||
if (i)
|
||||
{
|
||||
|
||||
/* Yes, we can move backwards. */
|
||||
i--;
|
||||
}
|
||||
|
||||
/* Get rid of trailing blanks in the destination string. */
|
||||
while (dest_ptr[i] == ' ')
|
||||
{
|
||||
|
||||
/* Set this entry to NULL. */
|
||||
dest_ptr[i] = 0;
|
||||
|
||||
/* Backup to the next character. Since leading spaces have been removed,
|
||||
we know that the index is always greater than 1. */
|
||||
i--;
|
||||
}
|
||||
|
||||
/* Determine if the source string is now at the end. */
|
||||
if (*source_ptr == 0)
|
||||
{
|
||||
|
||||
/* Yes, return a NULL pointer. */
|
||||
source_ptr = FX_NULL;
|
||||
}
|
||||
|
||||
/* Return the last pointer position in the source. */
|
||||
return(source_ptr);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,143 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** 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"
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _fx_directory_name_test PORTABLE C */
|
||||
/* 6.1 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function first attempts to find the specified directory name. */
|
||||
/* If found, the attributes are checked to see if the entry is a */
|
||||
/* directory. If not, the appropriate error code is returned to the */
|
||||
/* caller. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* media_ptr Media control block pointer */
|
||||
/* directory_name Directory name pointer */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* return status */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* _fx_directory_search Search for the file name in */
|
||||
/* the directory structure */
|
||||
/* */
|
||||
/* 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_name_test(FX_MEDIA *media_ptr, CHAR *directory_name)
|
||||
{
|
||||
|
||||
UINT status;
|
||||
FX_DIR_ENTRY dir_entry;
|
||||
|
||||
|
||||
#ifndef FX_MEDIA_STATISTICS_DISABLE
|
||||
|
||||
/* Increment the number of times this service has been called. */
|
||||
media_ptr -> fx_media_directory_name_tests++;
|
||||
#endif
|
||||
|
||||
/* Setup pointer to media name buffer. */
|
||||
dir_entry.fx_dir_entry_name = media_ptr -> fx_media_name_buffer + FX_MAX_LONG_NAME_LEN;
|
||||
|
||||
/* Clear the short name string. */
|
||||
dir_entry.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_NAME_TEST, media_ptr, directory_name, 0, 0, FX_TRACE_DIRECTORY_EVENTS, 0, 0)
|
||||
|
||||
/* Protect against other threads accessing the media. */
|
||||
FX_PROTECT
|
||||
|
||||
/* Search the system for the supplied directory name. */
|
||||
status = _fx_directory_search(media_ptr, directory_name, &dir_entry, FX_NULL, FX_NULL);
|
||||
|
||||
/* Determine if the search was successful. */
|
||||
if (status != FX_SUCCESS)
|
||||
{
|
||||
|
||||
/* Release media protection. */
|
||||
FX_UNPROTECT
|
||||
|
||||
/* Return the error code. */
|
||||
return(status);
|
||||
}
|
||||
|
||||
/* Check to see if the entry is a directory. */
|
||||
if (!(dir_entry.fx_dir_entry_attributes & (UCHAR)FX_DIRECTORY))
|
||||
{
|
||||
|
||||
/* Release media protection. */
|
||||
FX_UNPROTECT
|
||||
|
||||
/* Return the not a directory error code. */
|
||||
return(FX_NOT_DIRECTORY);
|
||||
}
|
||||
|
||||
/* Release media protection. */
|
||||
FX_UNPROTECT
|
||||
|
||||
/* Directory name test is complete, return successful status. */
|
||||
return(FX_SUCCESS);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,437 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** 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_utility.h"
|
||||
|
||||
#ifndef FX_NO_LOCAL_PATH
|
||||
FX_LOCAL_PATH_SETUP
|
||||
#endif
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _fx_directory_next_entry_find PORTABLE C */
|
||||
/* 6.1 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function returns the name of the next entry in the current */
|
||||
/* working directory. The function that returns the first name in the */
|
||||
/* current directory must be called prior to this function. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* media_ptr Media control block pointer */
|
||||
/* directory_name Destination for directory */
|
||||
/* name */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* return status */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* _fx_directory_entry_read Read entries from root dir */
|
||||
/* _fx_utility_FAT_entry_read Read FAT entries to calculate */
|
||||
/* the sub-directory size */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* Application Code and */
|
||||
/* FileX System Functions */
|
||||
/* */
|
||||
/* 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_next_entry_find(FX_MEDIA *media_ptr, CHAR *directory_name)
|
||||
{
|
||||
|
||||
ULONG i;
|
||||
UINT status;
|
||||
UINT temp_status;
|
||||
ULONG cluster, next_cluster = 0;
|
||||
ULONG64 directory_size;
|
||||
FX_DIR_ENTRY entry;
|
||||
FX_DIR_ENTRY *search_dir_ptr;
|
||||
FX_PATH *path_ptr;
|
||||
#ifndef FX_MEDIA_DISABLE_SEARCH_CACHE
|
||||
UINT index;
|
||||
CHAR *path_string_ptr = FX_NULL;
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef FX_MEDIA_STATISTICS_DISABLE
|
||||
|
||||
/* Increment the number of times this service has been called. */
|
||||
media_ptr -> fx_media_directory_next_entry_finds++;
|
||||
#endif
|
||||
|
||||
/* Setup pointer to media name buffer. */
|
||||
entry.fx_dir_entry_name = media_ptr -> fx_media_name_buffer + FX_MAX_LONG_NAME_LEN;
|
||||
|
||||
/* Clear the short name string. */
|
||||
entry.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_NEXT_ENTRY_FIND, media_ptr, directory_name, 0, 0, FX_TRACE_DIRECTORY_EVENTS, 0, 0)
|
||||
|
||||
/* Protect against other threads accessing the media. */
|
||||
FX_PROTECT
|
||||
|
||||
/* First check for a local path pointer stored in the thread control block. This
|
||||
is only available in ThreadX Version 4 and above. */
|
||||
|
||||
#ifndef FX_NO_LOCAL_PATH
|
||||
|
||||
if (_tx_thread_current_ptr -> tx_thread_filex_ptr)
|
||||
{
|
||||
|
||||
/* Setup the default path pointer. */
|
||||
path_ptr = (FX_PATH *)_tx_thread_current_ptr -> tx_thread_filex_ptr;
|
||||
|
||||
/* Determine if we are at the root directory. */
|
||||
if (path_ptr -> fx_path_directory.fx_dir_entry_name[0])
|
||||
{
|
||||
|
||||
/* No, we are not at the root directory. */
|
||||
|
||||
#ifndef FX_MEDIA_DISABLE_SEARCH_CACHE
|
||||
|
||||
/* Setup pointer to the path. */
|
||||
path_string_ptr = ((FX_PATH *)_tx_thread_current_ptr -> tx_thread_filex_ptr) -> fx_path_string;
|
||||
#endif
|
||||
|
||||
/* Set the internal pointer to the search directory as well. */
|
||||
search_dir_ptr = &(path_ptr -> fx_path_directory);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* The current default directory is the root so just set the
|
||||
search directory pointer to NULL. */
|
||||
search_dir_ptr = FX_NULL;
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif
|
||||
|
||||
/* Set the initial search directory to the current working
|
||||
directory - if there is one. */
|
||||
if (media_ptr -> fx_media_default_path.fx_path_directory.fx_dir_entry_name[0])
|
||||
{
|
||||
|
||||
/* Setup the path pointer to the global media path. */
|
||||
path_ptr = &media_ptr -> fx_media_default_path;
|
||||
|
||||
#ifndef FX_MEDIA_DISABLE_SEARCH_CACHE
|
||||
|
||||
/* Setup pointer to the path. */
|
||||
path_string_ptr = media_ptr -> fx_media_default_path.fx_path_string;
|
||||
#endif
|
||||
|
||||
/* Set the internal pointer to the search directory as well. */
|
||||
search_dir_ptr = &(path_ptr -> fx_path_directory);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* Setup the path pointer to the global media path. */
|
||||
path_ptr = &media_ptr -> fx_media_default_path;
|
||||
|
||||
/* The current default directory is the root so just set the
|
||||
search directory pointer to NULL. */
|
||||
search_dir_ptr = FX_NULL;
|
||||
}
|
||||
|
||||
/* Calculate the directory size. */
|
||||
if (search_dir_ptr)
|
||||
{
|
||||
/* Determine the directory size. */
|
||||
if (path_ptr -> fx_path_current_entry != 0)
|
||||
{
|
||||
|
||||
/* Pickup the previously saved directory size. */
|
||||
directory_size = search_dir_ptr -> fx_dir_entry_file_size;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* This should only be done on the first time into next directory find. */
|
||||
|
||||
/* Ensure that the search directory's last search cluster is cleared. */
|
||||
search_dir_ptr -> fx_dir_entry_last_search_cluster = 0;
|
||||
|
||||
/* Calculate the directory size by counting the allocated
|
||||
clusters for it. */
|
||||
i = 0;
|
||||
cluster = search_dir_ptr -> fx_dir_entry_cluster;
|
||||
while (cluster < media_ptr -> fx_media_fat_reserved)
|
||||
{
|
||||
|
||||
/* Increment the cluster count. */
|
||||
i++;
|
||||
|
||||
/* Read the next FAT entry. */
|
||||
status = _fx_utility_FAT_entry_read(media_ptr, cluster, &next_cluster);
|
||||
|
||||
/* Check the return status. */
|
||||
if (status != FX_SUCCESS)
|
||||
{
|
||||
|
||||
/* Release media protection. */
|
||||
FX_UNPROTECT
|
||||
|
||||
/* Return the bad status. */
|
||||
return(status);
|
||||
}
|
||||
|
||||
if ((cluster < FX_FAT_ENTRY_START) || (cluster == next_cluster) || (i > media_ptr -> fx_media_total_clusters))
|
||||
{
|
||||
|
||||
/* Release media protection. */
|
||||
FX_UNPROTECT
|
||||
|
||||
/* Return the bad status. */
|
||||
return(FX_FAT_READ_ERROR);
|
||||
}
|
||||
|
||||
cluster = next_cluster;
|
||||
}
|
||||
|
||||
/* Now we can calculate the directory size. */
|
||||
directory_size = (((ULONG64)media_ptr -> fx_media_bytes_per_sector) *
|
||||
((ULONG64)media_ptr -> fx_media_sectors_per_cluster) * i) /
|
||||
(ULONG64)FX_DIR_ENTRY_SIZE;
|
||||
|
||||
/* Save how many entries there are in the directory. */
|
||||
search_dir_ptr -> fx_dir_entry_file_size = directory_size;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* Directory size is the number of entries in the root directory. */
|
||||
directory_size = (ULONG)media_ptr -> fx_media_root_directory_entries;
|
||||
}
|
||||
|
||||
/* Preset status with an error return. */
|
||||
status = FX_NO_MORE_ENTRIES;
|
||||
|
||||
/* Determine if the current entry is inside of the directory's range. */
|
||||
while (path_ptr -> fx_path_current_entry < directory_size)
|
||||
{
|
||||
|
||||
/* Read an entry from the directory. */
|
||||
temp_status = _fx_directory_entry_read(media_ptr, search_dir_ptr,
|
||||
&(path_ptr -> fx_path_current_entry), &entry);
|
||||
|
||||
/* Check for error status. */
|
||||
if (temp_status != FX_SUCCESS)
|
||||
{
|
||||
|
||||
/* Release media protection. */
|
||||
FX_UNPROTECT
|
||||
|
||||
/* Return error status. */
|
||||
return(temp_status);
|
||||
}
|
||||
|
||||
/* Check to see if the entry has something in it. */
|
||||
if (((UCHAR)entry.fx_dir_entry_name[0] == (UCHAR)FX_DIR_ENTRY_FREE) && (entry.fx_dir_entry_short_name[0] == 0))
|
||||
{
|
||||
|
||||
/* Current entry is free, skip to next entry and continue the loop. */
|
||||
path_ptr -> fx_path_current_entry++;
|
||||
continue;
|
||||
}
|
||||
else if ((UCHAR)entry.fx_dir_entry_name[0] != (UCHAR)FX_DIR_ENTRY_DONE)
|
||||
{
|
||||
|
||||
/* A valid directory entry is present. */
|
||||
|
||||
/* Copy the name into the destination. */
|
||||
for (i = 0; entry.fx_dir_entry_name[i]; i++)
|
||||
{
|
||||
|
||||
*directory_name = entry.fx_dir_entry_name[i];
|
||||
directory_name++;
|
||||
}
|
||||
|
||||
/* Place a NULL at the end of the directory name. */
|
||||
*directory_name = (CHAR)0;
|
||||
|
||||
/* Increment the current entry for the media. */
|
||||
path_ptr -> fx_path_current_entry++;
|
||||
|
||||
#ifndef FX_MEDIA_DISABLE_SEARCH_CACHE
|
||||
{
|
||||
UINT v, j;
|
||||
|
||||
|
||||
/* If a subsequent search for the same name is done, it will find it immediately. */
|
||||
|
||||
/* Set the index of the saved name string. */
|
||||
v = 0;
|
||||
|
||||
/* First, build the full path and name. */
|
||||
if (path_string_ptr)
|
||||
{
|
||||
|
||||
/* Copy the path into the destination. */
|
||||
while ((v < (FX_MAX_LAST_NAME_LEN - 1)) && (path_string_ptr[v]))
|
||||
{
|
||||
|
||||
/* Copy one character. */
|
||||
media_ptr -> fx_media_last_found_name[v] = path_string_ptr[v];
|
||||
|
||||
/* Move to next character. */
|
||||
v++;
|
||||
}
|
||||
}
|
||||
|
||||
/* We know there is room at this point, place a directory separator character. */
|
||||
media_ptr -> fx_media_last_found_name[v++] = '/';
|
||||
|
||||
/* Now append the name to the path. */
|
||||
j = 0;
|
||||
while ((v < FX_MAX_LAST_NAME_LEN) && (entry.fx_dir_entry_name[j]))
|
||||
{
|
||||
|
||||
/* Copy one character. */
|
||||
media_ptr -> fx_media_last_found_name[v] = entry.fx_dir_entry_name[j];
|
||||
|
||||
/* Move to next character. */
|
||||
v++;
|
||||
j++;
|
||||
}
|
||||
|
||||
/* Null terminate the last name string. */
|
||||
if (v < FX_MAX_LAST_NAME_LEN)
|
||||
{
|
||||
|
||||
/* Null terminate. */
|
||||
media_ptr -> fx_media_last_found_name[v] = FX_NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* The string is too big, NULL the string so it won't be used in searching. */
|
||||
media_ptr -> fx_media_last_found_name[0] = FX_NULL;
|
||||
}
|
||||
|
||||
/* Determine if there is a search pointer. */
|
||||
if (search_dir_ptr)
|
||||
{
|
||||
|
||||
/* Yes, there is a search directory pointer so save it! */
|
||||
media_ptr -> fx_media_last_found_directory = *search_dir_ptr;
|
||||
|
||||
/* Indicate the search directory is valid. */
|
||||
media_ptr -> fx_media_last_found_directory_valid = FX_TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* Indicate the search directory is not valid. */
|
||||
media_ptr -> fx_media_last_found_directory_valid = FX_FALSE;
|
||||
}
|
||||
|
||||
/* Copy the directory entry. */
|
||||
media_ptr -> fx_media_last_found_entry = entry;
|
||||
|
||||
/* Setup the last found directory entry to point at the last found internal file name. */
|
||||
media_ptr -> fx_media_last_found_entry.fx_dir_entry_name = media_ptr -> fx_media_last_found_file_name;
|
||||
|
||||
/* Copy the actual directory name into the cached directory name. */
|
||||
for (index = 0; index < FX_MAX_LONG_NAME_LEN; index++)
|
||||
{
|
||||
|
||||
/* Copy character into the cached directory name. */
|
||||
media_ptr -> fx_media_last_found_file_name[index] = entry.fx_dir_entry_name[index];
|
||||
|
||||
/* See if we have copied the NULL termination character. */
|
||||
if (entry.fx_dir_entry_name[index] == (CHAR)FX_NULL)
|
||||
{
|
||||
|
||||
/* Check to see if we use the break to get out of the loop. */
|
||||
if (v < (FX_MAX_LONG_NAME_LEN - 1))
|
||||
{
|
||||
|
||||
/* Yes, not at the end of the string, break. */
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Set return status to success. */
|
||||
status = FX_SUCCESS;
|
||||
|
||||
/* Get out of the loop. */
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* Set the error code. */
|
||||
status = FX_NO_MORE_ENTRIES;
|
||||
|
||||
/* Get out of the loop. */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Release media protection. */
|
||||
FX_UNPROTECT
|
||||
|
||||
/* Return status to the caller. */
|
||||
return(status);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,515 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** 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_utility.h"
|
||||
|
||||
#ifndef FX_NO_LOCAL_PATH
|
||||
FX_LOCAL_PATH_SETUP
|
||||
#endif
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _fx_directory_next_full_entry_find PORTABLE C */
|
||||
/* 6.1 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function returns the name of the next entry in the current */
|
||||
/* working directory and various information about the name. The */
|
||||
/* function that returns the first name in the current directory must */
|
||||
/* be called prior to this function. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* media_ptr Media control block pointer */
|
||||
/* directory_name Destination for directory */
|
||||
/* name */
|
||||
/* attributes Destination for attributes */
|
||||
/* size Destination for size */
|
||||
/* year Destination for year */
|
||||
/* month Destination for month */
|
||||
/* day Destination for day */
|
||||
/* hour Destination for hour */
|
||||
/* minute Destination for minute */
|
||||
/* second Destination for second */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* return status */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* _fx_directory_entry_read Read entries from root dir */
|
||||
/* _fx_utility_FAT_entry_read Read FAT entries */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* Application Code and */
|
||||
/* FileX System Functions */
|
||||
/* */
|
||||
/* 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_next_full_entry_find(FX_MEDIA *media_ptr,
|
||||
CHAR *directory_name, UINT *attributes, ULONG *size,
|
||||
UINT *year, UINT *month, UINT *day, UINT *hour, UINT *minute, UINT *second)
|
||||
{
|
||||
|
||||
ULONG i;
|
||||
UINT status;
|
||||
UINT temp_status;
|
||||
ULONG cluster, next_cluster = 0;
|
||||
ULONG64 directory_size;
|
||||
FX_DIR_ENTRY entry;
|
||||
FX_DIR_ENTRY *search_dir_ptr;
|
||||
FX_PATH *path_ptr;
|
||||
#ifndef FX_MEDIA_DISABLE_SEARCH_CACHE
|
||||
UINT index;
|
||||
CHAR *path_string_ptr = FX_NULL;
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef FX_MEDIA_STATISTICS_DISABLE
|
||||
|
||||
/* Increment the number of times this service has been called. */
|
||||
media_ptr -> fx_media_directory_next_full_entry_finds++;
|
||||
#endif
|
||||
|
||||
/* Setup pointer to media name buffer. */
|
||||
entry.fx_dir_entry_name = media_ptr -> fx_media_name_buffer + FX_MAX_LONG_NAME_LEN;
|
||||
|
||||
/* Clear the short name string. */
|
||||
entry.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_NEXT_FULL_ENTRY_FIND, media_ptr, directory_name, 0, 0, FX_TRACE_DIRECTORY_EVENTS, 0, 0)
|
||||
|
||||
/* Protect against other threads accessing the media. */
|
||||
FX_PROTECT
|
||||
|
||||
/* First check for a local path pointer stored in the thread control block. This
|
||||
is only available in ThreadX Version 4 and above. */
|
||||
#ifndef FX_NO_LOCAL_PATH
|
||||
if (_tx_thread_current_ptr -> tx_thread_filex_ptr)
|
||||
{
|
||||
|
||||
/* Setup the default path pointer. */
|
||||
path_ptr = (FX_PATH *)_tx_thread_current_ptr -> tx_thread_filex_ptr;
|
||||
|
||||
/* Determine if we are at the root directory. */
|
||||
if (path_ptr -> fx_path_directory.fx_dir_entry_name[0])
|
||||
{
|
||||
|
||||
/* No, we are not at the root directory. */
|
||||
|
||||
#ifndef FX_MEDIA_DISABLE_SEARCH_CACHE
|
||||
|
||||
/* Setup pointer to the path. */
|
||||
path_string_ptr = ((FX_PATH *)_tx_thread_current_ptr -> tx_thread_filex_ptr) -> fx_path_string;
|
||||
#endif
|
||||
|
||||
/* Set the internal pointer to the search directory as well. */
|
||||
search_dir_ptr = &path_ptr -> fx_path_directory;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* The current default directory is the root so just set the
|
||||
search directory pointer to NULL. */
|
||||
search_dir_ptr = FX_NULL;
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif
|
||||
|
||||
/* Set the initial search directory to the current working
|
||||
directory - if there is one. */
|
||||
if (media_ptr -> fx_media_default_path.fx_path_directory.fx_dir_entry_name[0])
|
||||
{
|
||||
|
||||
/* Setup the path pointer to the global media path. */
|
||||
path_ptr = &media_ptr -> fx_media_default_path;
|
||||
|
||||
#ifndef FX_MEDIA_DISABLE_SEARCH_CACHE
|
||||
|
||||
/* Setup pointer to the path. */
|
||||
path_string_ptr = media_ptr -> fx_media_default_path.fx_path_string;
|
||||
#endif
|
||||
|
||||
/* Set the internal pointer to the search directory as well. */
|
||||
search_dir_ptr = &path_ptr -> fx_path_directory;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* Setup the path pointer to the global media path. */
|
||||
path_ptr = &media_ptr -> fx_media_default_path;
|
||||
|
||||
/* The current default directory is the root so just set the
|
||||
search directory pointer to NULL. */
|
||||
search_dir_ptr = FX_NULL;
|
||||
}
|
||||
|
||||
/* Calculate the directory size. */
|
||||
if (search_dir_ptr)
|
||||
{
|
||||
|
||||
|
||||
/* Determine the directory size. */
|
||||
if (path_ptr -> fx_path_current_entry != 0)
|
||||
{
|
||||
|
||||
/* Pickup the previously saved directory size. */
|
||||
directory_size = search_dir_ptr -> fx_dir_entry_file_size;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* This should only be done on the first time into next directory find. */
|
||||
|
||||
/* Ensure that the search directory's last search cluster is cleared. */
|
||||
search_dir_ptr -> fx_dir_entry_last_search_cluster = 0;
|
||||
|
||||
/* Calculate the directory size by counting the allocated
|
||||
clusters for it. */
|
||||
i = 0;
|
||||
cluster = search_dir_ptr -> fx_dir_entry_cluster;
|
||||
while (cluster < media_ptr -> fx_media_fat_reserved)
|
||||
{
|
||||
|
||||
/* Increment the cluster count. */
|
||||
i++;
|
||||
|
||||
/* Read the next FAT entry. */
|
||||
status = _fx_utility_FAT_entry_read(media_ptr, cluster, &next_cluster);
|
||||
|
||||
|
||||
/* Check the return status. */
|
||||
if (status != FX_SUCCESS)
|
||||
{
|
||||
|
||||
/* Release media protection. */
|
||||
FX_UNPROTECT
|
||||
|
||||
/* Return the bad status. */
|
||||
return(status);
|
||||
}
|
||||
|
||||
if ((cluster < FX_FAT_ENTRY_START) || (cluster == next_cluster) || (i > media_ptr -> fx_media_total_clusters))
|
||||
{
|
||||
|
||||
/* Release media protection. */
|
||||
FX_UNPROTECT
|
||||
|
||||
/* Return the bad status. */
|
||||
return(FX_FAT_READ_ERROR);
|
||||
}
|
||||
|
||||
cluster = next_cluster;
|
||||
}
|
||||
|
||||
/* Now we can calculate the directory size. */
|
||||
directory_size = (((ULONG64) media_ptr -> fx_media_bytes_per_sector) *
|
||||
((ULONG64) media_ptr -> fx_media_sectors_per_cluster) * i)
|
||||
/ (ULONG64) FX_DIR_ENTRY_SIZE;
|
||||
|
||||
/* Save how many entries there are in the directory. */
|
||||
search_dir_ptr -> fx_dir_entry_file_size = directory_size;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* Directory size is the number of entries in the root directory. */
|
||||
directory_size = (ULONG)media_ptr -> fx_media_root_directory_entries;
|
||||
}
|
||||
|
||||
/* Preset status with an error return. */
|
||||
status = FX_NO_MORE_ENTRIES;
|
||||
|
||||
/* Determine if the current entry is inside of the directory's range. */
|
||||
while (path_ptr -> fx_path_current_entry < directory_size)
|
||||
{
|
||||
|
||||
/* Read an entry from the directory. */
|
||||
temp_status = _fx_directory_entry_read(media_ptr, search_dir_ptr,
|
||||
&(path_ptr -> fx_path_current_entry), &entry);
|
||||
|
||||
/* Check for error status. */
|
||||
if (temp_status != FX_SUCCESS)
|
||||
{
|
||||
|
||||
/* Release media protection. */
|
||||
FX_UNPROTECT
|
||||
|
||||
/* Return error status. */
|
||||
return(temp_status);
|
||||
}
|
||||
|
||||
|
||||
/* Check to see if the entry has something in it. */
|
||||
if (((UCHAR)entry.fx_dir_entry_name[0] == (UCHAR)FX_DIR_ENTRY_FREE) && (entry.fx_dir_entry_short_name[0] == 0))
|
||||
{
|
||||
|
||||
/* Current entry is free, skip to next entry and continue the loop. */
|
||||
path_ptr -> fx_path_current_entry++;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Determine if a valid directory entry is present. */
|
||||
else if ((UCHAR)entry.fx_dir_entry_name[0] != (UCHAR)FX_DIR_ENTRY_DONE)
|
||||
{
|
||||
|
||||
/* A valid directory entry is present. */
|
||||
|
||||
/* Copy the name into the destination. */
|
||||
for (i = 0; entry.fx_dir_entry_name[i]; i++)
|
||||
{
|
||||
|
||||
*directory_name = entry.fx_dir_entry_name[i];
|
||||
directory_name++;
|
||||
}
|
||||
|
||||
/* Place a NULL at the end of the directory name. */
|
||||
*directory_name = (CHAR)0;
|
||||
|
||||
/* Determine if the entry's attributes are required. */
|
||||
if (attributes)
|
||||
{
|
||||
|
||||
/* Pickup the entry's attributes. */
|
||||
*attributes = entry.fx_dir_entry_attributes;
|
||||
}
|
||||
|
||||
/* Determine if the entry's size is required. */
|
||||
if (size)
|
||||
{
|
||||
|
||||
/* Pickup the entry's size. */
|
||||
*size = (ULONG)entry.fx_dir_entry_file_size;
|
||||
}
|
||||
|
||||
/* Determine if the entry's year is required. */
|
||||
if (year)
|
||||
{
|
||||
|
||||
/* Pickup the entry's year. */
|
||||
*year = ((entry.fx_dir_entry_date >> FX_YEAR_SHIFT) & FX_YEAR_MASK) + FX_BASE_YEAR;
|
||||
}
|
||||
|
||||
/* Determine if the entry's month is required. */
|
||||
if (month)
|
||||
{
|
||||
|
||||
/* Pickup the entry's month. */
|
||||
*month = (entry.fx_dir_entry_date >> FX_MONTH_SHIFT) & FX_MONTH_MASK;
|
||||
}
|
||||
|
||||
/* Determine if the entry's day is required. */
|
||||
if (day)
|
||||
{
|
||||
|
||||
/* Pickup the entry's day. */
|
||||
*day = entry.fx_dir_entry_date & FX_DAY_MASK;
|
||||
}
|
||||
|
||||
/* Determine if the entry's hour is required. */
|
||||
if (hour)
|
||||
{
|
||||
|
||||
/* Pickup the entry's hour. */
|
||||
*hour = (entry.fx_dir_entry_time >> FX_HOUR_SHIFT) & FX_HOUR_MASK;
|
||||
}
|
||||
|
||||
/* Determine if the entry's minute is required. */
|
||||
if (minute)
|
||||
{
|
||||
|
||||
/* Pickup the entry's minute. */
|
||||
*minute = (entry.fx_dir_entry_time >> FX_MINUTE_SHIFT) & FX_MINUTE_MASK;
|
||||
}
|
||||
|
||||
/* Determine if the entry's second is required. */
|
||||
if (second)
|
||||
{
|
||||
|
||||
/* Pickup the entry's second. */
|
||||
*second = (entry.fx_dir_entry_time & FX_SECOND_MASK) * 2;
|
||||
}
|
||||
|
||||
/* Increment the current entry for the media. */
|
||||
path_ptr -> fx_path_current_entry++;
|
||||
|
||||
#ifndef FX_MEDIA_DISABLE_SEARCH_CACHE
|
||||
{
|
||||
UINT v, j;
|
||||
|
||||
|
||||
/* If a subsequent search for the same name is done, it will find it immediately. */
|
||||
|
||||
/* Set the index of the saved name string. */
|
||||
v = 0;
|
||||
|
||||
/* First, build the full path and name. */
|
||||
if (path_string_ptr)
|
||||
{
|
||||
|
||||
/* Copy the path into the destination. */
|
||||
while ((v < (FX_MAX_LAST_NAME_LEN - 1)) && (path_string_ptr[v]))
|
||||
{
|
||||
|
||||
/* Copy one character. */
|
||||
media_ptr -> fx_media_last_found_name[v] = path_string_ptr[v];
|
||||
|
||||
/* Move to next character. */
|
||||
v++;
|
||||
}
|
||||
}
|
||||
|
||||
/* We know there is room at this point, place a directory separator character. */
|
||||
media_ptr -> fx_media_last_found_name[v++] = '/';
|
||||
|
||||
/* Now append the name to the path. */
|
||||
j = 0;
|
||||
while ((v < FX_MAX_LAST_NAME_LEN) && (entry.fx_dir_entry_name[j]))
|
||||
{
|
||||
|
||||
/* Copy one character. */
|
||||
media_ptr -> fx_media_last_found_name[v] = entry.fx_dir_entry_name[j];
|
||||
|
||||
/* Move to next character. */
|
||||
v++;
|
||||
j++;
|
||||
}
|
||||
|
||||
/* Null terminate the last name string. */
|
||||
if (v < FX_MAX_LAST_NAME_LEN)
|
||||
{
|
||||
|
||||
/* Null terminate. */
|
||||
media_ptr -> fx_media_last_found_name[v] = FX_NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* The string is too big, NULL the string so it won't be used in searching. */
|
||||
media_ptr -> fx_media_last_found_name[0] = FX_NULL;
|
||||
}
|
||||
|
||||
/* Determine if there is a search pointer. */
|
||||
if (search_dir_ptr)
|
||||
{
|
||||
|
||||
/* Yes, there is a search directory pointer so save it! */
|
||||
media_ptr -> fx_media_last_found_directory = *search_dir_ptr;
|
||||
|
||||
/* Indicate the search directory is valid. */
|
||||
media_ptr -> fx_media_last_found_directory_valid = FX_TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* Indicate the search directory is not valid. */
|
||||
media_ptr -> fx_media_last_found_directory_valid = FX_FALSE;
|
||||
}
|
||||
|
||||
/* Copy the directory entry. */
|
||||
media_ptr -> fx_media_last_found_entry = entry;
|
||||
|
||||
/* Setup the last found directory entry to point at the last found internal file name. */
|
||||
media_ptr -> fx_media_last_found_entry.fx_dir_entry_name = media_ptr -> fx_media_last_found_file_name;
|
||||
|
||||
/* Copy the actual directory name into the cached directory name. */
|
||||
for (index = 0; index < FX_MAX_LONG_NAME_LEN; index++)
|
||||
{
|
||||
|
||||
/* Copy character into the cached directory name. */
|
||||
media_ptr -> fx_media_last_found_file_name[index] = entry.fx_dir_entry_name[index];
|
||||
|
||||
/* See if we have copied the NULL termination character. */
|
||||
if (entry.fx_dir_entry_name[index] == (CHAR)FX_NULL)
|
||||
{
|
||||
|
||||
/* Check to see if we use the break to get out of the loop. */
|
||||
if (v < (FX_MAX_LONG_NAME_LEN - 1))
|
||||
{
|
||||
|
||||
/* Yes, not at the end of the string, break. */
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Set return status to success. */
|
||||
status = FX_SUCCESS;
|
||||
|
||||
/* Get out of the loop. */
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Set the error code. */
|
||||
status = FX_NO_MORE_ENTRIES;
|
||||
|
||||
/* Get out of the loop. */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Release media protection. */
|
||||
FX_UNPROTECT
|
||||
|
||||
/* Return status to the caller. */
|
||||
return(status);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,486 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** 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_rename PORTABLE C */
|
||||
/* 6.1 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function first attempts to find the specified directory. */
|
||||
/* If found, the rename request is valid and the directory will be */
|
||||
/* changed to the new name. Otherwise, if the directory is not found, */
|
||||
/* the appropriate error code is returned to the caller. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* media_ptr Media control block pointer */
|
||||
/* old_directory_name Old file directory pointer */
|
||||
/* new_directory_name New file directory pointer */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* return status */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* _fx_directory_entry_write Write the new directory entry */
|
||||
/* _fx_directory_free_search Search for a free directory */
|
||||
/* entry */
|
||||
/* _fx_directory_name_extract Extract directory name */
|
||||
/* _fx_directory_search Search for the file name in */
|
||||
/* the directory structure */
|
||||
/* _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_rename(FX_MEDIA *media_ptr, CHAR *old_directory_name, CHAR *new_directory_name)
|
||||
{
|
||||
|
||||
UINT status;
|
||||
FX_DIR_ENTRY old_dir_entry;
|
||||
FX_DIR_ENTRY new_dir_entry;
|
||||
FX_DIR_ENTRY search_directory;
|
||||
CHAR *new_name_ptr;
|
||||
ULONG i;
|
||||
CHAR *work_ptr;
|
||||
CHAR alpha, beta;
|
||||
#ifdef FX_RENAME_PATH_INHERIT
|
||||
UINT j;
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef FX_MEDIA_STATISTICS_DISABLE
|
||||
|
||||
/* Increment the number of times this service has been called. */
|
||||
media_ptr -> fx_media_directory_renames++;
|
||||
#endif
|
||||
|
||||
/* Setup pointers to media name buffers. */
|
||||
old_dir_entry.fx_dir_entry_name = media_ptr -> fx_media_name_buffer + FX_MAX_LONG_NAME_LEN;
|
||||
new_dir_entry.fx_dir_entry_name = media_ptr -> fx_media_name_buffer + FX_MAX_LONG_NAME_LEN * 2;
|
||||
search_directory.fx_dir_entry_name = media_ptr -> fx_media_name_buffer + FX_MAX_LONG_NAME_LEN * 3;
|
||||
|
||||
/* Clear the short name strings. */
|
||||
old_dir_entry.fx_dir_entry_short_name[0] = 0;
|
||||
new_dir_entry.fx_dir_entry_short_name[0] = 0;
|
||||
search_directory.fx_dir_entry_short_name[0] = 0;
|
||||
|
||||
/* 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 *)new_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);
|
||||
}
|
||||
|
||||
/* 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_RENAME, media_ptr, old_directory_name, new_directory_name, 0, FX_TRACE_DIRECTORY_EVENTS, 0, 0)
|
||||
|
||||
/* Protect against other threads accessing the media. */
|
||||
FX_PROTECT
|
||||
|
||||
#ifdef FX_ENABLE_FAULT_TOLERANT
|
||||
/* Start transaction. */
|
||||
_fx_fault_tolerant_transaction_start(media_ptr);
|
||||
#endif /* FX_ENABLE_FAULT_TOLERANT */
|
||||
|
||||
/* Check for write protect at the media level (set by driver). */
|
||||
if (media_ptr -> fx_media_driver_write_protect)
|
||||
{
|
||||
|
||||
#ifdef FX_ENABLE_FAULT_TOLERANT
|
||||
FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
|
||||
#endif /* FX_ENABLE_FAULT_TOLERANT */
|
||||
|
||||
/* Release media protection. */
|
||||
FX_UNPROTECT
|
||||
|
||||
/* Return write protect error. */
|
||||
return(FX_WRITE_PROTECT);
|
||||
}
|
||||
|
||||
/* Search the system for the supplied directory name. */
|
||||
status = _fx_directory_search(media_ptr, old_directory_name, &old_dir_entry, &search_directory, FX_NULL);
|
||||
|
||||
/* 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);
|
||||
}
|
||||
|
||||
/* Check to make sure the found entry is a directory. */
|
||||
if (!(old_dir_entry.fx_dir_entry_attributes & (UCHAR)(FX_DIRECTORY)))
|
||||
{
|
||||
|
||||
#ifdef FX_ENABLE_FAULT_TOLERANT
|
||||
FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
|
||||
#endif /* FX_ENABLE_FAULT_TOLERANT */
|
||||
|
||||
/* Release media protection. */
|
||||
FX_UNPROTECT
|
||||
|
||||
/* Return the not a directory error code. */
|
||||
return(FX_NOT_DIRECTORY);
|
||||
}
|
||||
|
||||
#ifdef FX_RENAME_PATH_INHERIT
|
||||
|
||||
/* Determine if the source directory name has a path and the target directory name does not. */
|
||||
if (((old_directory_name[0] == '/') || (old_directory_name[0] == '\\')) && (new_directory_name[0] != '/') && (new_directory_name[0] != '\\'))
|
||||
{
|
||||
|
||||
/* In this case, we need to prepend the path of the old directory name to that of the new directory name. */
|
||||
|
||||
/* Setup pointer to the rename buffer. */
|
||||
work_ptr = (CHAR *)media_ptr -> fx_media_rename_buffer;
|
||||
|
||||
/* First, copy the path of the old directory name. */
|
||||
i = 0;
|
||||
j = 0;
|
||||
while ((old_directory_name[i]) && (i < FX_MAXIMUM_PATH))
|
||||
{
|
||||
|
||||
/* Copy a character into the rename buffer. */
|
||||
*work_ptr++ = old_directory_name[i];
|
||||
|
||||
/* Determine if this character is directory separator. */
|
||||
if ((old_directory_name[i] == '/') || (old_directory_name[i] == '\\'))
|
||||
{
|
||||
|
||||
/* Yes, directory separator has been found - remember the index. */
|
||||
j = i;
|
||||
}
|
||||
|
||||
/* Move to next position in the old directory name. */
|
||||
i++;
|
||||
}
|
||||
|
||||
/* At this point, we have the path stored in the rename buffer. */
|
||||
|
||||
/* Position past the last slash or backslash. */
|
||||
j++;
|
||||
|
||||
/* Reset the working pointer to the position after the last directory separator. */
|
||||
work_ptr = (CHAR *)&(media_ptr -> fx_media_rename_buffer[j]);
|
||||
|
||||
/* Now copy the new directory name into the rename buffer. */
|
||||
i = 0;
|
||||
while ((new_directory_name[i]) && (j < FX_MAXIMUM_PATH))
|
||||
{
|
||||
|
||||
/* Copy a character into the rename buffer. */
|
||||
*work_ptr++ = new_directory_name[i];
|
||||
|
||||
/* Move to next character. */
|
||||
i++;
|
||||
j++;
|
||||
}
|
||||
|
||||
/* Determine if the path was successfully prepended. */
|
||||
if (new_directory_name[i])
|
||||
{
|
||||
|
||||
/* No, there was not enough room in the destination buffer. */
|
||||
|
||||
#ifdef FX_ENABLE_FAULT_TOLERANT
|
||||
FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
|
||||
#endif /* FX_ENABLE_FAULT_TOLERANT */
|
||||
|
||||
/* Release media protection. */
|
||||
FX_UNPROTECT
|
||||
|
||||
/* Return the invalid path error code. */
|
||||
return(FX_INVALID_PATH);
|
||||
}
|
||||
|
||||
/* Place a NULL at the end of the string. */
|
||||
*work_ptr = (CHAR)FX_NULL;
|
||||
|
||||
/* At this point, we have successfully prepended the path in the new directory name, override
|
||||
the new directory name so it is used from now on. */
|
||||
new_directory_name = (CHAR *)media_ptr -> fx_media_rename_buffer;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Search the media for the new directory name - including any supplied path. */
|
||||
status = _fx_directory_search(media_ptr, new_directory_name, &new_dir_entry, &search_directory, &new_name_ptr);
|
||||
|
||||
/* Determine if the search found anything. */
|
||||
if (status == FX_SUCCESS)
|
||||
{
|
||||
|
||||
/* Determine if the new name simply has an ASCII case change. If so, simply let the processing
|
||||
continue. */
|
||||
i = 0;
|
||||
do
|
||||
{
|
||||
|
||||
/* Pickup an old name and new name character and convert to upper case if necessary. */
|
||||
alpha = old_directory_name[i];
|
||||
if ((alpha >= 'a') && (alpha <= 'z'))
|
||||
{
|
||||
|
||||
/* Lower case, convert to upper case! */
|
||||
alpha = (CHAR)((INT)alpha - 0x20);
|
||||
}
|
||||
beta = new_directory_name[i];
|
||||
if ((beta >= 'a') && (beta <= 'z'))
|
||||
{
|
||||
|
||||
/* Lower case, convert to upper case! */
|
||||
beta = (CHAR)((INT)beta - 0x20);
|
||||
}
|
||||
|
||||
/* Now compare the characters. */
|
||||
if ((alpha != beta) || (alpha == 0))
|
||||
{
|
||||
|
||||
/* Get out of this loop! */
|
||||
break;
|
||||
}
|
||||
|
||||
/* Move to next character. */
|
||||
i++;
|
||||
} while (i < (FX_MAXIMUM_PATH-1));
|
||||
|
||||
/* Now determine if the names match. */
|
||||
if (alpha != beta)
|
||||
{
|
||||
|
||||
/* Yes, the directory name already exists in the target location. */
|
||||
|
||||
#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(FX_ALREADY_CREATED);
|
||||
}
|
||||
}
|
||||
|
||||
/* Make sure the name is valid. */
|
||||
if (_fx_directory_name_extract(new_name_ptr, &new_dir_entry.fx_dir_entry_name[0]))
|
||||
{
|
||||
|
||||
#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(FX_INVALID_NAME);
|
||||
}
|
||||
|
||||
/* Look for a free slot in the target directory. */
|
||||
status = _fx_directory_free_search(media_ptr, &search_directory, &new_dir_entry);
|
||||
|
||||
/* Was a free slot found? */
|
||||
if (status != FX_SUCCESS)
|
||||
{
|
||||
|
||||
#ifdef FX_ENABLE_FAULT_TOLERANT
|
||||
FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
|
||||
#endif /* FX_ENABLE_FAULT_TOLERANT */
|
||||
|
||||
/* No, release protection. */
|
||||
FX_UNPROTECT
|
||||
|
||||
/* Return the error code. */
|
||||
return(status);
|
||||
}
|
||||
|
||||
/* Extract the new directory name. */
|
||||
_fx_directory_name_extract(new_name_ptr, &new_dir_entry.fx_dir_entry_name[0]);
|
||||
|
||||
/* Determine if the name was a long directory name. */
|
||||
if (new_dir_entry.fx_dir_entry_long_name_present)
|
||||
{
|
||||
|
||||
/* Yes, clear the short directory name to force a new one. */
|
||||
new_dir_entry.fx_dir_entry_short_name[0] = 0;
|
||||
}
|
||||
|
||||
/* Setup new attributes for the new directory entry. */
|
||||
new_dir_entry.fx_dir_entry_attributes = old_dir_entry.fx_dir_entry_attributes;
|
||||
new_dir_entry.fx_dir_entry_cluster = old_dir_entry.fx_dir_entry_cluster;
|
||||
new_dir_entry.fx_dir_entry_file_size = old_dir_entry.fx_dir_entry_file_size;
|
||||
|
||||
/* Save the reserved field. */
|
||||
new_dir_entry.fx_dir_entry_reserved = old_dir_entry.fx_dir_entry_reserved;
|
||||
|
||||
/* Set time and date stamps. */
|
||||
new_dir_entry.fx_dir_entry_created_time_ms = old_dir_entry.fx_dir_entry_created_time_ms;
|
||||
new_dir_entry.fx_dir_entry_created_time = old_dir_entry.fx_dir_entry_created_time;
|
||||
new_dir_entry.fx_dir_entry_created_date = old_dir_entry.fx_dir_entry_created_date;
|
||||
new_dir_entry.fx_dir_entry_last_accessed_date = old_dir_entry.fx_dir_entry_last_accessed_date;
|
||||
new_dir_entry.fx_dir_entry_time = old_dir_entry.fx_dir_entry_time;
|
||||
new_dir_entry.fx_dir_entry_date = old_dir_entry.fx_dir_entry_date;
|
||||
|
||||
|
||||
/* Is there a leading dot? */
|
||||
if (new_dir_entry.fx_dir_entry_name[0] == '.')
|
||||
{
|
||||
|
||||
/* Yes, toggle the hidden attribute bit. */
|
||||
new_dir_entry.fx_dir_entry_attributes |= FX_HIDDEN;
|
||||
}
|
||||
|
||||
#ifndef FX_MEDIA_DISABLE_SEARCH_CACHE
|
||||
|
||||
/* Invalidate the directory cache. */
|
||||
media_ptr -> fx_media_last_found_name[0] = FX_NULL;
|
||||
#endif
|
||||
|
||||
/* Now write out the directory entry. */
|
||||
status = _fx_directory_entry_write(media_ptr, &new_dir_entry);
|
||||
|
||||
/* 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);
|
||||
}
|
||||
|
||||
/* Set the old directory entry to free. */
|
||||
old_dir_entry.fx_dir_entry_name[0] = (CHAR)FX_DIR_ENTRY_FREE;
|
||||
old_dir_entry.fx_dir_entry_short_name[0] = (CHAR)FX_DIR_ENTRY_FREE;
|
||||
|
||||
/* Now wipe out the old directory entry. */
|
||||
status = _fx_directory_entry_write(media_ptr, &old_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 rename is complete, return status. */
|
||||
return(status);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,936 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** 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_utility.h"
|
||||
|
||||
#ifndef FX_NO_LOCAL_PATH
|
||||
FX_LOCAL_PATH_SETUP
|
||||
#endif
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _fx_directory_search PORTABLE C */
|
||||
/* 6.1.10 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function searches the media for the supplied name. The search */
|
||||
/* routine will find files as well as directory names. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* media_ptr Media control block pointer */
|
||||
/* name_ptr Name pointer */
|
||||
/* entry_ptr Pointer to directory entry */
|
||||
/* record */
|
||||
/* last_dir_ptr Pointer to destination for */
|
||||
/* the last directory entry */
|
||||
/* last_name_ptr Pointer to the last name */
|
||||
/* token that was searched for */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* return status */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* _fx_directory_name_extract Extract directory name from */
|
||||
/* input string */
|
||||
/* _fx_directory_entry_read Read entries from root dir */
|
||||
/* _fx_utility_FAT_entry_read Read FAT entries to calculate */
|
||||
/* the sub-directory size */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* FileX System Functions */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 05-19-2020 William E. Lamie Initial Version 6.0 */
|
||||
/* 09-30-2020 William E. Lamie Modified comment(s), and */
|
||||
/* added conditional to */
|
||||
/* disable media search cache, */
|
||||
/* resulting in version 6.1 */
|
||||
/* 06-02-2021 Bhupendra Naphade Modified comment(s), and */
|
||||
/* added check for */
|
||||
/* volume label, */
|
||||
/* resulting in version 6.1.7 */
|
||||
/* 01-31-2022 William E. Lamie Modified comment(s), and */
|
||||
/* fixed path compare, */
|
||||
/* resulting in version 6.1.10 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
UINT _fx_directory_search(FX_MEDIA *media_ptr, CHAR *name_ptr, FX_DIR_ENTRY *entry_ptr,
|
||||
FX_DIR_ENTRY *last_dir_ptr, CHAR **last_name_ptr)
|
||||
{
|
||||
|
||||
ULONG i, n;
|
||||
UINT found;
|
||||
UINT status;
|
||||
#ifndef FX_MEDIA_DISABLE_SEARCH_CACHE
|
||||
UINT v, j;
|
||||
#endif /* FX_MEDIA_DISABLE_SEARCH_CACHE */
|
||||
ULONG cluster, next_cluster = 0;
|
||||
ULONG64 directory_size;
|
||||
CHAR *dir_name_ptr;
|
||||
CHAR *work_ptr;
|
||||
CHAR *source_name_ptr;
|
||||
CHAR *destination_name_ptr;
|
||||
FX_DIR_ENTRY search_dir;
|
||||
FX_DIR_ENTRY *search_dir_ptr;
|
||||
CHAR *name, alpha, name_alpha;
|
||||
#ifndef FX_MEDIA_DISABLE_SEARCH_CACHE
|
||||
UINT index;
|
||||
CHAR *path_ptr = FX_NULL;
|
||||
CHAR *original_name = name_ptr;
|
||||
#endif
|
||||
|
||||
#ifndef FX_MEDIA_STATISTICS_DISABLE
|
||||
|
||||
/* Increment the number of directory search requests. */
|
||||
media_ptr -> fx_media_directory_searches++;
|
||||
#endif
|
||||
|
||||
/* Setup pointer to media name buffer. */
|
||||
name = media_ptr -> fx_media_name_buffer;
|
||||
|
||||
/* Setup the last directory, if required. */
|
||||
if (last_dir_ptr)
|
||||
{
|
||||
|
||||
/* Set the first character of the directory entry to NULL to
|
||||
indicate root or no directory. */
|
||||
last_dir_ptr -> fx_dir_entry_name[0] = 0;
|
||||
}
|
||||
|
||||
/* Determine if the file name has a full directory path. */
|
||||
if ((*name_ptr == '\\') || (*name_ptr == '/'))
|
||||
{
|
||||
|
||||
/* Directory name has full path, set the search pointer to NULL. */
|
||||
search_dir_ptr = FX_NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* Set the initial search directory to the current working
|
||||
directory - if there is one. */
|
||||
|
||||
/* First check for a local path pointer stored in the thread control block. This
|
||||
is only available in ThreadX Version 4 and above. */
|
||||
#ifndef FX_NO_LOCAL_PATH
|
||||
if (_tx_thread_current_ptr -> tx_thread_filex_ptr)
|
||||
{
|
||||
|
||||
/* Determine if the local directory is not the root directory. */
|
||||
if (((FX_PATH *)_tx_thread_current_ptr -> tx_thread_filex_ptr) -> fx_path_directory.fx_dir_entry_name[0])
|
||||
{
|
||||
|
||||
/* Start at the current working directory of the media. */
|
||||
search_dir = ((FX_PATH *)_tx_thread_current_ptr -> tx_thread_filex_ptr) -> fx_path_directory;
|
||||
|
||||
#ifndef FX_MEDIA_DISABLE_SEARCH_CACHE
|
||||
|
||||
/* Setup pointer to the path. */
|
||||
path_ptr = ((FX_PATH *)_tx_thread_current_ptr -> tx_thread_filex_ptr) -> fx_path_string;
|
||||
#endif
|
||||
|
||||
/* Set the internal pointer to the search directory as well. */
|
||||
search_dir_ptr = &search_dir;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* We are searching in the root directory. */
|
||||
search_dir_ptr = FX_NULL;
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif
|
||||
if (media_ptr -> fx_media_default_path.fx_path_directory.fx_dir_entry_name[0])
|
||||
{
|
||||
|
||||
/* Start at the current working directory of the media. */
|
||||
search_dir = media_ptr -> fx_media_default_path.fx_path_directory;
|
||||
|
||||
#ifndef FX_MEDIA_DISABLE_SEARCH_CACHE
|
||||
|
||||
/* Setup pointer to the path. */
|
||||
path_ptr = media_ptr -> fx_media_default_path.fx_path_string;
|
||||
#endif
|
||||
|
||||
/* Set the internal pointer to the search directory as well. */
|
||||
search_dir_ptr = &search_dir;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* The current default directory is the root so just set the
|
||||
search directory pointer to NULL. */
|
||||
search_dir_ptr = FX_NULL;
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef FX_MEDIA_DISABLE_SEARCH_CACHE
|
||||
|
||||
/* Determine if there is a previously found directory entry. */
|
||||
if (media_ptr -> fx_media_last_found_name[0])
|
||||
{
|
||||
|
||||
UINT match;
|
||||
CHAR *temp_ptr, beta;
|
||||
|
||||
/* Yes, there is a previously found directory in our cache. */
|
||||
|
||||
/* Initialize the index. */
|
||||
v = 0;
|
||||
|
||||
/* Determine if there is a full path. */
|
||||
if ((*name_ptr == '\\') || (*name_ptr == '/'))
|
||||
{
|
||||
|
||||
/* Yes, the full path is in the name buffer. Simply compare with what is in
|
||||
the last search buffer. */
|
||||
while ((v < (FX_MAX_LAST_NAME_LEN - 1)) && (name_ptr[v]))
|
||||
{
|
||||
|
||||
/* Pickup the respective name characters. */
|
||||
alpha = name_ptr[v];
|
||||
beta = media_ptr -> fx_media_last_found_name[v];
|
||||
|
||||
/* Ensure directory markers are the same. */
|
||||
if (alpha == '\\')
|
||||
{
|
||||
alpha = '/';
|
||||
}
|
||||
if (beta == '\\')
|
||||
{
|
||||
beta = '/';
|
||||
}
|
||||
|
||||
/* Is the name the same? */
|
||||
if (alpha != beta)
|
||||
{
|
||||
|
||||
/* Break out of loop! */
|
||||
break;
|
||||
}
|
||||
|
||||
/* Move to next character. */
|
||||
v++;
|
||||
}
|
||||
|
||||
/* Determine if we have a match. */
|
||||
if (name_ptr[v] != media_ptr -> fx_media_last_found_name[v])
|
||||
{
|
||||
match = FX_FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
match = FX_TRUE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* Default to found. */
|
||||
match = FX_TRUE;
|
||||
|
||||
/* Determine if there is a default path to compare with. */
|
||||
if (path_ptr)
|
||||
{
|
||||
|
||||
/* Yes, compare the current path with what is contained in the last
|
||||
found buffer. Note that the last found name must have at least one
|
||||
path separator as well as room for at least one character for a name. */
|
||||
while ((v < (FX_MAX_LAST_NAME_LEN - 1)) && (path_ptr[v]))
|
||||
{
|
||||
|
||||
/* Pickup the respective name characters. */
|
||||
alpha = media_ptr -> fx_media_last_found_name[v];
|
||||
beta = path_ptr[v];
|
||||
|
||||
/* Ensure directory markers are the same. */
|
||||
if (alpha == '\\')
|
||||
{
|
||||
alpha = '/';
|
||||
}
|
||||
if (beta == '\\')
|
||||
{
|
||||
beta = '/';
|
||||
}
|
||||
|
||||
/* Is the name the same? */
|
||||
if (alpha != beta)
|
||||
{
|
||||
|
||||
/* Break out of loop! */
|
||||
break;
|
||||
}
|
||||
|
||||
/* Move to next character. */
|
||||
v++;
|
||||
}
|
||||
|
||||
/* Determine if we don't have a match... The relative path must be exhausted. */
|
||||
if (path_ptr[v])
|
||||
{
|
||||
match = FX_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
/* Determine if we still have a match. */
|
||||
if (match)
|
||||
{
|
||||
|
||||
/* Now examine the rest of the last name and the newly supplied
|
||||
input name. */
|
||||
|
||||
/* Determine if a valid directory separator is present. */
|
||||
if ((media_ptr -> fx_media_last_found_name[v] != '\\') &&
|
||||
(media_ptr -> fx_media_last_found_name[v] != '/'))
|
||||
{
|
||||
|
||||
/* Set match to false - invalid directory path separator. */
|
||||
match = FX_FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Position past the next directory separator in the
|
||||
last name string. */
|
||||
v++;
|
||||
}
|
||||
|
||||
/* Yes, the full path is in the name buffer. Simply compare with what is in
|
||||
the last search buffer. */
|
||||
j = 0;
|
||||
while ((v < (FX_MAX_LAST_NAME_LEN - 1)) && (name_ptr[j]) && (match))
|
||||
{
|
||||
|
||||
/* Pickup the respective name characters. */
|
||||
alpha = name_ptr[j];
|
||||
beta = media_ptr -> fx_media_last_found_name[v];
|
||||
|
||||
/* Ensure directory markers are the same. */
|
||||
if (alpha == '\\')
|
||||
{
|
||||
alpha = '/';
|
||||
}
|
||||
if (beta == '\\')
|
||||
{
|
||||
beta = '/';
|
||||
}
|
||||
|
||||
/* Is the name the same? */
|
||||
if (alpha != beta)
|
||||
{
|
||||
|
||||
/* Break out of loop! */
|
||||
break;
|
||||
}
|
||||
|
||||
/* Move to next character. */
|
||||
v++;
|
||||
j++;
|
||||
}
|
||||
|
||||
/* Avoid accessing fx_media_last_found_name out of bounds. */
|
||||
if (v >= 256)
|
||||
{
|
||||
match = FX_FALSE;
|
||||
}
|
||||
else if ((match) && (name_ptr[j] != media_ptr -> fx_media_last_found_name[v]))
|
||||
{
|
||||
|
||||
/* We don't have a match. */
|
||||
match = FX_FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Now determine if we actually found a match. */
|
||||
if (match)
|
||||
{
|
||||
|
||||
/* Save the directory entry name pointer. */
|
||||
temp_ptr = entry_ptr -> fx_dir_entry_name;
|
||||
|
||||
/* Copy the saved directory entry. */
|
||||
*entry_ptr = media_ptr -> fx_media_last_found_entry;
|
||||
|
||||
/* Restore the directory entry name pointer. */
|
||||
entry_ptr -> fx_dir_entry_name = temp_ptr;
|
||||
|
||||
/* Copy the directory name into the destination directory name. */
|
||||
for (index = 0; index < FX_MAX_LONG_NAME_LEN; index++)
|
||||
{
|
||||
|
||||
/* Copy character into the destination. */
|
||||
temp_ptr[index] = media_ptr -> fx_media_last_found_file_name[index];
|
||||
|
||||
/* See if we have copied the NULL termination character. */
|
||||
if (temp_ptr[index] == (CHAR)FX_NULL)
|
||||
{
|
||||
|
||||
/* Determine if we should break here or at the top of the loop. */
|
||||
if (index < (FX_MAX_LONG_NAME_LEN - 1))
|
||||
{
|
||||
|
||||
/* Yes, break out of the loop early. */
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Determine if there is a search directory to copy. */
|
||||
if ((last_dir_ptr) && (media_ptr -> fx_media_last_found_directory_valid))
|
||||
{
|
||||
|
||||
/* Yes, there was a search directory... and one is requested in this request as well.
|
||||
Simply copy it into the destination. */
|
||||
|
||||
/* First, save the name pointer from the list directory pointer. */
|
||||
destination_name_ptr = last_dir_ptr -> fx_dir_entry_name;
|
||||
|
||||
/* Copy the entire directory entry structure. */
|
||||
*last_dir_ptr = media_ptr -> fx_media_last_found_directory;
|
||||
|
||||
/* Restore the original name buffer pointer. */
|
||||
last_dir_ptr -> fx_dir_entry_name = destination_name_ptr;
|
||||
|
||||
/* Pickup pointer to name to copy. */
|
||||
source_name_ptr = media_ptr -> fx_media_last_found_directory.fx_dir_entry_name;
|
||||
|
||||
/* Loop to copy the name into the last directory name buffer. */
|
||||
for (n = 0; n < FX_MAX_LONG_NAME_LEN; n++)
|
||||
{
|
||||
|
||||
/* Copy a character. */
|
||||
destination_name_ptr[n] = source_name_ptr[n];
|
||||
|
||||
/* See if we have copied the NULL termination character. */
|
||||
if (source_name_ptr[n] == (CHAR)FX_NULL)
|
||||
{
|
||||
|
||||
/* Determine if we should break here or at the top of the loop. */
|
||||
if (n < (FX_MAX_LONG_NAME_LEN - 1))
|
||||
{
|
||||
|
||||
/* Yes, break out of the loop early. */
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Return the last name pointer, if required. */
|
||||
if (last_name_ptr)
|
||||
{
|
||||
|
||||
/* Just set the last name to initial name string. */
|
||||
*last_name_ptr = temp_ptr;
|
||||
}
|
||||
|
||||
#ifndef FX_MEDIA_STATISTICS_DISABLE
|
||||
|
||||
/* Increment the number of directory search cache hits. */
|
||||
media_ptr -> fx_media_directory_search_cache_hits++;
|
||||
#endif
|
||||
|
||||
/* Return success. */
|
||||
return(FX_SUCCESS);
|
||||
}
|
||||
}
|
||||
|
||||
/* Not a sequential search, invalidate the saved information. */
|
||||
media_ptr -> fx_media_last_found_name[0] = FX_NULL;
|
||||
|
||||
#ifndef FX_MEDIA_STATISTICS_DISABLE
|
||||
|
||||
/* If trace is enabled, insert this event into the trace buffer. */
|
||||
FX_TRACE_IN_LINE_INSERT(FX_TRACE_INTERNAL_DIR_CACHE_MISS, media_ptr, media_ptr -> fx_media_directory_searches - media_ptr -> fx_media_directory_search_cache_hits, 0, 0, FX_TRACE_INTERNAL_EVENTS, 0, 0)
|
||||
#else
|
||||
|
||||
/* If trace is enabled, insert this event into the trace buffer. */
|
||||
FX_TRACE_IN_LINE_INSERT(FX_TRACE_INTERNAL_DIR_CACHE_MISS, media_ptr, 0, 0, 0, FX_TRACE_INTERNAL_EVENTS, 0, 0)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Loop to traverse the directory paths to find the specified file. */
|
||||
do
|
||||
{
|
||||
|
||||
/* Remember the last name pointer, if required. */
|
||||
if (last_name_ptr)
|
||||
{
|
||||
|
||||
/* Just set the last name to initial name string. */
|
||||
*last_name_ptr = name_ptr;
|
||||
}
|
||||
|
||||
/* Extract file name. */
|
||||
name_ptr = _fx_directory_name_extract(name_ptr, name);
|
||||
|
||||
/* Calculate the directory size. */
|
||||
if (search_dir_ptr)
|
||||
{
|
||||
|
||||
/* Ensure that the search directory's last search cluster is cleared. */
|
||||
search_dir_ptr -> fx_dir_entry_last_search_cluster = 0;
|
||||
|
||||
/* Calculate the directory size by counting the allocated
|
||||
clusters for it. */
|
||||
i = 0;
|
||||
cluster = search_dir_ptr -> fx_dir_entry_cluster;
|
||||
while (cluster < media_ptr -> fx_media_fat_reserved)
|
||||
{
|
||||
|
||||
/* Increment the cluster count. */
|
||||
i++;
|
||||
|
||||
/* Read the next FAT entry. */
|
||||
status = _fx_utility_FAT_entry_read(media_ptr, cluster, &next_cluster);
|
||||
|
||||
/* Check the return status. */
|
||||
if (status != FX_SUCCESS)
|
||||
{
|
||||
|
||||
/* Return the bad status. */
|
||||
return(status);
|
||||
}
|
||||
|
||||
/* Check for error situation. */
|
||||
if ((cluster < FX_FAT_ENTRY_START) || (cluster == next_cluster) || (i > media_ptr -> fx_media_total_clusters))
|
||||
{
|
||||
|
||||
/* Return the bad status. */
|
||||
return(FX_FAT_READ_ERROR);
|
||||
}
|
||||
|
||||
cluster = next_cluster;
|
||||
}
|
||||
|
||||
/* Now we can calculate the directory size. */
|
||||
directory_size = (((ULONG64) media_ptr -> fx_media_bytes_per_sector) *
|
||||
((ULONG64) media_ptr -> fx_media_sectors_per_cluster) * i)
|
||||
/ (ULONG64) FX_DIR_ENTRY_SIZE;
|
||||
|
||||
/* Also save this in the directory entry so we don't have to
|
||||
calculate it later. */
|
||||
search_dir_ptr -> fx_dir_entry_file_size = directory_size;
|
||||
|
||||
/* If required, copy the last search directory entry into the
|
||||
destination. */
|
||||
if (last_dir_ptr)
|
||||
{
|
||||
|
||||
/* Copy the last search directory into the destination. */
|
||||
|
||||
/* First, save the name pointer from the list directory pointer. */
|
||||
destination_name_ptr = last_dir_ptr -> fx_dir_entry_name;
|
||||
|
||||
/* Copy the entire directory entry structure. */
|
||||
*last_dir_ptr = *search_dir_ptr;
|
||||
|
||||
/* Restore the original name buffer pointer. */
|
||||
last_dir_ptr -> fx_dir_entry_name = destination_name_ptr;
|
||||
|
||||
/* Pickup pointer to name to copy. */
|
||||
source_name_ptr = search_dir_ptr -> fx_dir_entry_name;
|
||||
|
||||
/* Loop to copy the name into the last directory name buffer. */
|
||||
for (n = 0; n < FX_MAX_LONG_NAME_LEN; n++)
|
||||
{
|
||||
|
||||
/* Copy a character. */
|
||||
destination_name_ptr[n] = source_name_ptr[n];
|
||||
|
||||
/* See if we have copied the NULL termination character. */
|
||||
if (source_name_ptr[n] == (CHAR) FX_NULL)
|
||||
{
|
||||
|
||||
/* Determine if we should break here or at the top of the loop. */
|
||||
if (n < (FX_MAX_LONG_NAME_LEN - 1))
|
||||
{
|
||||
|
||||
/* Yes, break out of the loop early. */
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* Directory size is the number of entries in the root directory. */
|
||||
directory_size = (ULONG)media_ptr -> fx_media_root_directory_entries;
|
||||
}
|
||||
|
||||
/* Loop through entries in the directory. Yes, this is a
|
||||
linear search! */
|
||||
i = 0;
|
||||
found = FX_FALSE;
|
||||
|
||||
|
||||
do
|
||||
{
|
||||
|
||||
/* Read an entry from the directory. */
|
||||
status = _fx_directory_entry_read(media_ptr, search_dir_ptr, &i, entry_ptr);
|
||||
|
||||
i++;
|
||||
|
||||
/* Check for error status. */
|
||||
if (status != FX_SUCCESS)
|
||||
{
|
||||
return(status);
|
||||
}
|
||||
|
||||
/* Determine if this is the last directory entry. */
|
||||
if ((UCHAR)entry_ptr -> fx_dir_entry_name[0] == (UCHAR)FX_DIR_ENTRY_DONE)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
/* Determine if the entry is a volume label entry */
|
||||
if ((entry_ptr -> fx_dir_entry_attributes & FX_VOLUME))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Determine if this is an empty entry. */
|
||||
if (((UCHAR)entry_ptr -> fx_dir_entry_name[0] == (UCHAR)FX_DIR_ENTRY_FREE) && (entry_ptr -> fx_dir_entry_short_name[0] == 0))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Compare the input name and extension with the directory
|
||||
entry. */
|
||||
work_ptr = &name[0];
|
||||
dir_name_ptr = &(entry_ptr -> fx_dir_entry_name[0]);
|
||||
|
||||
/* Loop to compare names. */
|
||||
do
|
||||
{
|
||||
|
||||
/* Pickup character of directory name. */
|
||||
alpha = *dir_name_ptr;
|
||||
|
||||
/* Pickup character of name. */
|
||||
name_alpha = *work_ptr;
|
||||
|
||||
/* Determine if its case needs to be changed. */
|
||||
if ((alpha >= 'a') && (alpha <= 'z'))
|
||||
{
|
||||
|
||||
/* Yes, make upper case. */
|
||||
alpha = (CHAR)((INT)alpha - 0x20);
|
||||
}
|
||||
|
||||
/* Determine if its case needs to be changed. */
|
||||
if ((name_alpha >= 'a') && (name_alpha <= 'z'))
|
||||
{
|
||||
|
||||
/* Yes, make upper case. */
|
||||
name_alpha = (CHAR)((INT)name_alpha - 0x20);
|
||||
}
|
||||
|
||||
/* Compare name with directory name. */
|
||||
if (alpha != name_alpha)
|
||||
{
|
||||
|
||||
/* The names don't match, get out of the loop. */
|
||||
break;
|
||||
}
|
||||
|
||||
/* Otherwise, increment the name pointers. */
|
||||
work_ptr++;
|
||||
dir_name_ptr++;
|
||||
} while (*dir_name_ptr);
|
||||
|
||||
/* Determine if the requested name has been found. If so,
|
||||
return success to the caller. */
|
||||
if ((*dir_name_ptr == 0) && (*work_ptr == *dir_name_ptr))
|
||||
{
|
||||
|
||||
/* Yes, the name was located. All pertinent directory
|
||||
information is in the directory entry field. */
|
||||
found = FX_TRUE;
|
||||
}
|
||||
/* Determine if there is a short name to check. */
|
||||
else if (entry_ptr -> fx_dir_entry_short_name[0] != 0)
|
||||
{
|
||||
|
||||
/* Yes, check for the short part of the name. */
|
||||
|
||||
/* Compare the input name and extension with the directory entry. */
|
||||
work_ptr = &name[0];
|
||||
dir_name_ptr = &(entry_ptr -> fx_dir_entry_short_name[0]);
|
||||
|
||||
/* Loop to compare names. */
|
||||
do
|
||||
{
|
||||
|
||||
/* Pickup character of directory name. */
|
||||
alpha = *dir_name_ptr;
|
||||
|
||||
/* Pickup character of name. */
|
||||
name_alpha = *work_ptr;
|
||||
|
||||
/* Determine if its case needs to be changed. */
|
||||
if ((name_alpha >= 'a') && (name_alpha <= 'z'))
|
||||
{
|
||||
|
||||
/* Yes, make upper case. */
|
||||
name_alpha = (CHAR)((INT)name_alpha - 0x20);
|
||||
}
|
||||
|
||||
/* Compare name with directory name. */
|
||||
if (alpha != name_alpha)
|
||||
{
|
||||
|
||||
/* The names don't match, get out of the loop. */
|
||||
break;
|
||||
}
|
||||
|
||||
/* Otherwise, move the name pointers and increment the
|
||||
count. */
|
||||
work_ptr++;
|
||||
dir_name_ptr++;
|
||||
} while (*dir_name_ptr);
|
||||
|
||||
/* Determine if the names match. */
|
||||
if ((*dir_name_ptr == 0) && (*work_ptr == *dir_name_ptr))
|
||||
{
|
||||
|
||||
/* Yes, the name was located. All pertinent directory
|
||||
information is in the directory entry field. */
|
||||
found = FX_TRUE;
|
||||
}
|
||||
}
|
||||
} while ((i < directory_size) && (!found));
|
||||
|
||||
/* Now determine if we have a match. */
|
||||
if (!found)
|
||||
{
|
||||
|
||||
/* Return a "not found" status to the caller. */
|
||||
return(FX_NOT_FOUND);
|
||||
}
|
||||
|
||||
/* Determine if the found entry is indeed a sub-directory. */
|
||||
if (entry_ptr -> fx_dir_entry_attributes & FX_DIRECTORY)
|
||||
{
|
||||
|
||||
/* Move the directory search pointer to this entry. */
|
||||
search_dir = *entry_ptr;
|
||||
search_dir_ptr = &search_dir;
|
||||
|
||||
/* Ensure that the search directory's last search cluster is cleared. */
|
||||
search_dir_ptr -> fx_dir_entry_last_search_cluster = 0;
|
||||
|
||||
/* Now determine if the new search directory is the root
|
||||
directory. */
|
||||
if (!search_dir_ptr -> fx_dir_entry_cluster)
|
||||
{
|
||||
|
||||
/* This is a backward link to the root directory. Make
|
||||
sure this is indicated in the search directory
|
||||
information. */
|
||||
search_dir_ptr -> fx_dir_entry_name[0] = 0;
|
||||
|
||||
/* Determine if we need to remember this in the last
|
||||
directory searched return area. */
|
||||
if (last_dir_ptr)
|
||||
{
|
||||
|
||||
/* Yes, return this value to the caller. */
|
||||
|
||||
/* First, save the name pointer from the list directory pointer. */
|
||||
destination_name_ptr = last_dir_ptr -> fx_dir_entry_name;
|
||||
|
||||
/* Copy the entire directory entry structure. */
|
||||
*last_dir_ptr = *search_dir_ptr;
|
||||
|
||||
/* Restore the original name buffer pointer. */
|
||||
last_dir_ptr -> fx_dir_entry_name = destination_name_ptr;
|
||||
|
||||
/* Pickup pointer to name to copy. */
|
||||
source_name_ptr = search_dir_ptr -> fx_dir_entry_name;
|
||||
|
||||
/* Loop to copy the name into the last directory name buffer. */
|
||||
for (n = 0; n < FX_MAX_LONG_NAME_LEN; n++)
|
||||
{
|
||||
|
||||
/* Copy a character. */
|
||||
destination_name_ptr[n] = source_name_ptr[n];
|
||||
}
|
||||
}
|
||||
|
||||
/* Set the search directory pointer to NULL to indicate
|
||||
we are at the root directory. */
|
||||
search_dir_ptr = FX_NULL;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* This is not a directory, we better return not found
|
||||
since we can't continue the search. */
|
||||
if (name_ptr)
|
||||
{
|
||||
|
||||
/* Return not-found status to caller. */
|
||||
return(FX_NOT_FOUND);
|
||||
}
|
||||
}
|
||||
} while (name_ptr);
|
||||
|
||||
/* If you reach this point, the directory is found absolutely, since !found will return directly in the loop above. */
|
||||
#ifndef FX_MEDIA_DISABLE_SEARCH_CACHE
|
||||
|
||||
|
||||
/* At this point, cache the found information. If a subsequent search for the same name is done,
|
||||
it will return immediately. */
|
||||
|
||||
/* Set the index of the saved name string. */
|
||||
v= 0;
|
||||
|
||||
/* First, build the full path and name. */
|
||||
if ((*original_name != '\\') && (*original_name != '/') && (path_ptr))
|
||||
{
|
||||
|
||||
/* Copy the path into the destination. */
|
||||
while ((v< (FX_MAX_LAST_NAME_LEN - 1)) && (path_ptr[v]))
|
||||
{
|
||||
|
||||
/* Copy one character. */
|
||||
media_ptr -> fx_media_last_found_name[v] = path_ptr[v];
|
||||
|
||||
/* Move to next character. */
|
||||
v++;
|
||||
}
|
||||
}
|
||||
|
||||
/* Now see if there is no directory path symbol in the name itself. */
|
||||
if ((*original_name != '\\') && (*original_name != '/'))
|
||||
{
|
||||
|
||||
/* If there is room, place a directory separator character. */
|
||||
if (v < (FX_MAX_LAST_NAME_LEN - 1))
|
||||
{
|
||||
media_ptr -> fx_media_last_found_name[v++] = '/';
|
||||
}
|
||||
}
|
||||
|
||||
/* Now append the name to the path. */
|
||||
j = 0;
|
||||
while ((v < FX_MAX_LAST_NAME_LEN) && (original_name[j]))
|
||||
{
|
||||
|
||||
/* Copy one character. */
|
||||
media_ptr -> fx_media_last_found_name[v] = original_name[j];
|
||||
|
||||
/* Move to next character. */
|
||||
v++;
|
||||
j++;
|
||||
}
|
||||
|
||||
/* Null terminate the last name string. */
|
||||
if (v< FX_MAX_LAST_NAME_LEN)
|
||||
{
|
||||
|
||||
/* Null terminate. */
|
||||
media_ptr -> fx_media_last_found_name[v] = FX_NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* The string is too big, NULL the string so it won't be used in searching. */
|
||||
media_ptr -> fx_media_last_found_name[0] = FX_NULL;
|
||||
}
|
||||
|
||||
/* Determine if there is a search pointer. */
|
||||
if (search_dir_ptr)
|
||||
{
|
||||
|
||||
/* Yes, there is a search directory pointer so save it! */
|
||||
media_ptr -> fx_media_last_found_directory = *search_dir_ptr;
|
||||
|
||||
/* Indicate the search directory is valid. */
|
||||
media_ptr -> fx_media_last_found_directory_valid = FX_TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* Indicate the search directory is not valid. */
|
||||
media_ptr -> fx_media_last_found_directory_valid = FX_FALSE;
|
||||
}
|
||||
|
||||
/* Copy the directory entry. */
|
||||
media_ptr -> fx_media_last_found_entry = *entry_ptr;
|
||||
|
||||
/* Setup the directory entry for the last found internal file name. */
|
||||
media_ptr -> fx_media_last_found_entry.fx_dir_entry_name = media_ptr -> fx_media_last_found_file_name;
|
||||
|
||||
/* Copy the actual directory name into the cached directory name. */
|
||||
for (index = 0; index < FX_MAX_LONG_NAME_LEN; index++)
|
||||
{
|
||||
|
||||
/* Copy character into the cached directory name. */
|
||||
media_ptr -> fx_media_last_found_file_name[index] = entry_ptr -> fx_dir_entry_name[index];
|
||||
|
||||
/* See if we have copied the NULL termination character. */
|
||||
if (entry_ptr -> fx_dir_entry_name[index] == (CHAR)FX_NULL)
|
||||
{
|
||||
|
||||
/* Check to see if we use the break to get out of the loop. */
|
||||
if (index < (FX_MAX_LONG_NAME_LEN - 1))
|
||||
{
|
||||
|
||||
/* Yes, not at the end of the string, break. */
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return(FX_SUCCESS);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,85 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** FileX Component */
|
||||
/** */
|
||||
/** Directory */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
#define FX_SOURCE_CODE
|
||||
|
||||
|
||||
/* Include necessary system files. */
|
||||
|
||||
#include "fx_api.h"
|
||||
#include "fx_directory.h"
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _fx_directory_short_name_get PORTABLE C */
|
||||
/* 6.1 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function gets the short file name via the supplied long file */
|
||||
/* name. If the long file name is really a short file name, the short */
|
||||
/* file name will be returned. */
|
||||
/* */
|
||||
/* Note, this API is deprecated as fx_directory_short_name_get_extended*/
|
||||
/* should be used. The maximum written size to short_file_name could */
|
||||
/* be FX_MAX_SHORT_NAME_LEN. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* media_ptr Media control block pointer */
|
||||
/* long_file_name Pointer to long (max 255) name*/
|
||||
/* short_file_name Pointer to short (8.3) name */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* return status */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* _fx_directory_short_name_get_extended Actual short name get service */
|
||||
/* */
|
||||
/* 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_short_name_get(FX_MEDIA *media_ptr, CHAR *long_file_name, CHAR *short_file_name)
|
||||
{
|
||||
|
||||
/* Call the extended version with maximum short name length. */
|
||||
return(_fx_directory_short_name_get_extended(media_ptr, long_file_name, short_file_name, FX_MAX_SHORT_NAME_LEN));
|
||||
}
|
||||
|
||||
@@ -0,0 +1,170 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** FileX Component */
|
||||
/** */
|
||||
/** Directory */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
#define FX_SOURCE_CODE
|
||||
|
||||
|
||||
/* Include necessary system files. */
|
||||
|
||||
#include "fx_api.h"
|
||||
#include "fx_directory.h"
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _fx_directory_short_name_get_extended PORTABLE C */
|
||||
/* 6.1 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function gets the short file name via the supplied long file */
|
||||
/* name. If the long file name is really a short file name, the short */
|
||||
/* file name will be returned. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* media_ptr Media control block pointer */
|
||||
/* long_file_name Pointer to long (max 255) name*/
|
||||
/* short_file_name Pointer to short (8.3) name */
|
||||
/* short_file_name_length Buffer length for short name */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* return status */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* _fx_directory_search Search for the file name in */
|
||||
/* */
|
||||
/* 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_short_name_get_extended(FX_MEDIA *media_ptr, CHAR *long_file_name, CHAR *short_file_name, UINT short_file_name_length)
|
||||
{
|
||||
|
||||
UINT status;
|
||||
UINT i;
|
||||
FX_DIR_ENTRY dir_entry;
|
||||
|
||||
|
||||
/* Setup pointer to media name buffer. */
|
||||
dir_entry.fx_dir_entry_name = media_ptr -> fx_media_name_buffer + FX_MAX_LONG_NAME_LEN;
|
||||
|
||||
/* Clear the short name string. */
|
||||
dir_entry.fx_dir_entry_short_name[0] = 0;
|
||||
|
||||
/* If trace is enabled, insert this event into the trace buffer. */
|
||||
FX_TRACE_IN_LINE_INSERT(FX_TRACE_DIRECTORY_SHORT_NAME_GET, media_ptr, long_file_name, short_file_name, 0, FX_TRACE_DIRECTORY_EVENTS, 0, 0)
|
||||
|
||||
/* Protect against other threads accessing the media. */
|
||||
FX_PROTECT
|
||||
|
||||
/* Search the system for the supplied short directory name. */
|
||||
status = _fx_directory_search(media_ptr, long_file_name, &dir_entry, FX_NULL, FX_NULL);
|
||||
|
||||
/* Determine if the search was successful. */
|
||||
if (status != FX_SUCCESS)
|
||||
{
|
||||
|
||||
/* Release media protection. */
|
||||
FX_UNPROTECT
|
||||
|
||||
/* Return the error code. */
|
||||
return(status);
|
||||
}
|
||||
|
||||
/* Determine if there is a short name. */
|
||||
if (dir_entry.fx_dir_entry_short_name[0])
|
||||
{
|
||||
|
||||
/* Yes, there is a short name. Copy the short file name portion into the destination string. */
|
||||
i = 0;
|
||||
while ((i < (FX_MAX_SHORT_NAME_LEN - 1)) && (dir_entry.fx_dir_entry_short_name[i]) && (i < (short_file_name_length - 1)))
|
||||
{
|
||||
|
||||
/* Copy a character of the long file name into the destination name. */
|
||||
short_file_name[i] = dir_entry.fx_dir_entry_short_name[i];
|
||||
|
||||
/* Move to next character. */
|
||||
i++;
|
||||
}
|
||||
|
||||
/* Ensure the short file name is NULL terminated. */
|
||||
short_file_name[i] = FX_NULL;
|
||||
|
||||
/* Check if the buffer is too short for the name. */
|
||||
if ((i == (short_file_name_length - 1)) && (dir_entry.fx_dir_entry_short_name[i]))
|
||||
{
|
||||
|
||||
/* Buffer too short, return error. */
|
||||
status = FX_BUFFER_ERROR;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* There is no long file name, simply copy the long file name into the short file name destination. */
|
||||
i = 0;
|
||||
while ((i < (FX_MAX_SHORT_NAME_LEN - 1)) && (dir_entry.fx_dir_entry_name[i]) && (i < (short_file_name_length - 1)))
|
||||
{
|
||||
|
||||
/* Copy a character of the file name into the destination name. */
|
||||
short_file_name[i] = dir_entry.fx_dir_entry_name[i];
|
||||
|
||||
/* Move to next character. */
|
||||
i++;
|
||||
}
|
||||
|
||||
/* Ensure the short file name is NULL terminated. */
|
||||
short_file_name[i] = FX_NULL;
|
||||
|
||||
/* Check if the buffer is too short for the name. */
|
||||
if ((i == (short_file_name_length - 1)) && (dir_entry.fx_dir_entry_name[i]))
|
||||
{
|
||||
|
||||
/* Buffer too short, return error. */
|
||||
status = FX_BUFFER_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
/* Release media protection. */
|
||||
FX_UNPROTECT
|
||||
|
||||
/* Return the completion status. */
|
||||
return(status);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,113 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** FileX Component */
|
||||
/** */
|
||||
/** Fault Tolerant */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
#define FX_SOURCE_CODE
|
||||
|
||||
#include "fx_api.h"
|
||||
#include "fx_utility.h"
|
||||
#include "fx_fault_tolerant.h"
|
||||
|
||||
|
||||
#ifdef FX_ENABLE_FAULT_TOLERANT
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _fx_fault_tolerant_add_FAT_log PORTABLE C */
|
||||
/* 6.1 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function converts FAT write into log entry and add it into */
|
||||
/* log file. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* media_ptr Media control block pointer */
|
||||
/* cluster Cluster entry number */
|
||||
/* value Next cluster value */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* return status */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* _fx_utility_16_unsigned_write Write a USHORT from memory */
|
||||
/* _fx_utility_32_unsigned_write Write a UINT from memory */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* _fx_utility_FAT_entry_write */
|
||||
/* */
|
||||
/* 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_fault_tolerant_add_FAT_log(FX_MEDIA *media_ptr, ULONG cluster, ULONG value)
|
||||
{
|
||||
ULONG file_size;
|
||||
FX_FAULT_TOLERANT_FAT_LOG *fat_log;
|
||||
|
||||
/* Increment the size of the log file. */
|
||||
file_size = media_ptr -> fx_media_fault_tolerant_file_size + FX_FAULT_TOLERANT_FAT_LOG_ENTRY_SIZE;
|
||||
|
||||
/* Check whether log file exceeds the buffer. */
|
||||
if (file_size > media_ptr -> fx_media_fault_tolerant_memory_buffer_size)
|
||||
{
|
||||
|
||||
/* Log file exceeds the size of the log buffer. This is a failure. */
|
||||
return(FX_NO_MORE_SPACE);
|
||||
}
|
||||
|
||||
/* Set log pointer. */
|
||||
fat_log = (FX_FAULT_TOLERANT_FAT_LOG *)(media_ptr -> fx_media_fault_tolerant_memory_buffer +
|
||||
media_ptr -> fx_media_fault_tolerant_file_size);
|
||||
|
||||
/* Set log type. */
|
||||
_fx_utility_16_unsigned_write((UCHAR *)&fat_log -> fx_fault_tolerant_FAT_log_type,
|
||||
FX_FAULT_TOLERANT_FAT_LOG_TYPE);
|
||||
|
||||
/* Size of log. */
|
||||
_fx_utility_16_unsigned_write((UCHAR *)&fat_log -> fx_fault_tolerant_FAT_log_size,
|
||||
FX_FAULT_TOLERANT_FAT_LOG_ENTRY_SIZE);
|
||||
|
||||
/* Set cluster and value. */
|
||||
_fx_utility_32_unsigned_write((UCHAR *)&fat_log -> fx_fault_tolerant_FAT_log_cluster, cluster);
|
||||
_fx_utility_32_unsigned_write((UCHAR *)&fat_log -> fx_fault_tolerant_FAT_log_value, value);
|
||||
|
||||
/* Update log information. */
|
||||
media_ptr -> fx_media_fault_tolerant_file_size = (USHORT)file_size;
|
||||
media_ptr -> fx_media_fault_tolerant_total_logs += 1;
|
||||
|
||||
return(FX_SUCCESS);
|
||||
}
|
||||
#endif /* FX_ENABLE_FAULT_TOLERANT */
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** FileX Component */
|
||||
/** */
|
||||
/** Fault Tolerant */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
#define FX_SOURCE_CODE
|
||||
|
||||
#include "fx_api.h"
|
||||
#include "fx_utility.h"
|
||||
#include "fx_fault_tolerant.h"
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** FileX Component */
|
||||
/** */
|
||||
/** Fault Tolerant */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
#define FX_SOURCE_CODE
|
||||
|
||||
#include "fx_api.h"
|
||||
#include "fx_utility.h"
|
||||
#include "fx_fault_tolerant.h"
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,132 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** FileX Component */
|
||||
/** */
|
||||
/** Fault Tolerant */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
#define FX_SOURCE_CODE
|
||||
|
||||
#include "fx_api.h"
|
||||
#include "fx_utility.h"
|
||||
#include "fx_fault_tolerant.h"
|
||||
|
||||
|
||||
#ifdef FX_ENABLE_FAULT_TOLERANT
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _fx_fault_tolerant_add_dir_log PORTABLE C */
|
||||
/* 6.1 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function converts directory entry write into log entry and add */
|
||||
/* it into log file. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* media_ptr Media control block pointer */
|
||||
/* logical_sector Original sector to write to */
|
||||
/* offset Offset in original sector */
|
||||
/* data Data of log */
|
||||
/* data_size Size of data */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* return status */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* _fx_utility_16_unsigned_write Write a USHORT from memory */
|
||||
/* _fx_utility_32_unsigned_write Write a ULONG from memory */
|
||||
/* _fx_utility_64_unsigned_write Write a ULONG64 from memory */
|
||||
/* memcpy Memory Copy */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* _fx_directory_entry_write */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 05-19-2020 William E. Lamie Initial Version 6.0 */
|
||||
/* 09-30-2020 William E. Lamie Modified comment(s), verified */
|
||||
/* memcpy usage, */
|
||||
/* resulting in version 6.1 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
UINT _fx_fault_tolerant_add_dir_log(FX_MEDIA *media_ptr, ULONG64 logical_sector, ULONG offset,
|
||||
UCHAR *data, ULONG data_size)
|
||||
{
|
||||
ULONG file_size;
|
||||
FX_FAULT_TOLERANT_DIR_LOG *dir_log;
|
||||
|
||||
/* Increment the size of the log file. */
|
||||
file_size = media_ptr -> fx_media_fault_tolerant_file_size + data_size + FX_FAULT_TOLERANT_DIR_LOG_ENTRY_SIZE;
|
||||
|
||||
/* Check whether log file exceeds the buffer. */
|
||||
if (file_size > media_ptr -> fx_media_fault_tolerant_memory_buffer_size)
|
||||
{
|
||||
|
||||
/* Log file exceeds the size of the log buffer. This is a failure. */
|
||||
return(FX_NO_MORE_SPACE);
|
||||
}
|
||||
|
||||
/* Any data to write? */
|
||||
if (data_size == 0)
|
||||
{
|
||||
|
||||
/* No. Just return. */
|
||||
return FX_SUCCESS;
|
||||
}
|
||||
|
||||
/* Set log pointer. */
|
||||
dir_log = (FX_FAULT_TOLERANT_DIR_LOG *)(media_ptr -> fx_media_fault_tolerant_memory_buffer +
|
||||
media_ptr -> fx_media_fault_tolerant_file_size);
|
||||
|
||||
/* Set log type. */
|
||||
_fx_utility_16_unsigned_write((UCHAR *)&dir_log -> fx_fault_tolerant_dir_log_type,
|
||||
FX_FAULT_TOLERANT_DIR_LOG_TYPE);
|
||||
|
||||
/* Size of log. */
|
||||
_fx_utility_16_unsigned_write((UCHAR *)&dir_log -> fx_fault_tolerant_dir_log_size,
|
||||
data_size + FX_FAULT_TOLERANT_DIR_LOG_ENTRY_SIZE);
|
||||
|
||||
/* Set sector and offset. */
|
||||
_fx_utility_64_unsigned_write((UCHAR *)&dir_log -> fx_fault_tolerant_dir_log_sector, logical_sector);
|
||||
_fx_utility_32_unsigned_write((UCHAR *)&dir_log -> fx_fault_tolerant_dir_log_offset, offset);
|
||||
|
||||
memcpy(media_ptr -> fx_media_fault_tolerant_memory_buffer + /* Use case of memcpy is verified. */
|
||||
media_ptr -> fx_media_fault_tolerant_file_size + FX_FAULT_TOLERANT_DIR_LOG_ENTRY_SIZE,
|
||||
data, data_size);
|
||||
|
||||
|
||||
/* Update log information. */
|
||||
media_ptr -> fx_media_fault_tolerant_file_size = (USHORT)file_size;
|
||||
media_ptr -> fx_media_fault_tolerant_total_logs += 1;
|
||||
|
||||
return(FX_SUCCESS);
|
||||
}
|
||||
#endif /* FX_ENABLE_FAULT_TOLERANT */
|
||||
|
||||
@@ -0,0 +1,268 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** FileX Component */
|
||||
/** */
|
||||
/** Fault Tolerant */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
#define FX_SOURCE_CODE
|
||||
|
||||
#include "fx_api.h"
|
||||
#include "fx_utility.h"
|
||||
#include "fx_fault_tolerant.h"
|
||||
|
||||
|
||||
#ifdef FX_ENABLE_FAULT_TOLERANT
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _fx_fault_tolerant_apply_logs PORTABLE C */
|
||||
/* 6.2.0 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function applies changes to the file system. The changes are */
|
||||
/* already recorded in the fault tolerant log file. Therefore this */
|
||||
/* function reads the content of the log entries and apply these */
|
||||
/* changes to the file system. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* media_ptr Media control block pointer */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* return status */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* _fx_utility_logical_sector_write Write a logical sector */
|
||||
/* _fx_utility_logical_sector_read Read a logical sector */
|
||||
/* _fx_utility_16_unsigned_read Read a USHORT from memory */
|
||||
/* _fx_utility_32_unsigned_read Read a ULONG from memory */
|
||||
/* _fx_utility_64_unsigned_read Read a ULONG64 from memory */
|
||||
/* _fx_utility_FAT_entry_write Write a FAT entry */
|
||||
/* _fx_fault_tolerant_cleanup_FAT_chain Cleanup FAT chain */
|
||||
/* memcpy Memory Copy */
|
||||
/* _fx_utility_FAT_flush Flush written FAT entries */
|
||||
/* _fx_utility_logical_sector_flush Flush written logical sectors */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* _fx_fault_tolerant_enable */
|
||||
/* _fx_fault_tolerant_transaction_end */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 05-19-2020 William E. Lamie Initial Version 6.0 */
|
||||
/* 09-30-2020 William E. Lamie Modified comment(s), verified */
|
||||
/* memcpy usage, */
|
||||
/* resulting in version 6.1 */
|
||||
/* 10-31-2022 Tiejun Zhou Modified comment(s), fixed */
|
||||
/* overflow in log size check, */
|
||||
/* resulting in version 6.2.0 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
UINT _fx_fault_tolerant_apply_logs(FX_MEDIA *media_ptr)
|
||||
{
|
||||
UINT status;
|
||||
ULONG64 log_sector;
|
||||
ULONG remaining_logs;
|
||||
ULONG copy_size;
|
||||
ULONG copy_offset;
|
||||
UCHAR *current_ptr;
|
||||
ULONG size;
|
||||
USHORT log_type;
|
||||
ULONG log_len;
|
||||
FX_FAULT_TOLERANT_LOG_HEADER *log_header;
|
||||
FX_FAULT_TOLERANT_FAT_CHAIN *FAT_chain;
|
||||
FX_FAULT_TOLERANT_LOG_CONTENT *log_content;
|
||||
FX_FAULT_TOLERANT_FAT_LOG *fat_log;
|
||||
FX_FAULT_TOLERANT_DIR_LOG *dir_log;
|
||||
|
||||
/* Set log header, FAT chain and log content pointer. */
|
||||
log_header = (FX_FAULT_TOLERANT_LOG_HEADER *)media_ptr -> fx_media_fault_tolerant_memory_buffer;
|
||||
FAT_chain = (FX_FAULT_TOLERANT_FAT_CHAIN *)(media_ptr -> fx_media_fault_tolerant_memory_buffer + FX_FAULT_TOLERANT_FAT_CHAIN_OFFSET);
|
||||
log_content = (FX_FAULT_TOLERANT_LOG_CONTENT *)(media_ptr -> fx_media_fault_tolerant_memory_buffer +
|
||||
FX_FAULT_TOLERANT_LOG_CONTENT_OFFSET);
|
||||
|
||||
/* Find the size of the log file. */
|
||||
size = _fx_utility_16_unsigned_read((UCHAR *)&log_header -> fx_fault_tolerant_log_header_total_size);
|
||||
|
||||
/* Extended port-specific processing macro, which is by default defined to white space. */
|
||||
FX_FAULT_TOLERANT_APPLY_LOGS_EXTENSION
|
||||
|
||||
size -= FX_FAULT_TOLERANT_LOG_CONTENT_HEADER_SIZE;
|
||||
|
||||
/* Find the number of log entries. */
|
||||
remaining_logs = _fx_utility_16_unsigned_read((UCHAR *)&log_content -> fx_fault_tolerant_log_content_count);
|
||||
|
||||
/* Get start address of logs. */
|
||||
current_ptr = (UCHAR *)log_content + FX_FAULT_TOLERANT_LOG_CONTENT_HEADER_SIZE;
|
||||
|
||||
/* Loop through all the logs to apply the changes. */
|
||||
while (remaining_logs)
|
||||
{
|
||||
|
||||
/* Obtain log type of this entry. */
|
||||
log_type = (USHORT)_fx_utility_16_unsigned_read(current_ptr);
|
||||
|
||||
/* Read log length. */
|
||||
log_len = _fx_utility_16_unsigned_read(current_ptr + 2);
|
||||
|
||||
|
||||
/* Validate log entry size. */
|
||||
if (log_len > size)
|
||||
{
|
||||
|
||||
/* Something wrong with log file. */
|
||||
return(FX_FILE_CORRUPT);
|
||||
}
|
||||
|
||||
/* Reduce the total log file size. */
|
||||
size -= log_len;
|
||||
|
||||
/* Process log entry by type. */
|
||||
switch (log_type)
|
||||
{
|
||||
case FX_FAULT_TOLERANT_FAT_LOG_TYPE:
|
||||
|
||||
/* This is a FAT log. */
|
||||
fat_log = (FX_FAULT_TOLERANT_FAT_LOG *)current_ptr;
|
||||
|
||||
/* Write FAT entry. */
|
||||
status = _fx_utility_FAT_entry_write(media_ptr,
|
||||
_fx_utility_32_unsigned_read((UCHAR *)&fat_log -> fx_fault_tolerant_FAT_log_cluster),
|
||||
_fx_utility_32_unsigned_read((UCHAR *)&fat_log -> fx_fault_tolerant_FAT_log_value));
|
||||
|
||||
if (status != FX_SUCCESS)
|
||||
{
|
||||
|
||||
/* Return the error status. */
|
||||
return(status);
|
||||
}
|
||||
break;
|
||||
|
||||
case FX_FAULT_TOLERANT_DIR_LOG_TYPE:
|
||||
|
||||
/* This is a DIR log. */
|
||||
dir_log = (FX_FAULT_TOLERANT_DIR_LOG *)current_ptr;
|
||||
|
||||
log_sector = _fx_utility_64_unsigned_read((UCHAR *)&dir_log -> fx_fault_tolerant_dir_log_sector);
|
||||
|
||||
/* Get the destination sector. */
|
||||
status = _fx_utility_logical_sector_read(media_ptr,
|
||||
log_sector,
|
||||
media_ptr -> fx_media_memory_buffer,
|
||||
((ULONG) 1), FX_DATA_SECTOR);
|
||||
|
||||
if (status != FX_SUCCESS)
|
||||
{
|
||||
|
||||
/* Return the error status. */
|
||||
return(status);
|
||||
}
|
||||
|
||||
/* Set copy information. */
|
||||
copy_offset = _fx_utility_32_unsigned_read((UCHAR *)&dir_log -> fx_fault_tolerant_dir_log_offset);
|
||||
|
||||
|
||||
copy_size = log_len - FX_FAULT_TOLERANT_DIR_LOG_ENTRY_SIZE;
|
||||
|
||||
if (((ULONG64)copy_offset + (ULONG64)copy_size) > (ULONG64)(media_ptr -> fx_media_memory_size))
|
||||
{
|
||||
return(FX_FILE_CORRUPT);
|
||||
}
|
||||
|
||||
/* Copy data into destination sector. */
|
||||
memcpy(media_ptr -> fx_media_memory_buffer + copy_offset, /* Use case of memcpy is verified. */
|
||||
current_ptr + FX_FAULT_TOLERANT_DIR_LOG_ENTRY_SIZE, copy_size);
|
||||
|
||||
|
||||
/* Write back the current logical sector. */
|
||||
status = _fx_utility_logical_sector_write(media_ptr,
|
||||
log_sector,
|
||||
media_ptr -> fx_media_memory_buffer,
|
||||
((ULONG) 1), FX_DIRECTORY_SECTOR);
|
||||
|
||||
if (status != FX_SUCCESS)
|
||||
{
|
||||
|
||||
/* Return the error status. */
|
||||
return(status);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
/* Wrong type. */
|
||||
return(FX_SECTOR_INVALID);
|
||||
}
|
||||
|
||||
/* Decrement the remaining log counter. */
|
||||
remaining_logs--;
|
||||
|
||||
/* Move to start position of next log entry. */
|
||||
current_ptr += log_len;
|
||||
}
|
||||
|
||||
/* Check whether or not to process FAT chain. */
|
||||
if (FAT_chain -> fx_fault_tolerant_FAT_chain_flag & FX_FAULT_TOLERANT_FLAG_FAT_CHAIN_VALID)
|
||||
{
|
||||
|
||||
/* Free old link of FAT. */
|
||||
status = _fx_fault_tolerant_cleanup_FAT_chain(media_ptr, FX_FAULT_TOLERANT_FAT_CHAIN_CLEANUP);
|
||||
if (status != FX_SUCCESS)
|
||||
{
|
||||
|
||||
/* Return the error status. */
|
||||
return(status);
|
||||
}
|
||||
}
|
||||
|
||||
/* Flush the internal logical sector cache. */
|
||||
status = _fx_utility_logical_sector_flush(media_ptr, 1, (ULONG64) media_ptr -> fx_media_total_sectors, FX_FALSE);
|
||||
|
||||
/* Check for a bad status. */
|
||||
if (status != FX_SUCCESS)
|
||||
{
|
||||
|
||||
/* Return the bad status. */
|
||||
return(status);
|
||||
}
|
||||
|
||||
/* Flush FAT table. */
|
||||
#ifdef FX_FAULT_TOLERANT
|
||||
|
||||
/* Ensure the new FAT chain is properly written to the media. */
|
||||
|
||||
/* Flush the cached individual FAT entries */
|
||||
_fx_utility_FAT_flush(media_ptr);
|
||||
#endif
|
||||
|
||||
/* Return success. */
|
||||
return(FX_SUCCESS);
|
||||
}
|
||||
#endif /* FX_ENABLE_FAULT_TOLERANT */
|
||||
|
||||
@@ -0,0 +1,103 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** FileX Component */
|
||||
/** */
|
||||
/** Fault Tolerant */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
#define FX_SOURCE_CODE
|
||||
|
||||
#include "fx_api.h"
|
||||
#include "fx_fault_tolerant.h"
|
||||
#include "fx_utility.h"
|
||||
|
||||
|
||||
#ifdef FX_ENABLE_FAULT_TOLERANT
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _fx_fault_tolerant_calculate_checksum PORTABLE C */
|
||||
/* 6.1 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function calculates checksum for consecutive data. The size */
|
||||
/* of the log file is required to be 4-byte aligned. Therefore this */
|
||||
/* checksum routine is able to perform 4-byte access. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* data Pointer to data */
|
||||
/* len Data length */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* Computed checksum value */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* _fx_utility_32_unsigned_read Read a UINT from memory */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* _fx_fault_tolerant_enable */
|
||||
/* _fx_fault_tolerant_cleanup_FAT_chain */
|
||||
/* _fx_fault_tolerant_reset_log_file */
|
||||
/* _fx_fault_tolerant_set_FAT_chain */
|
||||
/* _fx_fault_tolerant_transaction_end */
|
||||
/* */
|
||||
/* 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 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
USHORT _fx_fault_tolerant_calculate_checksum(UCHAR *data, UINT len)
|
||||
{
|
||||
ULONG checksum = 0;
|
||||
ULONG long_value;
|
||||
|
||||
while (len >= 4)
|
||||
{
|
||||
|
||||
/* Read first long value. */
|
||||
long_value = _fx_utility_32_unsigned_read(data);
|
||||
|
||||
/* Calculate checksum. */
|
||||
checksum += (long_value >> 16) + (long_value & 0xFFFF);
|
||||
|
||||
/* Decrease length. */
|
||||
len -= sizeof(ULONG);
|
||||
data += sizeof(ULONG);
|
||||
}
|
||||
|
||||
/* Trim high 16 bits of checksum. */
|
||||
checksum = (checksum & 0xFFFF) + (checksum >> 16);
|
||||
checksum = (checksum & 0xFFFF) + (checksum >> 16);
|
||||
|
||||
return((USHORT)((~checksum) & 0xFFFF));
|
||||
}
|
||||
#endif /* FX_ENABLE_FAULT_TOLERANT */
|
||||
|
||||
@@ -0,0 +1,356 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** FileX Component */
|
||||
/** */
|
||||
/** Fault Tolerant */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
#define FX_SOURCE_CODE
|
||||
|
||||
#include "fx_api.h"
|
||||
#include "fx_utility.h"
|
||||
#include "fx_fault_tolerant.h"
|
||||
|
||||
|
||||
#ifdef FX_ENABLE_FAULT_TOLERANT
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _fx_utility_FAT_entry_multiple_sectors_check PORTABLE C */
|
||||
/* 6.2.0 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* Tiejun Zhou, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function checks whether the FAT entry spans multiple sectors. */
|
||||
/* It is only possible when the file system is FAT12. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* media_ptr Media control block pointer */
|
||||
/* cluster Cluster entry number */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* FX_TRUE FAT entry spans two sectors */
|
||||
/* FX_FALSE FAT entry in one sector */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* _fx_fault_tolerant_cleanup_FAT_chain */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 10-31-2022 Tiejun Zhou Initial Version 6.2.0 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
static UINT _fx_utility_FAT_entry_multiple_sectors_check(FX_MEDIA *media_ptr, ULONG cluster)
|
||||
{
|
||||
ULONG byte_offset;
|
||||
ULONG FAT_sector;
|
||||
|
||||
/* Check FAT format. */
|
||||
if (!media_ptr -> fx_media_12_bit_FAT)
|
||||
{
|
||||
|
||||
/* Not FAT12. The FAT entry will be in one sector. */
|
||||
return(FX_FALSE);
|
||||
}
|
||||
|
||||
/* File system is FAT12. */
|
||||
/* Calculate the byte offset to the cluster entry. */
|
||||
byte_offset = (((ULONG)cluster << 1) + cluster) >> 1;
|
||||
|
||||
/* Calculate the FAT sector the requested FAT entry resides in. */
|
||||
FAT_sector = (byte_offset / media_ptr -> fx_media_bytes_per_sector) +
|
||||
(ULONG)media_ptr -> fx_media_reserved_sectors;
|
||||
|
||||
/* Now calculate the byte offset into this FAT sector. */
|
||||
byte_offset = byte_offset -
|
||||
((FAT_sector - (ULONG)media_ptr -> fx_media_reserved_sectors) *
|
||||
media_ptr -> fx_media_bytes_per_sector);
|
||||
|
||||
/* Determine if we are now past the end of the FAT buffer in memory. */
|
||||
if (byte_offset == (ULONG)(media_ptr -> fx_media_bytes_per_sector - 1))
|
||||
{
|
||||
|
||||
/* Yes, we are past the end of the FAT buffer. */
|
||||
return(FX_TRUE);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* No, we are not past the end of the FAT buffer. */
|
||||
return(FX_FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _fx_fault_tolerant_cleanup_FAT_chain PORTABLE C */
|
||||
/* 6.2.0 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function cleans up FAT chain. In order to prevent failures */
|
||||
/* during the link-list walk, and to improve efficiency, this function */
|
||||
/* frees the FAT entry chain in sections. For each section, it frees */
|
||||
/* FAT entry from the last entry in the chain and works backwards. */
|
||||
/* Using this method, if the system fails in the middle of the free */
|
||||
/* operation, the head is preserved, and fault tolerant module can */
|
||||
/* "redo" this operation next time it starts up. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* media_ptr Media control block pointer */
|
||||
/* operation Recover a failure operation or*/
|
||||
/* cleanup old FAT chain */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* return status */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* _fx_utility_FAT_entry_read Read a FAT entry */
|
||||
/* _fx_utility_FAT_entry_write Write a FAT entry */
|
||||
/* _fx_utility_16_unsigned_write Write a USHORT from memory */
|
||||
/* _fx_utility_32_unsigned_write Write a ULONG from memory */
|
||||
/* _fx_utility_32_unsigned_read Read a ULONG from memory */
|
||||
/* _fx_utility_FAT_flush Flush written FAT entries */
|
||||
/* _fx_fault_tolerant_calculate_checksum Compute Checksum of data */
|
||||
/* _fx_fault_tolerant_write_log_file Write log file */
|
||||
/* _fx_utility_FAT_entry_multiple_sectors_check */
|
||||
/* Check sectors for FAT entry */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* _fx_fault_tolerant_apply_logs */
|
||||
/* _fx_fault_tolerant_recover */
|
||||
/* */
|
||||
/* 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 */
|
||||
/* 10-31-2022 Tiejun Zhou Modified comment(s), */
|
||||
/* fixed FAT entry span two */
|
||||
/* sectors for FAT12, */
|
||||
/* resulting in version 6.2.0 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
UINT _fx_fault_tolerant_cleanup_FAT_chain(FX_MEDIA *media_ptr, UINT operation)
|
||||
{
|
||||
UINT status;
|
||||
ULONG current_cluster;
|
||||
ULONG next_cluster = 0;
|
||||
ULONG head_cluster;
|
||||
ULONG tail_cluster;
|
||||
ULONG cache_count;
|
||||
ULONG cache_max = FX_FAULT_TOLERANT_CACHE_SIZE >> 2;
|
||||
ULONG *cache_ptr = media_ptr -> fx_media_fault_tolerant_cache;
|
||||
ULONG next_session;
|
||||
USHORT checksum;
|
||||
ULONG i;
|
||||
FX_FAULT_TOLERANT_FAT_CHAIN *FAT_chain;
|
||||
ULONG FAT_sector;
|
||||
ULONG last_FAT_sector;
|
||||
|
||||
/* Set FAT chain pointer. */
|
||||
FAT_chain = (FX_FAULT_TOLERANT_FAT_CHAIN *)(media_ptr -> fx_media_fault_tolerant_memory_buffer + FX_FAULT_TOLERANT_FAT_CHAIN_OFFSET);
|
||||
|
||||
/* Get head and tail cluster. */
|
||||
if (operation == FX_FAULT_TOLERANT_FAT_CHAIN_RECOVER)
|
||||
{
|
||||
|
||||
/* Recover phase. Cleanup (remove) new FAT chain. */
|
||||
head_cluster = _fx_utility_32_unsigned_read((UCHAR *)&FAT_chain -> fx_fault_tolerant_FAT_chain_head_new);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* Cleanup phase. Cleanup (remove) old FAT chain. */
|
||||
head_cluster = _fx_utility_32_unsigned_read((UCHAR *)&FAT_chain -> fx_fault_tolerant_FAT_chain_head_original);
|
||||
}
|
||||
|
||||
/* At this point, the head_cluster points to the cluster chain that is to be removed. */
|
||||
|
||||
/* Tail cluster points to the back of the origianal FAT chain where the new chain is attached to.
|
||||
The remove process terminates once this cluster is encountered. */
|
||||
tail_cluster = _fx_utility_32_unsigned_read((UCHAR *)&FAT_chain -> fx_fault_tolerant_FAT_chain_insertion_back);
|
||||
|
||||
/* Are there any clusters to free? */
|
||||
if ((head_cluster < FX_FAT_ENTRY_START) || (head_cluster >= media_ptr -> fx_media_fat_reserved))
|
||||
{
|
||||
return(FX_SUCCESS);
|
||||
}
|
||||
|
||||
/* To optimize the deletion process of a long FAT chain, the deletion is done in sessions. During one session,
|
||||
a set of FAT entries are removed. If one session is interrupted, after restart the deletion process resumes and
|
||||
picks up from where it left.
|
||||
|
||||
During one deletion session, all FAT entries are between head_cluster(inclusive) and next_session (exclusive).
|
||||
*/
|
||||
next_session = _fx_utility_32_unsigned_read((UCHAR *)&FAT_chain -> fx_fault_tolerant_FAT_chain_next_deletion);
|
||||
|
||||
/* Loop to cleanup all FAT entries. */
|
||||
while ((head_cluster >= FX_FAT_ENTRY_START) && (head_cluster < media_ptr -> fx_media_fat_reserved))
|
||||
{
|
||||
|
||||
/* Initialize. */
|
||||
current_cluster = head_cluster;
|
||||
cache_count = 0;
|
||||
|
||||
/* Loop from head cluster to find entries to cleanup and store this information into cache. */
|
||||
do
|
||||
{
|
||||
|
||||
/* Get the next FAT entry. */
|
||||
status = _fx_utility_FAT_entry_read(media_ptr, current_cluster, &next_cluster);
|
||||
if (status != FX_SUCCESS)
|
||||
{
|
||||
|
||||
/* Return the error status. */
|
||||
return(status);
|
||||
}
|
||||
|
||||
/* Whether or not the cluster is occupied. */
|
||||
if (next_cluster == FX_FREE_CLUSTER)
|
||||
{
|
||||
|
||||
/* Current cluster has already been released. */
|
||||
break;
|
||||
}
|
||||
|
||||
/* Cache the FAT list. */
|
||||
cache_ptr[cache_count++] = current_cluster;
|
||||
|
||||
/* Check whether FAT entry spans multiple sectors. */
|
||||
if (_fx_utility_FAT_entry_multiple_sectors_check(media_ptr, current_cluster))
|
||||
{
|
||||
if (head_cluster == next_session || next_session == FX_FREE_CLUSTER)
|
||||
{
|
||||
next_session = next_cluster;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
/* Move to next cluster. */
|
||||
current_cluster = next_cluster;
|
||||
} while ((next_cluster >= FX_FAT_ENTRY_START) &&
|
||||
(next_cluster < media_ptr -> fx_media_fat_reserved) &&
|
||||
(next_cluster != tail_cluster) &&
|
||||
(cache_count < cache_max));
|
||||
|
||||
/* Get next session. */
|
||||
if (cache_count == cache_max)
|
||||
{
|
||||
next_session = next_cluster;
|
||||
}
|
||||
|
||||
/* Update head cluster and next session into log file. */
|
||||
_fx_utility_32_unsigned_write((UCHAR *)&FAT_chain -> fx_fault_tolerant_FAT_chain_next_deletion, next_session);
|
||||
if (operation == FX_FAULT_TOLERANT_FAT_CHAIN_RECOVER)
|
||||
{
|
||||
_fx_utility_32_unsigned_write((UCHAR *)&FAT_chain -> fx_fault_tolerant_FAT_chain_head_new, head_cluster);
|
||||
}
|
||||
else
|
||||
{
|
||||
_fx_utility_32_unsigned_write((UCHAR *)&FAT_chain -> fx_fault_tolerant_FAT_chain_head_original, head_cluster);
|
||||
}
|
||||
|
||||
/* Update checksum. */
|
||||
_fx_utility_16_unsigned_write((UCHAR *)&FAT_chain -> fx_fault_tolerant_FAT_chain_checksumm, 0);
|
||||
checksum = _fx_fault_tolerant_calculate_checksum((UCHAR *)FAT_chain, FX_FAULT_TOLERANT_FAT_CHAIN_SIZE);
|
||||
_fx_utility_16_unsigned_write((UCHAR *)&FAT_chain -> fx_fault_tolerant_FAT_chain_checksumm, checksum);
|
||||
|
||||
/* Flush the fault tolerant log into the file system. */
|
||||
_fx_fault_tolerant_write_log_file(media_ptr, 0);
|
||||
|
||||
/* Loop to free FAT in cache from back to front. */
|
||||
if (cache_count > 0)
|
||||
{
|
||||
|
||||
/* Get sector of last FAT entry. */
|
||||
last_FAT_sector = _fx_utility_FAT_sector_get(media_ptr, cache_ptr[cache_count - 1]);
|
||||
i = cache_count;
|
||||
while (i > 0)
|
||||
{
|
||||
i--;
|
||||
|
||||
/* Get sector of current FAT entry. */
|
||||
FAT_sector = _fx_utility_FAT_sector_get(media_ptr, cache_ptr[i]);
|
||||
if (FAT_sector != last_FAT_sector)
|
||||
{
|
||||
|
||||
/* Current FAT entry is located in different sector. Force flush. */
|
||||
/* Flush the cached individual FAT entries */
|
||||
_fx_utility_FAT_flush(media_ptr);
|
||||
|
||||
/* Update sector of current FAT entry. */
|
||||
last_FAT_sector = FAT_sector;
|
||||
}
|
||||
|
||||
/* Free current_cluster. */
|
||||
status = _fx_utility_FAT_entry_write(media_ptr, cache_ptr[i], FX_FREE_CLUSTER);
|
||||
if (status != FX_SUCCESS)
|
||||
{
|
||||
|
||||
/* Return the error status. */
|
||||
return(status);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* Increase the available clusters in the media control block. */
|
||||
media_ptr -> fx_media_available_clusters += cache_count;
|
||||
}
|
||||
|
||||
/* Flush the cached individual FAT entries */
|
||||
_fx_utility_FAT_flush(media_ptr);
|
||||
|
||||
|
||||
/* Get head cluster. */
|
||||
if (head_cluster == next_session)
|
||||
{
|
||||
break;
|
||||
}
|
||||
head_cluster = next_session;
|
||||
}
|
||||
|
||||
return(FX_SUCCESS);
|
||||
}
|
||||
#endif /* FX_ENABLE_FAULT_TOLERANT */
|
||||
@@ -0,0 +1,233 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** FileX Component */
|
||||
/** */
|
||||
/** Fault Tolerant */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
#define FX_SOURCE_CODE
|
||||
|
||||
#include "fx_api.h"
|
||||
#include "fx_utility.h"
|
||||
#include "fx_directory.h"
|
||||
#include "fx_fault_tolerant.h"
|
||||
|
||||
|
||||
#ifdef FX_ENABLE_FAULT_TOLERANT
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _fx_fault_tolerant_create_log_file PORTABLE C */
|
||||
/* 6.1.11 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function finds an available cluster used by log file. Then it */
|
||||
/* sets the cluster number to boot sector. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* media_ptr Media control block pointer */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* return status */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* _fx_utility_FAT_entry_read Read a FAT entry */
|
||||
/* _fx_utility_FAT_entry_write Write a FAT entry */
|
||||
/* _fx_utility_FAT_flush Flush written FAT entries */
|
||||
/* _fx_utility_32_unsigned_write Write a ULONG from memory */
|
||||
/* _fx_utility_logical_sector_read Read a logical sector */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* _fx_fault_tolerant_enable */
|
||||
/* */
|
||||
/* 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 */
|
||||
/* 01-31-2022 Bhupendra Naphade Modified comment(s), replaced */
|
||||
/* sector size constant, */
|
||||
/* resulting in version 6.1.10 */
|
||||
/* 04-25-2022 William E. Lamie Modified comment(s), */
|
||||
/* resulting in version 6.1.11 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
UINT _fx_fault_tolerant_create_log_file(FX_MEDIA *media_ptr)
|
||||
{
|
||||
ULONG clusters;
|
||||
ULONG FAT_index;
|
||||
ULONG FAT_value = 0;
|
||||
UINT found;
|
||||
UINT status;
|
||||
UINT i;
|
||||
|
||||
/* Yes. Create a log file. */
|
||||
/* First find a free cluster. */
|
||||
if (media_ptr -> fx_media_available_clusters < media_ptr -> fx_media_fault_tolerant_clusters)
|
||||
{
|
||||
|
||||
/* Out of disk space. */
|
||||
return(FX_NO_MORE_SPACE);
|
||||
}
|
||||
|
||||
/* Now we need to find the consecutive clusters. */
|
||||
clusters = media_ptr -> fx_media_fault_tolerant_clusters;
|
||||
FAT_index = FX_FAT_ENTRY_START;
|
||||
found = FX_FALSE;
|
||||
while (FAT_index <= (media_ptr -> fx_media_total_clusters - clusters + FX_FAT_ENTRY_START))
|
||||
{
|
||||
|
||||
/* Determine if enough consecutive FAT entries are available. */
|
||||
i = 0;
|
||||
|
||||
|
||||
do
|
||||
{
|
||||
|
||||
/* Read a FAT entry. */
|
||||
status = _fx_utility_FAT_entry_read(media_ptr, (FAT_index + i), &FAT_value);
|
||||
|
||||
/* Check for a successful status. */
|
||||
if (status != FX_SUCCESS)
|
||||
{
|
||||
|
||||
/* Return the error status. */
|
||||
return(status);
|
||||
}
|
||||
|
||||
/* Determine if the entry is free. */
|
||||
if (FAT_value != FX_FREE_CLUSTER)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
/* Otherwise, increment the consecutive FAT indices. */
|
||||
i++;
|
||||
} while (i < clusters);
|
||||
|
||||
/* Determine if we found enough FAT entries. */
|
||||
if (i >= clusters)
|
||||
{
|
||||
|
||||
/* Yes, we have found enough FAT entries - set the found
|
||||
flag and get out of this loop. */
|
||||
found = FX_TRUE;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Position to the next possibly free FAT entry. */
|
||||
FAT_index = FAT_index + i + 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Determine if we found enough consecutive clusters to satisfy the
|
||||
request. */
|
||||
if (!found)
|
||||
{
|
||||
|
||||
/* Not enough contiguous space on the media. Return error status. */
|
||||
return(FX_NO_MORE_SPACE);
|
||||
}
|
||||
|
||||
/* Update the link pointers in the new clusters. */
|
||||
for (i = 0; i < (clusters - 1); i++)
|
||||
{
|
||||
|
||||
/* Update the cluster links. Since the allocation is
|
||||
sequential, we just have to link each FAT entry to the
|
||||
next one. */
|
||||
status = _fx_utility_FAT_entry_write(media_ptr, FAT_index + i, FAT_index + i + 1);
|
||||
|
||||
/* Check for a bad status. */
|
||||
if (status != FX_SUCCESS)
|
||||
{
|
||||
|
||||
/* Return the error status. */
|
||||
return(status);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* Now place an EOF in the last cluster entry. */
|
||||
status = _fx_utility_FAT_entry_write(media_ptr, FAT_index + clusters - 1, media_ptr -> fx_media_fat_last);
|
||||
|
||||
/* Check for a bad status. */
|
||||
if (status != FX_SUCCESS)
|
||||
{
|
||||
|
||||
/* Return the error status. */
|
||||
return(status);
|
||||
}
|
||||
|
||||
|
||||
#ifdef FX_FAULT_TOLERANT
|
||||
|
||||
/* Flush the cached individual FAT entries */
|
||||
_fx_utility_FAT_flush(media_ptr);
|
||||
|
||||
#endif /* FX_FAULT_TOLERANT */
|
||||
|
||||
/* Write start cluster for the file tolerant log file into the boot sector. */
|
||||
_fx_utility_32_unsigned_write(media_ptr -> fx_media_fault_tolerant_memory_buffer + FX_FAULT_TOLERANT_BOOT_INDEX, FAT_index);
|
||||
|
||||
/* Write the boot sector. */
|
||||
media_ptr -> fx_media_driver_request = FX_DRIVER_BOOT_WRITE;
|
||||
media_ptr -> fx_media_driver_status = FX_IO_ERROR;
|
||||
media_ptr -> fx_media_driver_buffer = media_ptr -> fx_media_fault_tolerant_memory_buffer;
|
||||
media_ptr -> fx_media_driver_sectors = 1;
|
||||
media_ptr -> fx_media_driver_sector_type = FX_BOOT_SECTOR;
|
||||
|
||||
/* If trace is enabled, insert this event into the trace buffer. */
|
||||
FX_TRACE_IN_LINE_INSERT(FX_TRACE_INTERNAL_IO_DRIVER_BOOT_WRITE, media_ptr, media_ptr -> fx_media_fault_tolerant_memory_buffer, 0, 0, FX_TRACE_INTERNAL_EVENTS, 0, 0)
|
||||
|
||||
/* Invoke the driver to read the boot sector. */
|
||||
(media_ptr -> fx_media_driver_entry) (media_ptr);
|
||||
|
||||
/* Determine if the boot sector was read correctly. */
|
||||
if (media_ptr -> fx_media_driver_status != FX_SUCCESS)
|
||||
{
|
||||
|
||||
/* Return the boot sector error status. */
|
||||
return(FX_BOOT_ERROR);
|
||||
}
|
||||
|
||||
|
||||
/* Set the start cluster. */
|
||||
media_ptr -> fx_media_fault_tolerant_start_cluster = FAT_index;
|
||||
|
||||
/* Decrease available cluster. */
|
||||
media_ptr -> fx_media_available_clusters =
|
||||
media_ptr -> fx_media_available_clusters - clusters;
|
||||
|
||||
/* Return success. */
|
||||
return(FX_SUCCESS);
|
||||
}
|
||||
#endif /* FX_ENABLE_FAULT_TOLERANT */
|
||||
|
||||
@@ -0,0 +1,500 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** FileX Component */
|
||||
/** */
|
||||
/** Fault Tolerant */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
#define FX_SOURCE_CODE
|
||||
|
||||
#include "fx_api.h"
|
||||
#include "fx_utility.h"
|
||||
#include "fx_directory.h"
|
||||
#include "fx_fault_tolerant.h"
|
||||
|
||||
|
||||
#ifdef FX_ENABLE_FAULT_TOLERANT
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _fx_fault_tolerant_enable PORTABLE C */
|
||||
/* 6.2.0 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function enables the FileX Fault Tolerant feature. It first */
|
||||
/* searches for a valid log file. A valid log file indicates the */
|
||||
/* previous write operation failed, and appropriate action now must */
|
||||
/* be taken to restore the integrity of the file system. Once the */
|
||||
/* recovery effort is completed, the file system is properly restored. */
|
||||
/* An empty log file indicates the previous write operation was */
|
||||
/* successfully completed and no action needs to be taken at this */
|
||||
/* point. If the file system does not have a log file, or the */
|
||||
/* checksum is not valid, it is an indication either the file system */
|
||||
/* is not under the protection of FileX Fault Tolerant. A new log */
|
||||
/* file is created. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* media_ptr Media control block pointer */
|
||||
/* memory_buffer Pointer to memory buffer. */
|
||||
/* memory_size Size of memory buffer. */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* return status */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* _fx_fault_tolerant_calculate_checksum Compute Checksum of data */
|
||||
/* _fx_fault_tolerant_apply_logs Apply logs into file system */
|
||||
/* _fx_fault_tolerant_recover Recover FAT chain */
|
||||
/* _fx_fault_tolerant_reset_log_file Reset the log file */
|
||||
/* _fx_fault_tolerant_read_log_file Read log file to cache */
|
||||
/* _fx_utility_FAT_entry_read Read a FAT entry */
|
||||
/* _fx_utility_16_unsigned_read Read a USHORT from memory */
|
||||
/* _fx_utility_32_unsigned_read Read a ULONG from memory */
|
||||
/* */
|
||||
/* 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 */
|
||||
/* 10-31-2022 Tiejun Zhou Modified comment(s), */
|
||||
/* fixed memory buffer when */
|
||||
/* cache is disabled, */
|
||||
/* resulting in version 6.2.0 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
UINT _fx_fault_tolerant_enable(FX_MEDIA *media_ptr, VOID *memory_buffer, UINT memory_size)
|
||||
{
|
||||
ULONG start_cluster;
|
||||
ULONG FAT_value;
|
||||
UINT status;
|
||||
ULONG checksum;
|
||||
ULONG total_size;
|
||||
FX_FAULT_TOLERANT_LOG_HEADER *log_header;
|
||||
FX_FAULT_TOLERANT_FAT_CHAIN *FAT_chain;
|
||||
ULONG cluster_number;
|
||||
ULONG i, j;
|
||||
ULONG FAT_entry, FAT_sector, FAT_read_sectors;
|
||||
ULONG bytes_in_buffer;
|
||||
ULONG clusters;
|
||||
ULONG bytes_per_sector;
|
||||
ULONG bytes_per_cluster;
|
||||
|
||||
/* Protect against other threads accessing the media. */
|
||||
FX_PROTECT
|
||||
|
||||
/* Calculate clusters needed for fault tolerant log. */
|
||||
bytes_per_sector = media_ptr -> fx_media_bytes_per_sector;
|
||||
bytes_per_cluster = bytes_per_sector * media_ptr -> fx_media_sectors_per_cluster;
|
||||
|
||||
if (bytes_per_cluster == 0)
|
||||
{
|
||||
|
||||
/* Release media protection. */
|
||||
FX_UNPROTECT
|
||||
|
||||
return(FX_MEDIA_INVALID);
|
||||
}
|
||||
|
||||
clusters = (FX_FAULT_TOLERANT_MAXIMUM_LOG_FILE_SIZE + bytes_per_cluster - 1) / bytes_per_cluster;
|
||||
media_ptr -> fx_media_fault_tolerant_clusters = clusters;
|
||||
|
||||
/* Check buffer size requirement. */
|
||||
if (memory_size < bytes_per_sector)
|
||||
{
|
||||
|
||||
/* Release media protection. */
|
||||
FX_UNPROTECT
|
||||
|
||||
return(FX_NOT_ENOUGH_MEMORY);
|
||||
}
|
||||
|
||||
|
||||
if (media_ptr -> fx_media_FAT32_additional_info_sector)
|
||||
{
|
||||
|
||||
/* A 32-bit FAT is present. Read directly into the logical sector
|
||||
cache memory to optimize I/O on larger devices. Since we are looking for
|
||||
values of zero, endian issues are not important. */
|
||||
/* Force update the available cluster. */
|
||||
|
||||
#ifndef FX_DISABLE_CACHE
|
||||
/* Invalidate the current logical sector cache. */
|
||||
_fx_utility_logical_sector_flush(media_ptr, ((ULONG64) 1), (ULONG64) (media_ptr -> fx_media_total_sectors), FX_TRUE);
|
||||
|
||||
/* Reset the memory pointer. */
|
||||
media_ptr -> fx_media_memory_buffer = media_ptr -> fx_media_sector_cache[0].fx_cached_sector_memory_buffer;
|
||||
#endif /* FX_DISABLE_CACHE */
|
||||
|
||||
/* Reset the available cluster. */
|
||||
media_ptr -> fx_media_available_clusters = 0;
|
||||
|
||||
/* Loop through all FAT sectors in the primary FAT. The first two entries are
|
||||
examined in this loop, but they are always unavailable. */
|
||||
cluster_number = 0;
|
||||
#ifndef FX_DISABLE_CACHE
|
||||
for (i = 0; i < media_ptr -> fx_media_sectors_per_FAT; i = i + media_ptr -> fx_media_sector_cache_size)
|
||||
{
|
||||
|
||||
/* Calculate the starting next FAT sector. */
|
||||
FAT_sector = media_ptr -> fx_media_reserved_sectors + i;
|
||||
|
||||
/* Calculate how many sectors to read. */
|
||||
FAT_read_sectors = media_ptr -> fx_media_sectors_per_FAT - i;
|
||||
|
||||
/* Determine if there is not enough memory to read the remaining FAT sectors. */
|
||||
if (FAT_read_sectors > media_ptr -> fx_media_sector_cache_size)
|
||||
{
|
||||
FAT_read_sectors = media_ptr -> fx_media_sector_cache_size;
|
||||
}
|
||||
#else
|
||||
/* Reset the buffer sector. */
|
||||
media_ptr -> fx_media_memory_buffer_sector = (ULONG64)-1;
|
||||
for (i = 0; i < media_ptr -> fx_media_sectors_per_FAT; i++)
|
||||
{
|
||||
|
||||
/* Calculate the starting next FAT sector. */
|
||||
FAT_sector = media_ptr -> fx_media_reserved_sectors + i;
|
||||
|
||||
/* Calculate how many sectors to read. */
|
||||
FAT_read_sectors = 1;
|
||||
#endif /* FX_DISABLE_CACHE */
|
||||
|
||||
/* Read the FAT sectors directly from the driver. */
|
||||
media_ptr -> fx_media_driver_request = FX_DRIVER_READ;
|
||||
media_ptr -> fx_media_driver_status = FX_IO_ERROR;
|
||||
media_ptr -> fx_media_driver_buffer = media_ptr -> fx_media_memory_buffer;
|
||||
media_ptr -> fx_media_driver_logical_sector = FAT_sector;
|
||||
media_ptr -> fx_media_driver_sectors = FAT_read_sectors;
|
||||
media_ptr -> fx_media_driver_sector_type = FX_FAT_SECTOR;
|
||||
|
||||
/* If trace is enabled, insert this event into the trace buffer. */
|
||||
FX_TRACE_IN_LINE_INSERT(FX_TRACE_INTERNAL_IO_DRIVER_READ, media_ptr, FAT_sector, FAT_read_sectors, media_ptr -> fx_media_memory_buffer, FX_TRACE_INTERNAL_EVENTS, 0, 0)
|
||||
|
||||
/* Invoke the driver to read the FAT sectors. */
|
||||
(media_ptr -> fx_media_driver_entry) (media_ptr);
|
||||
|
||||
/* Determine if the read was successful. */
|
||||
if (media_ptr -> fx_media_driver_status != FX_SUCCESS)
|
||||
{
|
||||
|
||||
/* Release media protection. */
|
||||
FX_UNPROTECT
|
||||
|
||||
return(FX_FAT_READ_ERROR);
|
||||
}
|
||||
|
||||
/* Calculate the number of bytes in the buffer. */
|
||||
bytes_in_buffer = (media_ptr -> fx_media_bytes_per_sector * FAT_read_sectors);
|
||||
|
||||
/* Walk through the sector cache memory to search for available clusters and the first
|
||||
available if not already found. */
|
||||
for (j = 0; j < bytes_in_buffer;)
|
||||
{
|
||||
|
||||
/* Pickup 32-bit FAT entry. */
|
||||
FAT_entry = *((ULONG *)&(media_ptr -> fx_media_memory_buffer[j]));
|
||||
|
||||
/* Advance to next FAT entry. */
|
||||
j = j + 4;
|
||||
|
||||
/* Determine if the FAT entry is free. */
|
||||
if (FAT_entry == FX_FREE_CLUSTER)
|
||||
{
|
||||
|
||||
/* Entry is free, increment available clusters. */
|
||||
media_ptr -> fx_media_available_clusters++;
|
||||
|
||||
/* Determine if the starting free cluster has been found yet. */
|
||||
if (media_ptr -> fx_media_cluster_search_start == 0)
|
||||
{
|
||||
|
||||
/* Remember the first free cluster to start further searches from. */
|
||||
media_ptr -> fx_media_cluster_search_start = cluster_number;
|
||||
}
|
||||
}
|
||||
|
||||
/* Increment the cluster number. */
|
||||
cluster_number++;
|
||||
|
||||
/* Determine if we have reviewed all FAT entries. */
|
||||
if (cluster_number >= (media_ptr -> fx_media_total_clusters + FX_FAT_ENTRY_START))
|
||||
{
|
||||
|
||||
/* Yes, we have looked at all the FAT entries. */
|
||||
|
||||
/* Ensure that the outer loop terminates as well. */
|
||||
i = media_ptr -> fx_media_sectors_per_FAT;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Store memory buffer and size. */
|
||||
media_ptr -> fx_media_fault_tolerant_memory_buffer = (UCHAR *)memory_buffer;
|
||||
if (memory_size > (clusters * bytes_per_cluster))
|
||||
{
|
||||
media_ptr -> fx_media_fault_tolerant_memory_buffer_size = clusters * bytes_per_cluster;
|
||||
}
|
||||
else
|
||||
{
|
||||
media_ptr -> fx_media_fault_tolerant_memory_buffer_size = memory_size / bytes_per_sector * bytes_per_sector;
|
||||
}
|
||||
|
||||
/* Read the boot sector from the device. */
|
||||
media_ptr -> fx_media_driver_request = FX_DRIVER_BOOT_READ;
|
||||
media_ptr -> fx_media_driver_status = FX_IO_ERROR;
|
||||
media_ptr -> fx_media_driver_buffer = (UCHAR *)memory_buffer;
|
||||
media_ptr -> fx_media_driver_sectors = 1;
|
||||
media_ptr -> fx_media_driver_sector_type = FX_BOOT_SECTOR;
|
||||
|
||||
/* If trace is enabled, insert this event into the trace buffer. */
|
||||
FX_TRACE_IN_LINE_INSERT(FX_TRACE_INTERNAL_IO_DRIVER_BOOT_READ, media_ptr, memory_buffer, 0, 0, FX_TRACE_INTERNAL_EVENTS, 0, 0)
|
||||
|
||||
/* Invoke the driver to read the boot sector. */
|
||||
(media_ptr -> fx_media_driver_entry) (media_ptr);
|
||||
|
||||
/* Determine if the boot sector was read correctly. */
|
||||
if (media_ptr -> fx_media_driver_status != FX_SUCCESS)
|
||||
{
|
||||
|
||||
/* Release media protection. */
|
||||
FX_UNPROTECT
|
||||
|
||||
/* Return the boot sector error status. */
|
||||
return(FX_BOOT_ERROR);
|
||||
}
|
||||
|
||||
/* Check whether the boot index is used. */
|
||||
start_cluster = _fx_utility_32_unsigned_read((UCHAR *)memory_buffer + FX_FAULT_TOLERANT_BOOT_INDEX);
|
||||
if (start_cluster != 0)
|
||||
{
|
||||
|
||||
/* The location of the fault tolerant log file is found. Need to verify the integrity of the log file. */
|
||||
if ((start_cluster >= FX_FAT_ENTRY_START) && (start_cluster < media_ptr -> fx_media_fat_reserved))
|
||||
{
|
||||
|
||||
/* Check whether this cluster is used. */
|
||||
for (i = 0; i < clusters; i++)
|
||||
{
|
||||
|
||||
/* Read FAT entry. */
|
||||
status = _fx_utility_FAT_entry_read(media_ptr, start_cluster + i, &FAT_value);
|
||||
|
||||
/* Check for a bad status. */
|
||||
if (status != FX_SUCCESS)
|
||||
{
|
||||
|
||||
/* Release media protection. */
|
||||
FX_UNPROTECT
|
||||
|
||||
/* Return the bad status. */
|
||||
return(status);
|
||||
}
|
||||
|
||||
if (i < clusters - 1)
|
||||
{
|
||||
if (FAT_value != (start_cluster + i + 1))
|
||||
{
|
||||
|
||||
/* Mark invalid. */
|
||||
start_cluster = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (FAT_value != media_ptr -> fx_media_fat_last)
|
||||
{
|
||||
|
||||
/* Mark invalid. */
|
||||
start_cluster = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Is this FAT entry occupied by log file? */
|
||||
if (start_cluster)
|
||||
{
|
||||
|
||||
/* Set the start cluster. */
|
||||
media_ptr -> fx_media_fault_tolerant_start_cluster = start_cluster;
|
||||
|
||||
/* Read log file from file system to memory. */
|
||||
status = _fx_fault_tolerant_read_log_file(media_ptr);
|
||||
|
||||
/* Check for good completion status. */
|
||||
if (status != FX_SUCCESS)
|
||||
{
|
||||
|
||||
/* Release media protection. */
|
||||
FX_UNPROTECT
|
||||
|
||||
/* Return the error status. */
|
||||
return(status);
|
||||
}
|
||||
|
||||
/* Set log header and FAT chain pointer. */
|
||||
log_header = (FX_FAULT_TOLERANT_LOG_HEADER *)media_ptr -> fx_media_fault_tolerant_memory_buffer;
|
||||
FAT_chain = (FX_FAULT_TOLERANT_FAT_CHAIN *)(media_ptr -> fx_media_fault_tolerant_memory_buffer +
|
||||
FX_FAULT_TOLERANT_FAT_CHAIN_OFFSET);
|
||||
|
||||
/* Verify ID field. */
|
||||
if (_fx_utility_32_unsigned_read((UCHAR *)&log_header -> fx_fault_tolerant_log_header_id) == FX_FAULT_TOLERANT_ID)
|
||||
{
|
||||
|
||||
/* Calculate checksum of log header. */
|
||||
checksum = _fx_fault_tolerant_calculate_checksum((UCHAR *)log_header,
|
||||
FX_FAULT_TOLERANT_LOG_HEADER_SIZE);
|
||||
|
||||
if (checksum == 0)
|
||||
{
|
||||
|
||||
/* Fault tolerant log file is valid. */
|
||||
/* Initialize file size. */
|
||||
total_size = _fx_utility_16_unsigned_read((UCHAR *)&log_header -> fx_fault_tolerant_log_header_total_size);
|
||||
media_ptr -> fx_media_fault_tolerant_file_size = total_size;
|
||||
|
||||
|
||||
/* Verify the checksum of the FAT chain. */
|
||||
checksum = _fx_fault_tolerant_calculate_checksum((UCHAR *)FAT_chain,
|
||||
FX_FAULT_TOLERANT_FAT_CHAIN_SIZE);
|
||||
|
||||
if (checksum == 0)
|
||||
{
|
||||
|
||||
/* Checksum of FAT chain is correct. */
|
||||
|
||||
if (total_size > (FX_FAULT_TOLERANT_LOG_CONTENT_OFFSET + FX_FAULT_TOLERANT_LOG_HEADER_SIZE))
|
||||
{
|
||||
|
||||
/* Log content is present. */
|
||||
/* Now verify the checksum of log content. */
|
||||
checksum = _fx_fault_tolerant_calculate_checksum((media_ptr -> fx_media_fault_tolerant_memory_buffer +
|
||||
FX_FAULT_TOLERANT_LOG_CONTENT_OFFSET),
|
||||
(total_size - FX_FAULT_TOLERANT_LOG_CONTENT_OFFSET));
|
||||
if (checksum == 0)
|
||||
{
|
||||
|
||||
/* Checksum of log content is correct. */
|
||||
|
||||
/* Extended port-specific processing macro, which is by default defined to white space. */
|
||||
FX_FAULT_TOLERANT_ENABLE_EXTENSION
|
||||
|
||||
/* This is the situation where the log file contains log entries. This is an indication
|
||||
that previous write operation did not complete successfully. Need to apply the log entries
|
||||
to recover the previous write operation, effectively to finish up the previous write operation. */
|
||||
status = _fx_fault_tolerant_apply_logs(media_ptr);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* Extended port-specific processing macro, which is by default defined to white space. */
|
||||
FX_FAULT_TOLERANT_ENABLE_EXTENSION
|
||||
|
||||
/* The log file does not contain log content but the FAT chain operation information is present.
|
||||
This is the situation where the FAT chain has been modified but the rest of the content of these
|
||||
clusters are not updated yet. In this situation, the previous FAT chain operation needs to be
|
||||
reverted to restore the file system back to its state prior to the write operation. */
|
||||
status = _fx_fault_tolerant_recover(media_ptr);
|
||||
}
|
||||
|
||||
if (status != FX_SUCCESS)
|
||||
{
|
||||
|
||||
/* Release media protection. */
|
||||
FX_UNPROTECT
|
||||
|
||||
/* Return the error status. */
|
||||
return(status);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* Not a valid cluster number. Set the flag to create a new log file. */
|
||||
start_cluster = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Check whether or not to create a log file. */
|
||||
if (start_cluster == 0)
|
||||
{
|
||||
|
||||
/* Create log file. */
|
||||
status = _fx_fault_tolerant_create_log_file(media_ptr);
|
||||
|
||||
if (status != FX_SUCCESS)
|
||||
{
|
||||
|
||||
/* Release media protection. */
|
||||
FX_UNPROTECT
|
||||
|
||||
/* Return the error status. */
|
||||
return(status);
|
||||
}
|
||||
}
|
||||
|
||||
/* Reset log file. */
|
||||
status = _fx_fault_tolerant_reset_log_file(media_ptr);
|
||||
|
||||
if (status != FX_SUCCESS)
|
||||
{
|
||||
|
||||
/* Release media protection. */
|
||||
FX_UNPROTECT
|
||||
|
||||
/* Return the error status. */
|
||||
return(status);
|
||||
}
|
||||
|
||||
/* Mark fault tolerant feature is enabled. */
|
||||
media_ptr -> fx_media_fault_tolerant_enabled = FX_TRUE;
|
||||
|
||||
/* Reset the transaction count. */
|
||||
media_ptr -> fx_media_fault_tolerant_transaction_count = 0;
|
||||
|
||||
/* Initialize the sector number of cached FAT entries. */
|
||||
media_ptr -> fx_media_fault_tolerant_cached_FAT_sector = 0;
|
||||
|
||||
/* Release media protection. */
|
||||
FX_UNPROTECT
|
||||
|
||||
/* Return the error status. */
|
||||
return(FX_SUCCESS);
|
||||
}
|
||||
|
||||
#endif /* FX_ENABLE_FAULT_TOLERANT */
|
||||
|
||||
@@ -0,0 +1,167 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** FileX Component */
|
||||
/** */
|
||||
/** Fault Tolerant */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
#define FX_SOURCE_CODE
|
||||
|
||||
#include "fx_api.h"
|
||||
#include "fx_utility.h"
|
||||
#include "fx_fault_tolerant.h"
|
||||
|
||||
|
||||
#ifdef FX_ENABLE_FAULT_TOLERANT
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _fx_fault_tolerant_read_FAT PORTABLE C */
|
||||
/* 6.1 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function reads value of a FAT entry from log file if it */
|
||||
/* exists. During file or directory operations with Fault Tolerant */
|
||||
/* protection, intermediate operations are written to the fault */
|
||||
/* tolerant log files. Therefore, FAT-entry read should search for */
|
||||
/* fault tolerant log before the request can be passed to normal FAT */
|
||||
/* entry read routine. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* media_ptr Media control block pointer */
|
||||
/* cluster Cluster entry number */
|
||||
/* value Pointer to value for the entry*/
|
||||
/* log_type FAT or bitmap */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* return status */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* _fx_utility_16_unsigned_read Read a USHORT from memory */
|
||||
/* _fx_utility_32_unsigned_read Read a ULONG from memory */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* _fx_utility_FAT_entry_read */
|
||||
/* */
|
||||
/* 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_fault_tolerant_read_FAT(FX_MEDIA *media_ptr, ULONG cluster, ULONG *value, ULONG log_type)
|
||||
{
|
||||
ULONG logs_remaining;
|
||||
UCHAR *current_ptr;
|
||||
UCHAR found = FX_FALSE;
|
||||
ULONG size;
|
||||
USHORT type;
|
||||
ULONG log_len;
|
||||
FX_FAULT_TOLERANT_FAT_LOG *fat_log;
|
||||
|
||||
|
||||
/* Get fault tolerant data. */
|
||||
logs_remaining = media_ptr -> fx_media_fault_tolerant_total_logs;
|
||||
|
||||
/* Any redo logs? */
|
||||
if (logs_remaining == 0)
|
||||
{
|
||||
|
||||
/* No. Just return. */
|
||||
return(FX_READ_CONTINUE);
|
||||
}
|
||||
|
||||
/* Get size of all logs. */
|
||||
size = media_ptr -> fx_media_fault_tolerant_file_size - FX_FAULT_TOLERANT_LOG_CONTENT_OFFSET;
|
||||
|
||||
/* Get the first log pointer. */
|
||||
current_ptr = media_ptr -> fx_media_fault_tolerant_memory_buffer +
|
||||
FX_FAULT_TOLERANT_LOG_CONTENT_OFFSET +
|
||||
FX_FAULT_TOLERANT_LOG_CONTENT_HEADER_SIZE;
|
||||
|
||||
/* Loop throught all FAT logs. */
|
||||
while (logs_remaining)
|
||||
{
|
||||
|
||||
/* Check log type. */
|
||||
type = (USHORT)_fx_utility_16_unsigned_read(current_ptr);
|
||||
|
||||
/* Get log length. */
|
||||
log_len = _fx_utility_16_unsigned_read(current_ptr + 2);
|
||||
|
||||
/* Validate the size value. */
|
||||
if (log_len > size)
|
||||
{
|
||||
|
||||
/* Log file is corrupted. Nothing can be done. Return.*/
|
||||
return(FX_FILE_CORRUPT);
|
||||
}
|
||||
size -= log_len;
|
||||
|
||||
/* Check log type. */
|
||||
if (type == log_type)
|
||||
{
|
||||
|
||||
/* This is the log with same type . */
|
||||
/* Get the log pointer. */
|
||||
fat_log = (FX_FAULT_TOLERANT_FAT_LOG *)current_ptr;
|
||||
|
||||
/* Is this FAT log entry the one looking for? */
|
||||
if (_fx_utility_32_unsigned_read((UCHAR *)&fat_log -> fx_fault_tolerant_FAT_log_cluster) == cluster)
|
||||
{
|
||||
|
||||
/* Yes, it is. */
|
||||
*value = _fx_utility_32_unsigned_read((UCHAR *)&fat_log -> fx_fault_tolerant_FAT_log_value);
|
||||
|
||||
/* Do not return since there may be more than one log for this cluster. */
|
||||
found = FX_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
/* Decrease the logs_remaining counter. */
|
||||
logs_remaining--;
|
||||
|
||||
/* Get next log pointer. */
|
||||
current_ptr += log_len;
|
||||
}
|
||||
|
||||
if (found != FX_TRUE)
|
||||
{
|
||||
|
||||
/* Pass the request to FAT entry read. */
|
||||
return(FX_READ_CONTINUE);
|
||||
}
|
||||
|
||||
/* Return success. */
|
||||
return(FX_SUCCESS);
|
||||
}
|
||||
|
||||
#endif /* FX_ENABLE_FAULT_TOLERANT */
|
||||
|
||||
@@ -0,0 +1,178 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** FileX Component */
|
||||
/** */
|
||||
/** Fault Tolerant */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
#define FX_SOURCE_CODE
|
||||
|
||||
#include "fx_api.h"
|
||||
#include "fx_utility.h"
|
||||
#include "fx_fault_tolerant.h"
|
||||
|
||||
|
||||
#ifdef FX_ENABLE_FAULT_TOLERANT
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _fx_fault_tolerant_read_directory_sector PORTABLE C */
|
||||
/* 6.1 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function handles directory sector read requests. During file or*/
|
||||
/* directory operations with Fault Tolerant protection, intermediate */
|
||||
/* operations are written to the fault tolerant log files. Therefore, */
|
||||
/* sector read should search for fault tolerant log before the request */
|
||||
/* can be passed to normal directory entry read routine. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* media_ptr Media control block pointer */
|
||||
/* logical_sector Logical sector number */
|
||||
/* buffer_ptr Pointer of receiving buffer */
|
||||
/* sectors Number of sectors to read */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* return status */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* _fx_utility_16_unsigned_read Read a USHORT from memory */
|
||||
/* _fx_utility_32_unsigned_read Read a ULONG from memory */
|
||||
/* memcpy Memory Copy */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* _fx_utility_logical_sector_read */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 05-19-2020 William E. Lamie Initial Version 6.0 */
|
||||
/* 09-30-2020 William E. Lamie Modified comment(s), verified */
|
||||
/* memcpy usage, */
|
||||
/* resulting in version 6.1 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
UINT _fx_fault_tolerant_read_directory_sector(FX_MEDIA *media_ptr, ULONG64 logical_sector,
|
||||
VOID *buffer_ptr, ULONG64 sectors)
|
||||
{
|
||||
ULONG logs_remaining;
|
||||
ULONG copy_offset;
|
||||
ULONG copy_size;
|
||||
UCHAR *current_ptr;
|
||||
UCHAR *current_buffer_ptr;
|
||||
ULONG size;
|
||||
USHORT type;
|
||||
ULONG log_len;
|
||||
ULONG64 log_sector;
|
||||
FX_FAULT_TOLERANT_DIR_LOG *dir_log;
|
||||
|
||||
/* Get fault tolerant data. */
|
||||
logs_remaining = media_ptr -> fx_media_fault_tolerant_total_logs;
|
||||
|
||||
/* Any redo logs? */
|
||||
if (logs_remaining == 0)
|
||||
{
|
||||
|
||||
/* No. Just return. */
|
||||
return(FX_SUCCESS);
|
||||
}
|
||||
|
||||
/* Get size of all logs. */
|
||||
size = media_ptr -> fx_media_fault_tolerant_file_size - FX_FAULT_TOLERANT_LOG_CONTENT_OFFSET;
|
||||
|
||||
/* Get the first log pointer. */
|
||||
current_ptr = media_ptr -> fx_media_fault_tolerant_memory_buffer +
|
||||
FX_FAULT_TOLERANT_LOG_CONTENT_OFFSET +
|
||||
FX_FAULT_TOLERANT_LOG_CONTENT_HEADER_SIZE;
|
||||
|
||||
/* Loop throught all FAT logs. */
|
||||
while (logs_remaining)
|
||||
{
|
||||
|
||||
/* Check log type. */
|
||||
type = (USHORT)_fx_utility_16_unsigned_read(current_ptr);
|
||||
|
||||
/* Get log length. */
|
||||
log_len = _fx_utility_16_unsigned_read(current_ptr + 2);
|
||||
|
||||
/* Validate the size value. */
|
||||
if (log_len > size)
|
||||
{
|
||||
|
||||
/* Log file is corrupted. Nothing can be done. Return.*/
|
||||
return(FX_FILE_CORRUPT);
|
||||
}
|
||||
size -= log_len;
|
||||
|
||||
/* Check log type. */
|
||||
if (type == FX_FAULT_TOLERANT_DIR_LOG_TYPE)
|
||||
{
|
||||
|
||||
/* Get the log pointer. */
|
||||
dir_log = (FX_FAULT_TOLERANT_DIR_LOG *)current_ptr;
|
||||
|
||||
/* Get the sector of log. */
|
||||
log_sector = _fx_utility_64_unsigned_read((UCHAR *)&dir_log -> fx_fault_tolerant_dir_log_sector);
|
||||
|
||||
/* Is this log sector in the range of sectors to read? */
|
||||
if ((log_sector >= logical_sector) && (log_sector < logical_sector + sectors))
|
||||
{
|
||||
|
||||
/* Yes. Update the content in this sector. */
|
||||
current_buffer_ptr = ((UCHAR *)buffer_ptr) + (log_sector - logical_sector) *
|
||||
media_ptr -> fx_media_bytes_per_sector;
|
||||
|
||||
/* Set copy information. */
|
||||
copy_offset = _fx_utility_32_unsigned_read((UCHAR *)&dir_log -> fx_fault_tolerant_dir_log_offset);
|
||||
|
||||
copy_size = log_len - FX_FAULT_TOLERANT_DIR_LOG_ENTRY_SIZE;
|
||||
|
||||
if ((copy_offset + copy_size) > media_ptr -> fx_media_bytes_per_sector)
|
||||
{
|
||||
return(FX_FILE_CORRUPT);
|
||||
}
|
||||
|
||||
/* Copy data into destination sector. */
|
||||
memcpy(current_buffer_ptr + copy_offset, /* Use case of memcpy is verified. */
|
||||
current_ptr + FX_FAULT_TOLERANT_DIR_LOG_ENTRY_SIZE, copy_size);
|
||||
}
|
||||
}
|
||||
|
||||
/* Decrease the logs_remaining counter. */
|
||||
logs_remaining--;
|
||||
|
||||
/* Move to start position of next log entry. */
|
||||
current_ptr += log_len;
|
||||
}
|
||||
|
||||
/* Return success. */
|
||||
return(FX_SUCCESS);
|
||||
}
|
||||
|
||||
#endif /* FX_ENABLE_FAULT_TOLERANT */
|
||||
|
||||
@@ -0,0 +1,93 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** FileX Component */
|
||||
/** */
|
||||
/** Fault Tolerant */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
#define FX_SOURCE_CODE
|
||||
|
||||
#include "fx_api.h"
|
||||
#include "fx_utility.h"
|
||||
#include "fx_fault_tolerant.h"
|
||||
|
||||
|
||||
#ifdef FX_ENABLE_FAULT_TOLERANT
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _fx_fault_tolerant_read_log_file PORTABLE C */
|
||||
/* 6.1 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function reads the entire log file from file system into the */
|
||||
/* fault tolerant cache. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* media_ptr Media control block pointer */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* return status */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* _fx_utility_logical_sector_read Read a logical sector */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* _fx_fault_tolerant_enable */
|
||||
/* */
|
||||
/* 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_fault_tolerant_read_log_file(FX_MEDIA *media_ptr)
|
||||
{
|
||||
UINT status;
|
||||
ULONG sectors;
|
||||
ULONG start_sector;
|
||||
|
||||
/* Calculate count of sectors to read. */
|
||||
sectors = media_ptr -> fx_media_fault_tolerant_memory_buffer_size / media_ptr -> fx_media_bytes_per_sector;
|
||||
|
||||
/* Calculate the start sector of log file. */
|
||||
start_sector = (media_ptr -> fx_media_fault_tolerant_start_cluster - FX_FAT_ENTRY_START) *
|
||||
media_ptr -> fx_media_sectors_per_cluster +
|
||||
media_ptr -> fx_media_data_sector_start;
|
||||
|
||||
status = _fx_utility_logical_sector_read(media_ptr, (ULONG64) start_sector,
|
||||
media_ptr -> fx_media_fault_tolerant_memory_buffer,
|
||||
sectors, FX_DATA_SECTOR);
|
||||
|
||||
/* Return the status. */
|
||||
return(status);
|
||||
}
|
||||
#endif /* FX_ENABLE_FAULT_TOLERANT */
|
||||
|
||||
@@ -0,0 +1,159 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** FileX Component */
|
||||
/** */
|
||||
/** Fault Tolerant */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
#define FX_SOURCE_CODE
|
||||
|
||||
#include "fx_api.h"
|
||||
#include "fx_utility.h"
|
||||
#include "fx_fault_tolerant.h"
|
||||
|
||||
|
||||
#ifdef FX_ENABLE_FAULT_TOLERANT
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _fx_fault_tolerant_recover PORTABLE C */
|
||||
/* 6.1 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function is called after the FAT chain is been updated but */
|
||||
/* the rest of the write operation fails. At this point, there is */
|
||||
/* need to undo the FAT chain operation, which includes: */
|
||||
/* (1) Remove newly allocated FAT entries; */
|
||||
/* (2) Restore the origianl FAT chain removed during the FAT chain */
|
||||
/* update; */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* media_ptr Media control block pointer */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* return status */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* _fx_fault_tolerant_cleanup_FAT_chain Cleanup FAT chain */
|
||||
/* _fx_utility_32_unsigned_read Read a ULONG from memory */
|
||||
/* _fx_utility_FAT_entry_write Write a FAT entry */
|
||||
/* _fx_utility_FAT_flush Flush written FAT entries */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* _fx_directory_attributes_set */
|
||||
/* _fx_directory_create */
|
||||
/* _fx_directory_delete */
|
||||
/* _fx_directory_rename */
|
||||
/* _fx_file_allocate */
|
||||
/* _fx_file_attributes_set */
|
||||
/* _fx_file_best_effort_allocate */
|
||||
/* _fx_file_create */
|
||||
/* _fx_file_delete */
|
||||
/* _fx_file_rename */
|
||||
/* _fx_file_truncate */
|
||||
/* _fx_file_truncate_release */
|
||||
/* _fx_file_write */
|
||||
/* _fx_unicode_directory_create */
|
||||
/* _fx_unicode_file_create */
|
||||
/* _fx_fault_tolerant_enable */
|
||||
/* */
|
||||
/* 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_fault_tolerant_recover(FX_MEDIA *media_ptr)
|
||||
{
|
||||
UINT status;
|
||||
ULONG insertion_front;
|
||||
ULONG origianl_head_cluster;
|
||||
FX_FAULT_TOLERANT_FAT_CHAIN *FAT_chain;
|
||||
|
||||
|
||||
/* Set fault tolerant state to IDLE. */
|
||||
media_ptr -> fx_media_fault_tolerant_state = FX_FAULT_TOLERANT_STATE_IDLE;
|
||||
|
||||
/* Set FAT chain pointer. */
|
||||
FAT_chain = (FX_FAULT_TOLERANT_FAT_CHAIN *)(media_ptr -> fx_media_fault_tolerant_memory_buffer + FX_FAULT_TOLERANT_FAT_CHAIN_OFFSET);
|
||||
|
||||
/* Whether or not the supplied FAT chain is valid. */
|
||||
if (!(FAT_chain -> fx_fault_tolerant_FAT_chain_flag & FX_FAULT_TOLERANT_FLAG_FAT_CHAIN_VALID))
|
||||
{
|
||||
|
||||
/* Invalid, which indiates the FAT chain has been cleaned up already. In this case, just return. */
|
||||
return(FX_SUCCESS);
|
||||
}
|
||||
|
||||
/* Set FAT chain pointer. */
|
||||
FAT_chain = (FX_FAULT_TOLERANT_FAT_CHAIN *)(media_ptr -> fx_media_fault_tolerant_memory_buffer + FX_FAULT_TOLERANT_FAT_CHAIN_OFFSET);
|
||||
|
||||
/* Recover FAT chain. */
|
||||
status = _fx_fault_tolerant_cleanup_FAT_chain(media_ptr, FX_FAULT_TOLERANT_FAT_CHAIN_RECOVER);
|
||||
if (status != FX_SUCCESS)
|
||||
{
|
||||
|
||||
/* Return the error status. */
|
||||
return(status);
|
||||
}
|
||||
|
||||
/* Now, link the front of the insertion point back to the origianl FAT chain. */
|
||||
insertion_front = _fx_utility_32_unsigned_read((UCHAR *)&FAT_chain -> fx_fault_tolerant_FAT_chain_insertion_front);
|
||||
origianl_head_cluster = _fx_utility_32_unsigned_read((UCHAR *)&FAT_chain -> fx_fault_tolerant_FAT_chain_head_original);
|
||||
|
||||
if (insertion_front != FX_FREE_CLUSTER)
|
||||
{
|
||||
|
||||
/* Front of the insertion point exists. Link the origianl chain back to the front of the insertion point. */
|
||||
status = _fx_utility_FAT_entry_write(media_ptr, insertion_front, origianl_head_cluster);
|
||||
if (status != FX_SUCCESS)
|
||||
{
|
||||
|
||||
/* Return the error status. */
|
||||
return(status);
|
||||
}
|
||||
}
|
||||
|
||||
/* New FAT chain is always linked by FAT entries. */
|
||||
|
||||
/* Flush FAT table. */
|
||||
#ifdef FX_FAULT_TOLERANT
|
||||
|
||||
/* Ensure the new FAT chain is properly written to the media. */
|
||||
|
||||
/* Flush the cached individual FAT entries */
|
||||
_fx_utility_FAT_flush(media_ptr);
|
||||
#endif
|
||||
|
||||
/* Return success. */
|
||||
return(FX_SUCCESS);
|
||||
}
|
||||
#endif /* FX_ENABLE_FAULT_TOLERANT */
|
||||
|
||||
@@ -0,0 +1,142 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** FileX Component */
|
||||
/** */
|
||||
/** Fault Tolerant */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
#define FX_SOURCE_CODE
|
||||
|
||||
#include "fx_api.h"
|
||||
#include "fx_utility.h"
|
||||
#include "fx_directory.h"
|
||||
#include "fx_fault_tolerant.h"
|
||||
|
||||
|
||||
#ifdef FX_ENABLE_FAULT_TOLERANT
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _fx_fault_tolerant_reset_log_file PORTABLE C */
|
||||
/* 6.1 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function removes all log entries from the log file, and */
|
||||
/* it to its initial state. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* media_ptr Media control block pointer */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* return status */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* _fx_utility_16_unsigned_write Write a USHORT from memory */
|
||||
/* _fx_utility_32_unsigned_write Write a ULONG from memory */
|
||||
/* _fx_fault_tolerant_calculate_checksum Compute Checksum of data */
|
||||
/* _fx_fault_tolerant_write_log_file Write log file */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* _fx_directory_attributes_set */
|
||||
/* _fx_directory_create */
|
||||
/* _fx_directory_delete */
|
||||
/* _fx_directory_rename */
|
||||
/* _fx_file_allocate */
|
||||
/* _fx_file_attributes_set */
|
||||
/* _fx_file_best_effort_allocate */
|
||||
/* _fx_file_create */
|
||||
/* _fx_file_delete */
|
||||
/* _fx_file_rename */
|
||||
/* _fx_file_truncate */
|
||||
/* _fx_file_truncate_release */
|
||||
/* _fx_file_write */
|
||||
/* _fx_unicode_directory_create */
|
||||
/* _fx_unicode_file_create */
|
||||
/* _fx_fault_tolerant_enable */
|
||||
/* _fx_fault_tolerant_transaction_end */
|
||||
/* */
|
||||
/* 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_fault_tolerant_reset_log_file(FX_MEDIA *media_ptr)
|
||||
{
|
||||
UINT status;
|
||||
USHORT checksum;
|
||||
FX_FAULT_TOLERANT_LOG_HEADER *log_header;
|
||||
FX_FAULT_TOLERANT_FAT_CHAIN *FAT_chain;
|
||||
FX_FAULT_TOLERANT_LOG_CONTENT *log_content;
|
||||
|
||||
/* Set log header, FAT chain and log content pointer. */
|
||||
log_header = (FX_FAULT_TOLERANT_LOG_HEADER *)media_ptr -> fx_media_fault_tolerant_memory_buffer;
|
||||
FAT_chain = (FX_FAULT_TOLERANT_FAT_CHAIN *)(media_ptr -> fx_media_fault_tolerant_memory_buffer +
|
||||
FX_FAULT_TOLERANT_FAT_CHAIN_OFFSET);
|
||||
log_content = (FX_FAULT_TOLERANT_LOG_CONTENT *)(media_ptr -> fx_media_fault_tolerant_memory_buffer +
|
||||
FX_FAULT_TOLERANT_LOG_CONTENT_OFFSET);
|
||||
|
||||
/* Reset the log file header. */
|
||||
_fx_utility_32_unsigned_write((UCHAR *)&log_header -> fx_fault_tolerant_log_header_id, FX_FAULT_TOLERANT_ID);
|
||||
_fx_utility_16_unsigned_write((UCHAR *)&log_header -> fx_fault_tolerant_log_header_total_size,
|
||||
(FX_FAULT_TOLERANT_LOG_HEADER_SIZE + FX_FAULT_TOLERANT_FAT_CHAIN_SIZE));
|
||||
_fx_utility_16_unsigned_write((UCHAR *)&log_header -> fx_fault_tolerant_log_header_checksum, 0);
|
||||
log_header -> fx_fault_tolerant_log_header_version_major = FX_FAULT_TOLERANT_VERSION_MAJOR;
|
||||
log_header -> fx_fault_tolerant_log_header_version_minor = FX_FAULT_TOLERANT_VERSION_MINOR;
|
||||
_fx_utility_16_unsigned_write((UCHAR *)&log_header -> fx_fault_tolerant_log_header_reserved, 0);
|
||||
checksum = _fx_fault_tolerant_calculate_checksum((UCHAR *)log_header, FX_FAULT_TOLERANT_LOG_HEADER_SIZE);
|
||||
_fx_utility_16_unsigned_write((UCHAR *)&log_header -> fx_fault_tolerant_log_header_checksum, checksum);
|
||||
|
||||
/* Reset the undo log section. */
|
||||
_fx_utility_16_unsigned_write((UCHAR *)&FAT_chain -> fx_fault_tolerant_FAT_chain_checksumm, 0xFFFF);
|
||||
FAT_chain -> fx_fault_tolerant_FAT_chain_flag = 0;
|
||||
FAT_chain -> fx_fault_tolerant_FAT_chain_reserved = 0;
|
||||
_fx_utility_32_unsigned_write((UCHAR *)&FAT_chain -> fx_fault_tolerant_FAT_chain_insertion_front, 0);
|
||||
_fx_utility_32_unsigned_write((UCHAR *)&FAT_chain -> fx_fault_tolerant_FAT_chain_head_new, 0);
|
||||
_fx_utility_32_unsigned_write((UCHAR *)&FAT_chain -> fx_fault_tolerant_FAT_chain_head_original, 0);
|
||||
_fx_utility_32_unsigned_write((UCHAR *)&FAT_chain -> fx_fault_tolerant_FAT_chain_insertion_back, 0);
|
||||
_fx_utility_32_unsigned_write((UCHAR *)&FAT_chain -> fx_fault_tolerant_FAT_chain_next_deletion, 0);
|
||||
|
||||
/* Reset log content header. */
|
||||
_fx_utility_16_unsigned_write((UCHAR *)&log_content -> fx_fault_tolerant_log_content_checksum, 0xFFFF);
|
||||
_fx_utility_16_unsigned_write((UCHAR *)&log_content -> fx_fault_tolerant_log_content_count, 0xFFFF);
|
||||
|
||||
/* No matter success or fail, close this transaction. */
|
||||
media_ptr -> fx_media_fault_tolerant_state = FX_FAULT_TOLERANT_STATE_IDLE;
|
||||
|
||||
/* Write the log header and FAT chain. */
|
||||
status = _fx_fault_tolerant_write_log_file(media_ptr, 0);
|
||||
|
||||
/* Return the status. */
|
||||
return(status);
|
||||
}
|
||||
#endif /* FX_ENABLE_FAULT_TOLERANT */
|
||||
|
||||
@@ -0,0 +1,125 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** FileX Component */
|
||||
/** */
|
||||
/** Fault Tolerant */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
#define FX_SOURCE_CODE
|
||||
|
||||
#include "fx_api.h"
|
||||
#include "fx_utility.h"
|
||||
#include "fx_fault_tolerant.h"
|
||||
|
||||
|
||||
#ifdef FX_ENABLE_FAULT_TOLERANT
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _fx_fault_tolerant_set_FAT_chain PORTABLE C */
|
||||
/* 6.1 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function sets data of FAT chain. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* media_ptr Media control block pointer */
|
||||
/* use_bitmap Whether or not the orignal */
|
||||
/* FAT chain uses bitmap */
|
||||
/* insertion_front Previous cluster of head */
|
||||
/* new_head_cluster Head cluster of new chain */
|
||||
/* origianl_head_cluster Head cluster of the original */
|
||||
/* chain */
|
||||
/* insertion_back next cluster of chain tail */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* return status */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* _fx_utility_16_unsigned_write Write a USHORT from memory */
|
||||
/* _fx_utility_32_unsigned_write Write a ULONG from memory */
|
||||
/* _fx_fault_tolerant_calculate_checksum Compute Checksum of data */
|
||||
/* _fx_fault_tolerant_write_log_file Write log file */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* _fx_file_allocate */
|
||||
/* _fx_file_best_effort_allocate */
|
||||
/* _fx_file_delete */
|
||||
/* _fx_file_truncate_release */
|
||||
/* _fx_file_write */
|
||||
/* */
|
||||
/* 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_fault_tolerant_set_FAT_chain(FX_MEDIA *media_ptr, UINT use_bitmap, ULONG insertion_front,
|
||||
ULONG new_head_cluster, ULONG original_head_cluster,
|
||||
ULONG insertion_back)
|
||||
{
|
||||
UINT status;
|
||||
USHORT checksum;
|
||||
UCHAR flag = FX_FAULT_TOLERANT_FLAG_FAT_CHAIN_VALID;
|
||||
FX_FAULT_TOLERANT_FAT_CHAIN *FAT_chain;
|
||||
|
||||
/* Set FAT chain pointer. */
|
||||
FAT_chain = (FX_FAULT_TOLERANT_FAT_CHAIN *)(media_ptr -> fx_media_fault_tolerant_memory_buffer + FX_FAULT_TOLERANT_FAT_CHAIN_OFFSET);
|
||||
|
||||
/* Parameters not used. Avoid compiler warnings. */
|
||||
FX_PARAMETER_NOT_USED(use_bitmap);
|
||||
|
||||
|
||||
/* Reset checksum first. */
|
||||
_fx_utility_16_unsigned_write((UCHAR *)&FAT_chain -> fx_fault_tolerant_FAT_chain_checksumm, 0);
|
||||
|
||||
/* Set clusters. */
|
||||
_fx_utility_32_unsigned_write((UCHAR *)&FAT_chain -> fx_fault_tolerant_FAT_chain_insertion_front, insertion_front);
|
||||
_fx_utility_32_unsigned_write((UCHAR *)&FAT_chain -> fx_fault_tolerant_FAT_chain_head_new, new_head_cluster);
|
||||
_fx_utility_32_unsigned_write((UCHAR *)&FAT_chain -> fx_fault_tolerant_FAT_chain_head_original, original_head_cluster);
|
||||
_fx_utility_32_unsigned_write((UCHAR *)&FAT_chain -> fx_fault_tolerant_FAT_chain_insertion_back, insertion_back);
|
||||
_fx_utility_32_unsigned_write((UCHAR *)&FAT_chain -> fx_fault_tolerant_FAT_chain_next_deletion, FX_FREE_CLUSTER);
|
||||
|
||||
/* Set flag and reserved. */
|
||||
FAT_chain -> fx_fault_tolerant_FAT_chain_flag = flag;
|
||||
FAT_chain -> fx_fault_tolerant_FAT_chain_reserved = (UCHAR)0;
|
||||
|
||||
/* Calculate checksum. */
|
||||
checksum = _fx_fault_tolerant_calculate_checksum((UCHAR *)FAT_chain, FX_FAULT_TOLERANT_FAT_CHAIN_SIZE);
|
||||
_fx_utility_16_unsigned_write((UCHAR *)&FAT_chain -> fx_fault_tolerant_FAT_chain_checksumm, checksum);
|
||||
|
||||
/* Write the log header and FAT chain. */
|
||||
status = _fx_fault_tolerant_write_log_file(media_ptr, 0);
|
||||
|
||||
/* Return the status. */
|
||||
return(status);
|
||||
}
|
||||
#endif /* FX_ENABLE_FAULT_TOLERANT */
|
||||
|
||||
@@ -0,0 +1,207 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** FileX Component */
|
||||
/** */
|
||||
/** Fault Tolerant */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
#define FX_SOURCE_CODE
|
||||
|
||||
#include "fx_api.h"
|
||||
#include "fx_fault_tolerant.h"
|
||||
#include "fx_utility.h"
|
||||
|
||||
#ifdef FX_ENABLE_FAULT_TOLERANT
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _fx_fault_tolerant_transaction_end PORTABLE C */
|
||||
/* 6.1 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function completes a file system update operation protected */
|
||||
/* by fault tolerant. This function first computes the checksum */
|
||||
/* for the log entries, flush the log file to the file system (a */
|
||||
/* necessary step to record vital information for the file system to */
|
||||
/* recover, in case the update operation fails midway). After the */
|
||||
/* log entries are written to the physical medium, the actualy file */
|
||||
/* system changes (FAT table, directory entries) are applied. */
|
||||
/* */
|
||||
/* If the file system changes are successfully applied, the log */
|
||||
/* entries can be removed. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* media_ptr Media control block pointer */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* return status */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* _fx_utility_16_unsigned_write Write a USHORT from memory */
|
||||
/* _fx_fault_tolerant_apply_logs Apply logs into file system */
|
||||
/* _fx_fault_tolerant_calculate_checksum Compute Checksum of data */
|
||||
/* _fx_fault_tolerant_write_log_file Write log file */
|
||||
/* _fx_fault_tolerant_reset_log_file Reset the log file */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* _fx_directory_attributes_set */
|
||||
/* _fx_directory_create */
|
||||
/* _fx_directory_delete */
|
||||
/* _fx_directory_rename */
|
||||
/* _fx_file_allocate */
|
||||
/* _fx_file_attributes_set */
|
||||
/* _fx_file_best_effort_allocate */
|
||||
/* _fx_file_create */
|
||||
/* _fx_file_delete */
|
||||
/* _fx_file_rename */
|
||||
/* _fx_file_truncate */
|
||||
/* _fx_file_truncate_release */
|
||||
/* _fx_file_write */
|
||||
/* _fx_unicode_directory_create */
|
||||
/* _fx_unicode_file_create */
|
||||
/* */
|
||||
/* 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_fault_tolerant_transaction_end(FX_MEDIA *media_ptr)
|
||||
{
|
||||
ULONG relative_sector;
|
||||
UINT status;
|
||||
USHORT checksum;
|
||||
UINT offset;
|
||||
FX_FAULT_TOLERANT_LOG_HEADER *log_header;
|
||||
FX_FAULT_TOLERANT_LOG_CONTENT *log_content;
|
||||
|
||||
/* Is fault tolerant enabled? */
|
||||
if (media_ptr -> fx_media_fault_tolerant_enabled == FX_FALSE)
|
||||
{
|
||||
return(FX_SUCCESS);
|
||||
}
|
||||
|
||||
/* Decrease the transaction. */
|
||||
media_ptr -> fx_media_fault_tolerant_transaction_count--;
|
||||
|
||||
/* Is transaction finished? */
|
||||
if (media_ptr -> fx_media_fault_tolerant_transaction_count != 0)
|
||||
{
|
||||
return(FX_SUCCESS);
|
||||
}
|
||||
|
||||
/* Close this transaction. */
|
||||
media_ptr -> fx_media_fault_tolerant_state = FX_FAULT_TOLERANT_STATE_IDLE;
|
||||
|
||||
/* Set log header and FAT chain pointer. */
|
||||
log_header = (FX_FAULT_TOLERANT_LOG_HEADER *)media_ptr -> fx_media_fault_tolerant_memory_buffer;
|
||||
log_content = (FX_FAULT_TOLERANT_LOG_CONTENT *)(media_ptr -> fx_media_fault_tolerant_memory_buffer +
|
||||
FX_FAULT_TOLERANT_LOG_CONTENT_OFFSET);
|
||||
|
||||
/* Reset checksum field and update log entry counter field. */
|
||||
_fx_utility_16_unsigned_write((UCHAR *)&log_content -> fx_fault_tolerant_log_content_checksum, 0);
|
||||
_fx_utility_16_unsigned_write((UCHAR *)&log_content -> fx_fault_tolerant_log_content_count,
|
||||
media_ptr -> fx_media_fault_tolerant_total_logs);
|
||||
|
||||
/* Now calculate the checksum of log content. */
|
||||
checksum = _fx_fault_tolerant_calculate_checksum((media_ptr -> fx_media_fault_tolerant_memory_buffer +
|
||||
FX_FAULT_TOLERANT_LOG_CONTENT_OFFSET),
|
||||
(media_ptr -> fx_media_fault_tolerant_file_size -
|
||||
FX_FAULT_TOLERANT_LOG_CONTENT_OFFSET));
|
||||
|
||||
/* Record checksum field of log content. */
|
||||
_fx_utility_16_unsigned_write((UCHAR *)&log_content -> fx_fault_tolerant_log_content_checksum, checksum);
|
||||
|
||||
/* Record log header. */
|
||||
_fx_utility_16_unsigned_write((UCHAR *)&log_header -> fx_fault_tolerant_log_header_total_size,
|
||||
media_ptr -> fx_media_fault_tolerant_file_size);
|
||||
_fx_utility_16_unsigned_write((UCHAR *)&log_header -> fx_fault_tolerant_log_header_checksum, 0);
|
||||
|
||||
/* Calculate checksum of the header. */
|
||||
checksum = _fx_fault_tolerant_calculate_checksum((UCHAR *)log_header, FX_FAULT_TOLERANT_LOG_HEADER_SIZE);
|
||||
|
||||
/* Record checksum field of the header. */
|
||||
_fx_utility_16_unsigned_write((UCHAR *)&log_header -> fx_fault_tolerant_log_header_checksum, checksum);
|
||||
|
||||
/* Flush log content and flush first sector at last. The first sector contains size of total log file.
|
||||
* The log file will contain wrong value of size when it is interrupted after first sector flushed to file system. */
|
||||
relative_sector = 1;
|
||||
offset = media_ptr -> fx_media_bytes_per_sector;
|
||||
while (offset < media_ptr -> fx_media_fault_tolerant_file_size)
|
||||
{
|
||||
|
||||
/* Write back the log. */
|
||||
status = _fx_fault_tolerant_write_log_file(media_ptr, relative_sector);
|
||||
|
||||
/* Check for good completion status. */
|
||||
if (status != FX_SUCCESS)
|
||||
{
|
||||
|
||||
/* Error. */
|
||||
return(status);
|
||||
}
|
||||
|
||||
/* Increase relative sector and offset. */
|
||||
relative_sector++;
|
||||
offset += media_ptr -> fx_media_bytes_per_sector;
|
||||
}
|
||||
|
||||
/* Flush first sector. */
|
||||
status = _fx_fault_tolerant_write_log_file(media_ptr, 0);
|
||||
|
||||
/* Check for good completion status. */
|
||||
if (status != FX_SUCCESS)
|
||||
{
|
||||
|
||||
/* Error. */
|
||||
return(status);
|
||||
}
|
||||
|
||||
/* At this pointer, the vital information has been flushed to the physical medium.
|
||||
Update the file system (FAT table, directory entry) using information recorded in the
|
||||
log file. */
|
||||
status = _fx_fault_tolerant_apply_logs(media_ptr);
|
||||
|
||||
/* Check for a bad status. */
|
||||
if (status != FX_SUCCESS)
|
||||
{
|
||||
|
||||
/* Return the bad status. */
|
||||
return(status);
|
||||
}
|
||||
|
||||
/* The file system has been updated successfully. Remove and reset the fault tolerant
|
||||
log file. */
|
||||
status = _fx_fault_tolerant_reset_log_file(media_ptr);
|
||||
|
||||
return(status);
|
||||
}
|
||||
#endif /* FX_ENABLE_FAULT_TOLERANT */
|
||||
|
||||
@@ -0,0 +1,105 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** FileX Component */
|
||||
/** */
|
||||
/** Fault Tolerant */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
#define FX_SOUCE_CODE
|
||||
|
||||
#include "fx_api.h"
|
||||
#include "fx_fault_tolerant.h"
|
||||
|
||||
#if defined(FX_ENABLE_FAULT_TOLERANT) && defined(FX_FAULT_TOLERANT_TRANSACTION_FAIL_FUNCTION)
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _fx_fault_tolerant_transaction_fail PORTABLE C */
|
||||
/* 6.1 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function cleans up resources created by fault tolerant when */
|
||||
/* transaction fails. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* media_ptr Media control block pointer */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* return status */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* _fx_directory_attributes_set */
|
||||
/* _fx_directory_create */
|
||||
/* _fx_directory_delete */
|
||||
/* _fx_directory_rename */
|
||||
/* _fx_file_allocate */
|
||||
/* _fx_file_attributes_set */
|
||||
/* _fx_file_best_effort_allocate */
|
||||
/* _fx_file_create */
|
||||
/* _fx_file_delete */
|
||||
/* _fx_file_rename */
|
||||
/* _fx_file_truncate */
|
||||
/* _fx_file_truncate_release */
|
||||
/* _fx_file_write */
|
||||
/* _fx_unicode_directory_create */
|
||||
/* _fx_unicode_file_create */
|
||||
/* */
|
||||
/* 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_fault_tolerant_transaction_fail(FX_MEDIA *media_ptr)
|
||||
{
|
||||
|
||||
/* Check whether fault tolerant is enabled or not. */
|
||||
if (media_ptr -> fx_media_fault_tolerant_enabled == FX_TRUE)
|
||||
{
|
||||
|
||||
/* Yes. Decrease the counter for transaction. */
|
||||
media_ptr -> fx_media_fault_tolerant_transaction_count--;
|
||||
|
||||
/* Is this the last transaction? */
|
||||
if (media_ptr -> fx_media_fault_tolerant_transaction_count == 0)
|
||||
{
|
||||
|
||||
/* Yes. Perform recover and reset the log file. */
|
||||
_fx_fault_tolerant_recover(media_ptr);
|
||||
_fx_fault_tolerant_reset_log_file(media_ptr);
|
||||
}
|
||||
}
|
||||
|
||||
return(FX_SUCCESS);
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,115 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** FileX Component */
|
||||
/** */
|
||||
/** Fault Tolerant */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
#define FX_SOURCE_CODE
|
||||
|
||||
#include "fx_api.h"
|
||||
#include "fx_fault_tolerant.h"
|
||||
|
||||
|
||||
#ifdef FX_ENABLE_FAULT_TOLERANT
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _fx_fault_tolerant_transaction_start PORTABLE C */
|
||||
/* 6.1 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function is called at the beginning of an update to FileX */
|
||||
/* file, directory entry, or FAT table. It resets fault tolerant */
|
||||
/* internal state information. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* media_ptr Media control block pointer */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* return status */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* _fx_directory_attributes_set */
|
||||
/* _fx_directory_create */
|
||||
/* _fx_directory_delete */
|
||||
/* _fx_directory_rename */
|
||||
/* _fx_file_allocate */
|
||||
/* _fx_file_attributes_set */
|
||||
/* _fx_file_best_effort_allocate */
|
||||
/* _fx_file_create */
|
||||
/* _fx_file_delete */
|
||||
/* _fx_file_rename */
|
||||
/* _fx_file_truncate */
|
||||
/* _fx_file_truncate_release */
|
||||
/* _fx_file_write */
|
||||
/* _fx_unicode_directory_create */
|
||||
/* _fx_unicode_file_create */
|
||||
/* */
|
||||
/* 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_fault_tolerant_transaction_start(FX_MEDIA *media_ptr)
|
||||
{
|
||||
|
||||
/* Is fault tolerant enabled? */
|
||||
if (media_ptr -> fx_media_fault_tolerant_enabled == FX_TRUE)
|
||||
{
|
||||
|
||||
/* Is this a new transaction? */
|
||||
if (media_ptr -> fx_media_fault_tolerant_transaction_count == 0)
|
||||
{
|
||||
|
||||
/* Yes. Initialize data. */
|
||||
media_ptr -> fx_media_fault_tolerant_file_size = FX_FAULT_TOLERANT_LOG_HEADER_SIZE +
|
||||
FX_FAULT_TOLERANT_FAT_CHAIN_SIZE +
|
||||
FX_FAULT_TOLERANT_LOG_CONTENT_HEADER_SIZE;
|
||||
|
||||
/* Reset total logs. */
|
||||
media_ptr -> fx_media_fault_tolerant_total_logs = 0;
|
||||
|
||||
/* Set state of fault tolerant. */
|
||||
media_ptr -> fx_media_fault_tolerant_state = FX_FAULT_TOLERANT_STATE_STARTED;
|
||||
}
|
||||
|
||||
/* Increase the transaction. */
|
||||
media_ptr -> fx_media_fault_tolerant_transaction_count++;
|
||||
}
|
||||
|
||||
return(FX_SUCCESS);
|
||||
}
|
||||
#endif /* FX_ENABLE_FAULT_TOLERANT */
|
||||
|
||||
@@ -0,0 +1,112 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** FileX Component */
|
||||
/** */
|
||||
/** Fault Tolerant */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
#define FX_SOURCE_CODE
|
||||
|
||||
#include "fx_api.h"
|
||||
#include "fx_utility.h"
|
||||
#include "fx_directory.h"
|
||||
#include "fx_fault_tolerant.h"
|
||||
|
||||
|
||||
#ifdef FX_ENABLE_FAULT_TOLERANT
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _fx_fault_tolerant_write_log_file PORTABLE C */
|
||||
/* 6.1 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function writes data of one sector of fault tolerant data */
|
||||
/* from memory to log file in file system. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* media_ptr Media control block pointer */
|
||||
/* relative_sector Relative sector number of the */
|
||||
/* log file to write to */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* return status */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* _fx_utility_logical_sector_write Write a logical sector */
|
||||
/* _fx_utility_logical_sector_flush Flush written logical sectors */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* _fx_fault_tolerant_cleanup_FAT_chain */
|
||||
/* _fx_fault_tolerant_reset_log_file */
|
||||
/* _fx_fault_tolerant_set_FAT_chain */
|
||||
/* _fx_fault_tolerant_transaction_end */
|
||||
/* */
|
||||
/* 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_fault_tolerant_write_log_file(FX_MEDIA *media_ptr, ULONG relative_sector)
|
||||
{
|
||||
UINT status;
|
||||
ULONG start_sector;
|
||||
|
||||
/* Calculate the start sector of log file. */
|
||||
start_sector = (media_ptr -> fx_media_fault_tolerant_start_cluster - FX_FAT_ENTRY_START) *
|
||||
media_ptr -> fx_media_sectors_per_cluster +
|
||||
media_ptr -> fx_media_data_sector_start;
|
||||
|
||||
|
||||
/* Write sector directly. */
|
||||
status = _fx_utility_logical_sector_write(media_ptr, (ULONG64) (start_sector + relative_sector),
|
||||
media_ptr -> fx_media_fault_tolerant_memory_buffer +
|
||||
media_ptr -> fx_media_bytes_per_sector * relative_sector,
|
||||
((ULONG) 1), FX_DATA_SECTOR);
|
||||
|
||||
/* Check for a bad status. */
|
||||
if (status != FX_SUCCESS)
|
||||
{
|
||||
|
||||
/* Return the bad status. */
|
||||
return(status);
|
||||
}
|
||||
|
||||
/* Flush the internal logical sector cache. */
|
||||
status = _fx_utility_logical_sector_flush(media_ptr, (ULONG64) start_sector, ((ULONG64) 1), FX_FALSE);
|
||||
|
||||
FX_FAULT_TOLERANT_WRITE_LOG_FILE_EXTENSION
|
||||
|
||||
/* Return the status. */
|
||||
return(status);
|
||||
}
|
||||
#endif /* FX_ENABLE_FAULT_TOLERANT */
|
||||
|
||||
@@ -0,0 +1,84 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** FileX Component */
|
||||
/** */
|
||||
/** File */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
#define FX_SOURCE_CODE
|
||||
|
||||
|
||||
/* Include necessary system files. */
|
||||
|
||||
#include "fx_api.h"
|
||||
#include "fx_file.h"
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _fx_file_allocate PORTABLE C */
|
||||
/* 6.1 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function attempts to allocate the number of consecutive */
|
||||
/* clusters required to satisfy the user's request. If there are */
|
||||
/* enough clusters, the clusters are allocated and linked to the file. */
|
||||
/* Otherwise, if there are not enough consecutive clusters, an error */
|
||||
/* code is returned to the caller. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* file_ptr File control block pointer */
|
||||
/* size Number of bytes to allocate */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* return status */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* _fx_file_extended_allocate Allocate the clusters */
|
||||
/* */
|
||||
/* 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), and */
|
||||
/* Added conditional to */
|
||||
/* disable one line function, */
|
||||
/* resulting in version 6.1 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
#ifndef FX_DISABLE_ONE_LINE_FUNCTION
|
||||
UINT _fx_file_allocate(FX_FILE *file_ptr, ULONG size)
|
||||
{
|
||||
|
||||
return(_fx_file_extended_allocate(file_ptr, (ULONG64)size));
|
||||
}
|
||||
#endif /* FX_DISABLE_ONE_LINE_FUNCTION */
|
||||
@@ -0,0 +1,158 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** FileX Component */
|
||||
/** */
|
||||
/** File */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
#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"
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _fx_file_attributes_read PORTABLE C */
|
||||
/* 6.1 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function first attempts to find the specified file. If found, */
|
||||
/* the attribute read request is valid and the directory entry will be */
|
||||
/* in order to pickup the file's attributes. Otherwise, if the file */
|
||||
/* is not found, the appropriate error code is returned to the caller. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* media_ptr Media control block pointer */
|
||||
/* file_name File name pointer */
|
||||
/* attributes_ptr Return attributes pointer */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* return status */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* _fx_directory_search Search for the file name in */
|
||||
/* the directory structure */
|
||||
/* */
|
||||
/* 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_file_attributes_read(FX_MEDIA *media_ptr, CHAR *file_name, UINT *attributes_ptr)
|
||||
{
|
||||
|
||||
UINT status;
|
||||
FX_DIR_ENTRY dir_entry;
|
||||
|
||||
#ifdef TX_ENABLE_EVENT_TRACE
|
||||
TX_TRACE_BUFFER_ENTRY *trace_event;
|
||||
ULONG trace_timestamp;
|
||||
#endif
|
||||
UCHAR not_a_file_attr;
|
||||
|
||||
|
||||
#ifndef FX_MEDIA_STATISTICS_DISABLE
|
||||
|
||||
/* Increment the number of times this service has been called. */
|
||||
media_ptr -> fx_media_file_attributes_reads++;
|
||||
#endif
|
||||
|
||||
/* Setup pointer to media name buffer. */
|
||||
dir_entry.fx_dir_entry_name = media_ptr -> fx_media_name_buffer + FX_MAX_LONG_NAME_LEN;
|
||||
|
||||
/* Clear the short name string. */
|
||||
dir_entry.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);
|
||||
}
|
||||
|
||||
not_a_file_attr = FX_DIRECTORY | FX_VOLUME;
|
||||
|
||||
/* If trace is enabled, insert this event into the trace buffer. */
|
||||
FX_TRACE_IN_LINE_INSERT(FX_TRACE_FILE_ATTRIBUTES_READ, media_ptr, file_name, 0, 0, FX_TRACE_FILE_EVENTS, &trace_event, &trace_timestamp)
|
||||
|
||||
/* Protect against other threads accessing the media. */
|
||||
FX_PROTECT
|
||||
|
||||
/* Search the system for the supplied file name. */
|
||||
status = _fx_directory_search(media_ptr, file_name, &dir_entry, FX_NULL, FX_NULL);
|
||||
|
||||
/* Determine if the search was successful. */
|
||||
if (status != FX_SUCCESS)
|
||||
{
|
||||
|
||||
/* Release media protection. */
|
||||
FX_UNPROTECT
|
||||
|
||||
/* Return the error code. */
|
||||
return(status);
|
||||
}
|
||||
|
||||
/* Check to make sure the found entry is a file. */
|
||||
if (dir_entry.fx_dir_entry_attributes & not_a_file_attr)
|
||||
{
|
||||
|
||||
/* Release media protection. */
|
||||
FX_UNPROTECT
|
||||
|
||||
/* Return the not a file error code. */
|
||||
return(FX_NOT_A_FILE);
|
||||
}
|
||||
|
||||
/* Place the current attributes into the destination. */
|
||||
*attributes_ptr = (UINT)dir_entry.fx_dir_entry_attributes;
|
||||
|
||||
/* Update the trace event with the attributes read. */
|
||||
FX_TRACE_EVENT_UPDATE(trace_event, trace_timestamp, FX_TRACE_FILE_ATTRIBUTES_READ, 0, 0, dir_entry.fx_dir_entry_attributes, 0)
|
||||
|
||||
/* Release media protection. */
|
||||
FX_UNPROTECT
|
||||
|
||||
/* File attribute read is complete, return successful status. */
|
||||
return(FX_SUCCESS);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,221 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** FileX Component */
|
||||
/** */
|
||||
/** File */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
#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_file_attributes_set PORTABLE C */
|
||||
/* 6.1 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function first attempts to find the specified file. If found, */
|
||||
/* the attribute set request is valid and the directory entry will be */
|
||||
/* modified with the new attributes. Otherwise, if the file is not */
|
||||
/* found, the appropriate error code is returned to the caller. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* media_ptr Media control block pointer */
|
||||
/* file_name File name pointer */
|
||||
/* attributes New file attributes */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* return status */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* _fx_directory_entry_write Write the new directory entry */
|
||||
/* _fx_directory_search Search for the file name in */
|
||||
/* the directory structure */
|
||||
/* _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_file_attributes_set(FX_MEDIA *media_ptr, CHAR *file_name, UINT attributes)
|
||||
{
|
||||
|
||||
UINT status;
|
||||
ULONG open_count;
|
||||
FX_FILE *search_ptr;
|
||||
FX_DIR_ENTRY dir_entry;
|
||||
UCHAR not_a_file_attr;
|
||||
|
||||
|
||||
#ifndef FX_MEDIA_STATISTICS_DISABLE
|
||||
|
||||
/* Increment the number of times this service has been called. */
|
||||
media_ptr -> fx_media_file_attributes_sets++;
|
||||
#endif
|
||||
|
||||
/* Setup pointer to media name buffer. */
|
||||
dir_entry.fx_dir_entry_name = media_ptr -> fx_media_name_buffer + FX_MAX_LONG_NAME_LEN;
|
||||
|
||||
/* Clear the short name string. */
|
||||
dir_entry.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);
|
||||
}
|
||||
not_a_file_attr = FX_DIRECTORY | FX_VOLUME;
|
||||
|
||||
/* If trace is enabled, insert this event into the trace buffer. */
|
||||
FX_TRACE_IN_LINE_INSERT(FX_TRACE_FILE_ATTRIBUTES_SET, media_ptr, file_name, attributes, 0, FX_TRACE_FILE_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);
|
||||
}
|
||||
|
||||
/* Search the system for the supplied file name. */
|
||||
status = _fx_directory_search(media_ptr, file_name, &dir_entry, FX_NULL, FX_NULL);
|
||||
|
||||
/* Determine if the search was successful. */
|
||||
if (status != FX_SUCCESS)
|
||||
{
|
||||
|
||||
/* Release media protection. */
|
||||
FX_UNPROTECT
|
||||
|
||||
/* Return the error code. */
|
||||
return(status);
|
||||
}
|
||||
|
||||
/* Check to make sure the found entry is a file. */
|
||||
if (dir_entry.fx_dir_entry_attributes & not_a_file_attr)
|
||||
{
|
||||
|
||||
/* Release media protection. */
|
||||
FX_UNPROTECT
|
||||
|
||||
/* Return the not a file error code. */
|
||||
return(FX_NOT_A_FILE);
|
||||
}
|
||||
|
||||
/* Search the opened files to see if this file is currently
|
||||
opened. */
|
||||
open_count = media_ptr -> fx_media_opened_file_count;
|
||||
search_ptr = media_ptr -> fx_media_opened_file_list;
|
||||
while (open_count)
|
||||
{
|
||||
|
||||
/* Look at each opened file to see if the same file is opened. */
|
||||
if ((search_ptr -> fx_file_dir_entry.fx_dir_entry_log_sector == dir_entry.fx_dir_entry_log_sector) &&
|
||||
(search_ptr -> fx_file_dir_entry.fx_dir_entry_byte_offset == dir_entry.fx_dir_entry_byte_offset))
|
||||
{
|
||||
|
||||
/* Release media protection. */
|
||||
FX_UNPROTECT
|
||||
|
||||
/* The file is currently open. */
|
||||
return(FX_ACCESS_ERROR);
|
||||
}
|
||||
|
||||
/* Adjust the pointer and decrement the search count. */
|
||||
search_ptr = search_ptr -> fx_file_opened_next;
|
||||
open_count--;
|
||||
}
|
||||
|
||||
/* Place the new attributes in the directory entry. */
|
||||
dir_entry.fx_dir_entry_attributes = (UCHAR)attributes;
|
||||
|
||||
#ifdef FX_ENABLE_FAULT_TOLERANT
|
||||
/* Start transaction. */
|
||||
_fx_fault_tolerant_transaction_start(media_ptr);
|
||||
#endif /* FX_ENABLE_FAULT_TOLERANT */
|
||||
|
||||
/* Now write out the 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
|
||||
|
||||
/* File attribute set is complete, return status. */
|
||||
return(status);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,97 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** FileX Component */
|
||||
/** */
|
||||
/** File */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
#define FX_SOURCE_CODE
|
||||
|
||||
|
||||
/* Include necessary system files. */
|
||||
|
||||
#include "fx_api.h"
|
||||
#include "fx_file.h"
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _fx_file_best_effort_allocate PORTABLE C */
|
||||
/* 6.1 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function attempts to allocate the number of consecutive */
|
||||
/* clusters required to satisfy the user's request. If there are not */
|
||||
/* enough clusters, the largest set of clusters are allocated and */
|
||||
/* linked to the file. If there are no free clusters, an error */
|
||||
/* code is returned to the caller. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* file_ptr File control block pointer */
|
||||
/* size Number of bytes to allocate */
|
||||
/* actual_size_allocated Number of bytes allocated */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* return status */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* _fx_file_extended_best_effort_allocate */
|
||||
/* Allocate the largest set of */
|
||||
/* clusters */
|
||||
/* */
|
||||
/* 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_file_best_effort_allocate(FX_FILE *file_ptr, ULONG size, ULONG *actual_size_allocated)
|
||||
{
|
||||
|
||||
UINT status;
|
||||
ULONG64 temp_actual_size_allocated;
|
||||
|
||||
/* Call actual best effort file allocate service. */
|
||||
status = _fx_file_extended_best_effort_allocate(file_ptr, (ULONG64)size, &temp_actual_size_allocated);
|
||||
|
||||
/* Check status. */
|
||||
if (status == FX_SUCCESS)
|
||||
{
|
||||
*actual_size_allocated = (ULONG)temp_actual_size_allocated;
|
||||
}
|
||||
|
||||
/* Return status to the caller. */
|
||||
return(status);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,186 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** FileX Component */
|
||||
/** */
|
||||
/** File */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
#define FX_SOURCE_CODE
|
||||
|
||||
|
||||
/* Include necessary system files. */
|
||||
|
||||
#include "fx_api.h"
|
||||
#include "fx_system.h"
|
||||
#include "fx_file.h"
|
||||
#include "fx_utility.h"
|
||||
#include "fx_directory.h"
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _fx_file_close PORTABLE C */
|
||||
/* 6.1 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function closes the specified file. If the file was written */
|
||||
/* to this function will also write the directory entry (with the new */
|
||||
/* size and time/date stamp) out to disk. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* file_ptr File control block pointer */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* return status */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* _fx_directory_entry_write Write the directory entry */
|
||||
/* */
|
||||
/* 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_file_close(FX_FILE *file_ptr)
|
||||
{
|
||||
|
||||
UINT status;
|
||||
FX_MEDIA *media_ptr;
|
||||
FX_INT_SAVE_AREA
|
||||
|
||||
|
||||
/* First, determine if the file is still open. */
|
||||
if (file_ptr -> fx_file_id != FX_FILE_ID)
|
||||
{
|
||||
|
||||
/* Return the file not open error status. */
|
||||
return(FX_NOT_OPEN);
|
||||
}
|
||||
|
||||
/* Setup a pointer to the associated media. */
|
||||
media_ptr = file_ptr -> fx_file_media_ptr;
|
||||
|
||||
#ifndef FX_MEDIA_STATISTICS_DISABLE
|
||||
|
||||
/* Increment the number of times this service has been called. */
|
||||
media_ptr -> fx_media_file_closes++;
|
||||
#endif
|
||||
|
||||
/* If trace is enabled, insert this event into the trace buffer. */
|
||||
FX_TRACE_IN_LINE_INSERT(FX_TRACE_FILE_CLOSE, file_ptr, file_ptr -> fx_file_current_file_size, 0, 0, FX_TRACE_FILE_EVENTS, 0, 0)
|
||||
|
||||
/* Protect against other threads accessing the media. */
|
||||
FX_PROTECT
|
||||
/* If trace is enabled, unregister this object. */
|
||||
FX_TRACE_OBJECT_UNREGISTER(file_ptr)
|
||||
|
||||
/* Remove this file from the opened list for the media. */
|
||||
|
||||
/* See if the file is the only one on the open list for this media. */
|
||||
if (file_ptr == file_ptr -> fx_file_opened_next)
|
||||
{
|
||||
|
||||
/* Only opened file, just set the opened list to NULL. */
|
||||
media_ptr -> fx_media_opened_file_list = FX_NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* Otherwise, not the only opened file, link-up the neighbors. */
|
||||
(file_ptr -> fx_file_opened_next) -> fx_file_opened_previous =
|
||||
file_ptr -> fx_file_opened_previous;
|
||||
(file_ptr -> fx_file_opened_previous) -> fx_file_opened_next =
|
||||
file_ptr -> fx_file_opened_next;
|
||||
|
||||
/* See if we have to update the opened list head pointer. */
|
||||
if (media_ptr -> fx_media_opened_file_list == file_ptr)
|
||||
{
|
||||
|
||||
/* Yes, move the head pointer to the next opened file. */
|
||||
media_ptr -> fx_media_opened_file_list = file_ptr -> fx_file_opened_next;
|
||||
}
|
||||
}
|
||||
|
||||
/* Decrement the opened file counter. */
|
||||
media_ptr -> fx_media_opened_file_count--;
|
||||
|
||||
/* Finally, Indicate that this file is closed. */
|
||||
file_ptr -> fx_file_id = FX_FILE_CLOSED_ID;
|
||||
|
||||
/* Check to see if this file needs to have its directory entry written
|
||||
back to the media. */
|
||||
if ((file_ptr -> fx_file_open_mode == FX_OPEN_FOR_WRITE) &&
|
||||
(file_ptr -> fx_file_modified))
|
||||
{
|
||||
|
||||
/* Lockout interrupts for time/date access. */
|
||||
FX_DISABLE_INTS
|
||||
|
||||
/* Set the new time and date. */
|
||||
file_ptr -> fx_file_dir_entry.fx_dir_entry_time = _fx_system_time;
|
||||
file_ptr -> fx_file_dir_entry.fx_dir_entry_date = _fx_system_date;
|
||||
|
||||
/* Set the last access date. */
|
||||
file_ptr -> fx_file_dir_entry.fx_dir_entry_last_accessed_date = _fx_system_date;
|
||||
|
||||
/* Restore interrupts. */
|
||||
FX_RESTORE_INTS
|
||||
|
||||
/* Copy the new file size into the directory entry. */
|
||||
file_ptr -> fx_file_dir_entry.fx_dir_entry_file_size =
|
||||
file_ptr -> fx_file_current_file_size;
|
||||
|
||||
/* Write the directory entry to the media. */
|
||||
status = _fx_directory_entry_write(media_ptr, &(file_ptr -> fx_file_dir_entry));
|
||||
|
||||
/* Check for a good status. */
|
||||
if (status != FX_SUCCESS)
|
||||
{
|
||||
|
||||
/* Release media protection. */
|
||||
FX_UNPROTECT
|
||||
|
||||
/* Error writing the directory. */
|
||||
return(status);
|
||||
}
|
||||
}
|
||||
|
||||
/* Release media protection. */
|
||||
FX_UNPROTECT
|
||||
|
||||
/* Return status to the caller. */
|
||||
return(FX_SUCCESS);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,303 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** FileX Component */
|
||||
/** */
|
||||
/** File */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
#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_file_create PORTABLE C */
|
||||
/* 6.1 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function first attempts to find the specified file. 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, a */
|
||||
/* file of 0 bytes will be created. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* media_ptr Media control block pointer */
|
||||
/* file_name File name */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* return status */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* _fx_directory_entry_write Write the new directory entry */
|
||||
/* _fx_directory_name_extract Extract directory name */
|
||||
/* _fx_directory_search Search for the file name in */
|
||||
/* the directory structure */
|
||||
/* _fx_directory_free_search Search for a free directory */
|
||||
/* entry */
|
||||
/* _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_file_create(FX_MEDIA *media_ptr, CHAR *file_name)
|
||||
{
|
||||
|
||||
FX_INT_SAVE_AREA
|
||||
|
||||
UINT status;
|
||||
CHAR *name_ptr;
|
||||
UINT i;
|
||||
CHAR *work_ptr;
|
||||
FX_DIR_ENTRY dir_entry;
|
||||
FX_DIR_ENTRY search_directory;
|
||||
|
||||
|
||||
#ifndef FX_MEDIA_STATISTICS_DISABLE
|
||||
|
||||
/* Increment the number of times this service has been called. */
|
||||
media_ptr -> fx_media_file_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 *)file_name;
|
||||
while (*work_ptr)
|
||||
{
|
||||
|
||||
/* 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 another 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 strings. */
|
||||
dir_entry.fx_dir_entry_short_name[0] = 0;
|
||||
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_FILE_CREATE, media_ptr, file_name, 0, 0, FX_TRACE_FILE_EVENTS, 0, 0)
|
||||
|
||||
/* Protect against other threads accessing the media. */
|
||||
FX_PROTECT
|
||||
|
||||
#ifdef FX_ENABLE_FAULT_TOLERANT
|
||||
/* Start transaction. */
|
||||
_fx_fault_tolerant_transaction_start(media_ptr);
|
||||
#endif /* FX_ENABLE_FAULT_TOLERANT */
|
||||
|
||||
/* Check for write protect at the media level (set by driver). */
|
||||
if (media_ptr -> fx_media_driver_write_protect)
|
||||
{
|
||||
|
||||
#ifdef FX_ENABLE_FAULT_TOLERANT
|
||||
FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
|
||||
#endif /* FX_ENABLE_FAULT_TOLERANT */
|
||||
|
||||
/* Release media protection. */
|
||||
FX_UNPROTECT
|
||||
|
||||
/* Return write protect error. */
|
||||
return(FX_WRITE_PROTECT);
|
||||
}
|
||||
|
||||
/* Search the system for the supplied file name. */
|
||||
status = _fx_directory_search(media_ptr, file_name, &dir_entry, &search_directory, &name_ptr);
|
||||
|
||||
/* 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
|
||||
|
||||
/* File found - Return the error code. */
|
||||
return(FX_ALREADY_CREATED);
|
||||
}
|
||||
|
||||
/* Determine if there is anything left after the name. */
|
||||
if (_fx_directory_name_extract(name_ptr, &dir_entry.fx_dir_entry_name[0]))
|
||||
{
|
||||
|
||||
#ifdef FX_ENABLE_FAULT_TOLERANT
|
||||
FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
|
||||
#endif /* FX_ENABLE_FAULT_TOLERANT */
|
||||
|
||||
/* Release media protection. */
|
||||
FX_UNPROTECT
|
||||
|
||||
/* Extra information after the file name, return an invalid path
|
||||
error. */
|
||||
return(FX_INVALID_PATH);
|
||||
}
|
||||
|
||||
|
||||
/* Find a free slot for the new file. */
|
||||
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);
|
||||
}
|
||||
|
||||
/* Populate the directory entry. */
|
||||
|
||||
/* Isolate the file name. */
|
||||
_fx_directory_name_extract(name_ptr, &dir_entry.fx_dir_entry_name[0]);
|
||||
|
||||
/* Disable 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_ARCHIVE;
|
||||
|
||||
/* Set file size to 0. */
|
||||
dir_entry.fx_dir_entry_file_size = 0;
|
||||
|
||||
|
||||
/* Set the cluster to NULL. */
|
||||
dir_entry.fx_dir_entry_cluster = FX_NULL;
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
|
||||
/* Now write out the 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
|
||||
|
||||
/* File create is complete, return status. */
|
||||
return(status);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,137 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** FileX Component */
|
||||
/** */
|
||||
/** File */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
#define FX_SOURCE_CODE
|
||||
|
||||
|
||||
/* Include necessary system files. */
|
||||
|
||||
#include "fx_api.h"
|
||||
#include "fx_directory.h"
|
||||
#include "fx_file.h"
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _fx_file_date_time_set PORTABLE C */
|
||||
/* 6.1 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function sets the specified file's date and time with the */
|
||||
/* values provided. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* media_ptr Media control block pointer */
|
||||
/* file_name File name pointer */
|
||||
/* year Year */
|
||||
/* month Month */
|
||||
/* day Day */
|
||||
/* hour Hour */
|
||||
/* minute Minute */
|
||||
/* second Second */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* return status */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* _fx_directory_search Search for the file name in */
|
||||
/* the directory structure */
|
||||
/* _fx_directory_entry_write Write the directory entry */
|
||||
/* */
|
||||
/* 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_file_date_time_set(FX_MEDIA *media_ptr, CHAR *file_name,
|
||||
UINT year, UINT month, UINT day, UINT hour, UINT minute, UINT second)
|
||||
{
|
||||
|
||||
UINT status;
|
||||
FX_DIR_ENTRY dir_entry;
|
||||
|
||||
|
||||
/* Setup pointer to media name buffer. */
|
||||
dir_entry.fx_dir_entry_name = media_ptr -> fx_media_name_buffer + FX_MAX_LONG_NAME_LEN;
|
||||
|
||||
/* Clear the short name string. */
|
||||
dir_entry.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_FILE_DATE_TIME_SET, media_ptr, file_name, year, month, FX_TRACE_FILE_EVENTS, 0, 0)
|
||||
|
||||
/* Protect against other threads accessing the media. */
|
||||
FX_PROTECT
|
||||
|
||||
/* Search the system for the supplied directory name. */
|
||||
status = _fx_directory_search(media_ptr, file_name, &dir_entry, FX_NULL, FX_NULL);
|
||||
|
||||
/* Determine if the search was successful. */
|
||||
if (status != FX_SUCCESS)
|
||||
{
|
||||
|
||||
/* Release media protection. */
|
||||
FX_UNPROTECT
|
||||
|
||||
/* Return the error code. */
|
||||
return(status);
|
||||
}
|
||||
|
||||
/* Set the new time and date. */
|
||||
dir_entry.fx_dir_entry_time = (hour << FX_HOUR_SHIFT) | (minute << FX_MINUTE_SHIFT) | (second / 2);
|
||||
dir_entry.fx_dir_entry_date = ((year - FX_BASE_YEAR) << FX_YEAR_SHIFT) | (month << FX_MONTH_SHIFT) | day;
|
||||
|
||||
/* Write the directory entry to the media. */
|
||||
status = _fx_directory_entry_write(media_ptr, &dir_entry);
|
||||
|
||||
/* Release media protection. */
|
||||
FX_UNPROTECT
|
||||
|
||||
/* Directory information write is complete, return status. */
|
||||
return(status);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,382 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** FileX Component */
|
||||
/** */
|
||||
/** File */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
#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_file_delete PORTABLE C */
|
||||
/* 6.1 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function first attempts to find the specified file. If found, */
|
||||
/* the delete request is valid and all of its clusters will be */
|
||||
/* released and its directory entry will be marked as available. */
|
||||
/* Otherwise, if the file is not found, the appropriate error code is */
|
||||
/* returned to the caller. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* media_ptr Media control block pointer */
|
||||
/* file_name File name pointer */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* return status */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* _fx_directory_entry_write Write the new directory entry */
|
||||
/* _fx_directory_search Search for the file name in */
|
||||
/* the directory structure */
|
||||
/* _fx_utility_FAT_entry_read Read a FAT entry */
|
||||
/* _fx_utility_FAT_entry_write Write a FAT entry */
|
||||
/* _fx_utility_FAT_flush Flush written FAT entries */
|
||||
/* _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 */
|
||||
/* _fx_fault_tolerant_set_FAT_chain Set data of FAT chain */
|
||||
/* */
|
||||
/* 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_file_delete(FX_MEDIA *media_ptr, CHAR *file_name)
|
||||
{
|
||||
|
||||
UINT status;
|
||||
ULONG cluster;
|
||||
ULONG contents;
|
||||
ULONG open_count;
|
||||
FX_FILE *search_ptr;
|
||||
ULONG cluster_count;
|
||||
FX_DIR_ENTRY dir_entry;
|
||||
UCHAR not_a_file_attr;
|
||||
|
||||
#ifndef FX_MEDIA_STATISTICS_DISABLE
|
||||
|
||||
/* Increment the number of times this service has been called. */
|
||||
media_ptr -> fx_media_file_deletes++;
|
||||
#endif
|
||||
|
||||
/* Setup pointer to media name buffer. */
|
||||
dir_entry.fx_dir_entry_name = media_ptr -> fx_media_name_buffer + FX_MAX_LONG_NAME_LEN;
|
||||
|
||||
/* Clear the short name string. */
|
||||
dir_entry.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_FILE_DELETE, media_ptr, file_name, 0, 0, FX_TRACE_FILE_EVENTS, 0, 0)
|
||||
|
||||
/* Protect against other threads accessing the media. */
|
||||
FX_PROTECT
|
||||
|
||||
#ifdef FX_ENABLE_FAULT_TOLERANT
|
||||
/* Start transaction. */
|
||||
_fx_fault_tolerant_transaction_start(media_ptr);
|
||||
#endif /* FX_ENABLE_FAULT_TOLERANT */
|
||||
|
||||
/* Check for write protect at the media level (set by driver). */
|
||||
if (media_ptr -> fx_media_driver_write_protect)
|
||||
{
|
||||
|
||||
#ifdef FX_ENABLE_FAULT_TOLERANT
|
||||
FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
|
||||
#endif /* FX_ENABLE_FAULT_TOLERANT */
|
||||
|
||||
/* Release media protection. */
|
||||
FX_UNPROTECT
|
||||
|
||||
/* Return write protect error. */
|
||||
return(FX_WRITE_PROTECT);
|
||||
}
|
||||
|
||||
/* Search the system for the supplied file name. */
|
||||
status = _fx_directory_search(media_ptr, file_name, &dir_entry, FX_NULL, FX_NULL);
|
||||
|
||||
/* 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);
|
||||
}
|
||||
|
||||
not_a_file_attr = FX_DIRECTORY | FX_VOLUME;
|
||||
|
||||
/* Check to make sure the found entry is a file. */
|
||||
if (dir_entry.fx_dir_entry_attributes & not_a_file_attr)
|
||||
{
|
||||
|
||||
#ifdef FX_ENABLE_FAULT_TOLERANT
|
||||
FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
|
||||
#endif /* FX_ENABLE_FAULT_TOLERANT */
|
||||
|
||||
/* Release media protection. */
|
||||
FX_UNPROTECT
|
||||
|
||||
/* Return the not a file error code. */
|
||||
return(FX_NOT_A_FILE);
|
||||
}
|
||||
|
||||
/* Check if the entry is read only */
|
||||
if (dir_entry.fx_dir_entry_attributes & (UCHAR)(FX_READ_ONLY))
|
||||
{
|
||||
#ifdef FX_ENABLE_FAULT_TOLERANT
|
||||
FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
|
||||
#endif /* FX_ENABLE_FAULT_TOLERANT */
|
||||
|
||||
/* Release media protection. */
|
||||
FX_UNPROTECT
|
||||
|
||||
/* Return the not a directory error code. */
|
||||
return(FX_WRITE_PROTECT);
|
||||
}
|
||||
|
||||
/* Search the opened files to see if this file is currently
|
||||
opened. */
|
||||
open_count = media_ptr -> fx_media_opened_file_count;
|
||||
search_ptr = media_ptr -> fx_media_opened_file_list;
|
||||
while (open_count)
|
||||
{
|
||||
|
||||
/* Look at each opened file to see if the same file is opened. */
|
||||
if ((search_ptr -> fx_file_dir_entry.fx_dir_entry_log_sector == dir_entry.fx_dir_entry_log_sector) &&
|
||||
(search_ptr -> fx_file_dir_entry.fx_dir_entry_byte_offset == dir_entry.fx_dir_entry_byte_offset))
|
||||
{
|
||||
|
||||
#ifdef FX_ENABLE_FAULT_TOLERANT
|
||||
FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
|
||||
#endif /* FX_ENABLE_FAULT_TOLERANT */
|
||||
|
||||
/* Release media protection. */
|
||||
FX_UNPROTECT
|
||||
|
||||
/* The file is currently open. */
|
||||
return(FX_ACCESS_ERROR);
|
||||
}
|
||||
|
||||
/* Adjust the pointer and decrement the search count. */
|
||||
search_ptr = search_ptr -> fx_file_opened_next;
|
||||
open_count--;
|
||||
}
|
||||
|
||||
/* Pickup the starting cluster of the file. */
|
||||
cluster = dir_entry.fx_dir_entry_cluster;
|
||||
|
||||
/* At this point, make the directory entry invalid in order to delete the file. */
|
||||
|
||||
#ifndef FX_MEDIA_DISABLE_SEARCH_CACHE
|
||||
|
||||
/* Invalidate the directory search saved information. */
|
||||
media_ptr -> fx_media_last_found_name[0] = FX_NULL;
|
||||
#endif
|
||||
|
||||
/* Mark the directory entry as available, while leaving the other
|
||||
information for the sake of posterity. */
|
||||
dir_entry.fx_dir_entry_name[0] = (CHAR)FX_DIR_ENTRY_FREE;
|
||||
dir_entry.fx_dir_entry_short_name[0] = (CHAR)FX_DIR_ENTRY_FREE;
|
||||
|
||||
/* Now write out the directory entry. */
|
||||
status = _fx_directory_entry_write(media_ptr, &dir_entry);
|
||||
|
||||
/* 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);
|
||||
}
|
||||
|
||||
/* Now that the directory entry is no longer valid and pointing at the chain of clusters,
|
||||
walk the chain of allocated FAT entries and mark each of them as free. */
|
||||
cluster_count = 0;
|
||||
|
||||
|
||||
#ifdef FX_ENABLE_FAULT_TOLERANT
|
||||
if (media_ptr -> fx_media_fault_tolerant_enabled)
|
||||
{
|
||||
|
||||
/* Note: Directory entries are already written to log files. FAT chain is updated as the last step.
|
||||
Since there are no others FAT entries written to the log. Therefore there is no need to set
|
||||
the flag FX_FRAULT_TOLERANT_STATE_SET_FAT_CHAIN here. */
|
||||
status = _fx_fault_tolerant_set_FAT_chain(media_ptr, FX_FALSE, 0,
|
||||
media_ptr -> fx_media_fat_last, cluster, media_ptr -> fx_media_fat_last);
|
||||
|
||||
/* 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);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
#endif /* FX_ENABLE_FAULT_TOLERANT */
|
||||
|
||||
/* Follow the link of FAT entries. */
|
||||
while ((cluster >= FX_FAT_ENTRY_START) && (cluster < media_ptr -> fx_media_fat_reserved))
|
||||
{
|
||||
|
||||
/* Increment the number of clusters. */
|
||||
cluster_count++;
|
||||
|
||||
|
||||
/* Read the current cluster entry from the FAT. */
|
||||
status = _fx_utility_FAT_entry_read(media_ptr, cluster, &contents);
|
||||
|
||||
/* Check the return value. */
|
||||
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 status. */
|
||||
return(status);
|
||||
}
|
||||
|
||||
if ((cluster == contents) || (cluster_count > media_ptr -> fx_media_total_clusters))
|
||||
{
|
||||
|
||||
#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(FX_FAT_READ_ERROR);
|
||||
}
|
||||
|
||||
|
||||
/* Make the current cluster available. */
|
||||
status = _fx_utility_FAT_entry_write(media_ptr, cluster, FX_FREE_CLUSTER);
|
||||
|
||||
/* Check the return value. */
|
||||
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 status. */
|
||||
return(status);
|
||||
}
|
||||
|
||||
/* Setup for the next cluster. */
|
||||
cluster = contents;
|
||||
}
|
||||
#ifdef FX_ENABLE_FAULT_TOLERANT
|
||||
}
|
||||
#endif /* FX_ENABLE_FAULT_TOLERANT */
|
||||
|
||||
/* Update the free clusters in the media control block. */
|
||||
media_ptr -> fx_media_available_clusters =
|
||||
media_ptr -> fx_media_available_clusters + cluster_count;
|
||||
|
||||
#ifdef FX_FAULT_TOLERANT
|
||||
|
||||
/* Flush the cached individual FAT entries */
|
||||
_fx_utility_FAT_flush(media_ptr);
|
||||
#endif
|
||||
|
||||
#ifdef FX_ENABLE_FAULT_TOLERANT
|
||||
|
||||
/* End transaction. */
|
||||
status = _fx_fault_tolerant_transaction_end(media_ptr);
|
||||
#endif /* FX_ENABLE_FAULT_TOLERANT */
|
||||
|
||||
/* Release media protection. */
|
||||
FX_UNPROTECT
|
||||
|
||||
/* File delete is complete, return status. */
|
||||
return(status);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,543 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** FileX Component */
|
||||
/** */
|
||||
/** File */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
#define FX_SOURCE_CODE
|
||||
|
||||
|
||||
/* Include necessary system files. */
|
||||
|
||||
#include "fx_api.h"
|
||||
#include "fx_system.h"
|
||||
#include "fx_file.h"
|
||||
#include "fx_utility.h"
|
||||
#include "fx_directory.h"
|
||||
#ifdef FX_ENABLE_FAULT_TOLERANT
|
||||
#include "fx_fault_tolerant.h"
|
||||
#endif /* FX_ENABLE_FAULT_TOLERANT */
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _fx_file_extended_allocate PORTABLE C */
|
||||
/* 6.1 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function attempts to allocate the number of consecutive */
|
||||
/* clusters required to satisfy the user's request. If there are */
|
||||
/* enough clusters, the clusters are allocated and linked to the file. */
|
||||
/* Otherwise, if there are not enough consecutive clusters, an error */
|
||||
/* code is returned to the caller. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* file_ptr File control block pointer */
|
||||
/* size Number of bytes to allocate */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* return status */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* _fx_directory_entry_write Update directory entry */
|
||||
/* _fx_utility_FAT_entry_read Read a FAT entry */
|
||||
/* _fx_utility_FAT_entry_write Write a FAT entry */
|
||||
/* _fx_utility_FAT_flush Flush written FAT entries */
|
||||
/* _fx_utility_logical_sector_flush Flush the written log 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 */
|
||||
/* _fx_fault_tolerant_set_FAT_chain Set data of FAT chain */
|
||||
/* */
|
||||
/* 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_file_extended_allocate(FX_FILE *file_ptr, ULONG64 size)
|
||||
{
|
||||
|
||||
UINT status;
|
||||
ULONG i;
|
||||
UINT found;
|
||||
ULONG bytes_per_cluster;
|
||||
ULONG FAT_index;
|
||||
ULONG FAT_value;
|
||||
ULONG clusters;
|
||||
FX_MEDIA *media_ptr;
|
||||
|
||||
#ifdef TX_ENABLE_EVENT_TRACE
|
||||
TX_TRACE_BUFFER_ENTRY *trace_event;
|
||||
ULONG trace_timestamp;
|
||||
#endif
|
||||
|
||||
|
||||
/* First, determine if the file is still open. */
|
||||
if (file_ptr -> fx_file_id != FX_FILE_ID)
|
||||
{
|
||||
|
||||
/* Return the file not open error status. */
|
||||
return(FX_NOT_OPEN);
|
||||
}
|
||||
|
||||
/* Setup pointer to media structure. */
|
||||
media_ptr = file_ptr -> fx_file_media_ptr;
|
||||
|
||||
#ifndef FX_MEDIA_STATISTICS_DISABLE
|
||||
|
||||
/* Increment the number of times this service has been called. */
|
||||
media_ptr -> fx_media_file_allocates++;
|
||||
#endif
|
||||
|
||||
/* Make sure this file is open for writing. */
|
||||
if (file_ptr -> fx_file_open_mode != FX_OPEN_FOR_WRITE)
|
||||
{
|
||||
|
||||
/* Return the access error exception - a write was attempted from
|
||||
a file opened for reading! */
|
||||
return(FX_ACCESS_ERROR);
|
||||
}
|
||||
|
||||
/* Determine if the requested allocation is for zero bytes. */
|
||||
if (size == 0)
|
||||
{
|
||||
|
||||
/* Return a successful completion - nothing needs to be done. */
|
||||
return(FX_SUCCESS);
|
||||
}
|
||||
|
||||
/* Setup pointer to associated media control block. */
|
||||
media_ptr = file_ptr -> fx_file_media_ptr;
|
||||
|
||||
/* If trace is enabled, insert this event into the trace buffer. */
|
||||
FX_TRACE_IN_LINE_INSERT(FX_TRACE_FILE_ALLOCATE, file_ptr, size, file_ptr -> fx_file_current_available_size, 0, FX_TRACE_FILE_EVENTS, &trace_event, &trace_timestamp)
|
||||
|
||||
/* Protect against other threads accessing the media. */
|
||||
FX_PROTECT
|
||||
|
||||
#ifdef FX_ENABLE_FAULT_TOLERANT
|
||||
/* Start transaction. */
|
||||
_fx_fault_tolerant_transaction_start(media_ptr);
|
||||
#endif /* FX_ENABLE_FAULT_TOLERANT */
|
||||
|
||||
/* Check for write protect at the media level (set by driver). */
|
||||
if (media_ptr -> fx_media_driver_write_protect)
|
||||
{
|
||||
|
||||
#ifdef FX_ENABLE_FAULT_TOLERANT
|
||||
FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
|
||||
#endif /* FX_ENABLE_FAULT_TOLERANT */
|
||||
|
||||
/* Release media protection. */
|
||||
FX_UNPROTECT
|
||||
|
||||
/* Return write protect error. */
|
||||
return(FX_WRITE_PROTECT);
|
||||
}
|
||||
|
||||
/* Calculate the number of bytes per cluster. */
|
||||
bytes_per_cluster = ((ULONG)media_ptr -> fx_media_bytes_per_sector) *
|
||||
((ULONG)media_ptr -> fx_media_sectors_per_cluster);
|
||||
|
||||
/* Check for invalid value. */
|
||||
if (bytes_per_cluster == 0)
|
||||
{
|
||||
|
||||
#ifdef FX_ENABLE_FAULT_TOLERANT
|
||||
FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
|
||||
#endif /* FX_ENABLE_FAULT_TOLERANT */
|
||||
|
||||
/* Release media protection. */
|
||||
FX_UNPROTECT
|
||||
|
||||
/* Invalid media, return error. */
|
||||
return(FX_MEDIA_INVALID);
|
||||
}
|
||||
|
||||
/* Calculate the number of consecutive clusters needed to satisfy this
|
||||
request. */
|
||||
clusters = (ULONG)(((size + bytes_per_cluster - 1) / bytes_per_cluster));
|
||||
|
||||
/* Determine if cluster count is 0. */
|
||||
if (clusters == 0)
|
||||
{
|
||||
|
||||
#ifdef FX_ENABLE_FAULT_TOLERANT
|
||||
FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
|
||||
#endif /* FX_ENABLE_FAULT_TOLERANT */
|
||||
|
||||
/* Release media protection. */
|
||||
FX_UNPROTECT
|
||||
|
||||
/* Size overflow when rounding to the next cluster, return an error status. */
|
||||
return(FX_NO_MORE_SPACE);
|
||||
}
|
||||
|
||||
/* Determine if there are enough available clusters on the media. */
|
||||
if (clusters > media_ptr -> fx_media_available_clusters)
|
||||
{
|
||||
|
||||
#ifdef FX_ENABLE_FAULT_TOLERANT
|
||||
FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
|
||||
#endif /* FX_ENABLE_FAULT_TOLERANT */
|
||||
|
||||
/* Release media protection. */
|
||||
FX_UNPROTECT
|
||||
|
||||
/* Not enough clusters, return an error status. */
|
||||
return(FX_NO_MORE_SPACE);
|
||||
}
|
||||
|
||||
/* Determine if the requested file allocation would exceed the physical limit of the file. */
|
||||
if (((file_ptr -> fx_file_current_available_size + (((ULONG64) clusters) * ((ULONG64) bytes_per_cluster))) < file_ptr -> fx_file_current_available_size) ||
|
||||
((file_ptr -> fx_file_current_available_size + (((ULONG64) clusters) * ((ULONG64) bytes_per_cluster))) > 0xFFFFFFFFULL))
|
||||
{
|
||||
|
||||
#ifdef FX_ENABLE_FAULT_TOLERANT
|
||||
FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
|
||||
#endif /* FX_ENABLE_FAULT_TOLERANT */
|
||||
|
||||
/* Release media protection. */
|
||||
FX_UNPROTECT
|
||||
|
||||
/* Return the no more space error, since the new file size would be larger than
|
||||
the 32-bit field to represent it in the file's directory entry. */
|
||||
return(FX_NO_MORE_SPACE);
|
||||
}
|
||||
|
||||
/* Now we need to find the consecutive clusters. */
|
||||
FAT_index = FX_FAT_ENTRY_START;
|
||||
found = FX_FALSE;
|
||||
|
||||
|
||||
while (FAT_index <= (media_ptr -> fx_media_total_clusters - clusters + FX_FAT_ENTRY_START))
|
||||
{
|
||||
|
||||
/* Determine if enough consecutive FAT entries are available. */
|
||||
i = 0;
|
||||
|
||||
|
||||
do
|
||||
{
|
||||
|
||||
/* Read a FAT entry. */
|
||||
status = _fx_utility_FAT_entry_read(media_ptr, (FAT_index + i), &FAT_value);
|
||||
|
||||
/* Check for a successful 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 error status. */
|
||||
return(status);
|
||||
}
|
||||
|
||||
/* Determine if the entry is free. */
|
||||
if (FAT_value != FX_FREE_CLUSTER)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
/* Otherwise, increment the consecutive FAT indices. */
|
||||
i++;
|
||||
} while (i < clusters);
|
||||
|
||||
/* Determine if we found enough FAT entries. */
|
||||
if (i >= clusters)
|
||||
{
|
||||
|
||||
/* Yes, we have found enough FAT entries - set the found
|
||||
flag and get out of this loop. */
|
||||
found = FX_TRUE;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Position to the next possibly free FAT entry. */
|
||||
FAT_index = FAT_index + i + 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Determine if we found enough consecutive clusters to satisfy the
|
||||
request. */
|
||||
if (found)
|
||||
{
|
||||
|
||||
#ifdef FX_ENABLE_FAULT_TOLERANT
|
||||
if (media_ptr -> fx_media_fault_tolerant_enabled)
|
||||
{
|
||||
|
||||
/* Record the action that is about to take place. This information
|
||||
would aid the undo process should fault condition happens. */
|
||||
media_ptr -> fx_media_fault_tolerant_state |= FX_FAULT_TOLERANT_STATE_SET_FAT_CHAIN;
|
||||
_fx_fault_tolerant_set_FAT_chain(media_ptr, FX_FALSE, file_ptr -> fx_file_last_physical_cluster,
|
||||
FAT_index, media_ptr -> fx_media_fat_last, media_ptr -> fx_media_fat_last);
|
||||
}
|
||||
#endif /* FX_ENABLE_FAULT_TOLERANT */
|
||||
|
||||
|
||||
/* Update the link pointers in the new clusters. */
|
||||
for (i = 0; i < (clusters - 1); i++)
|
||||
{
|
||||
|
||||
/* Update the cluster links. Since the allocation is
|
||||
sequential, we just have to link each FAT entry to the
|
||||
next one. */
|
||||
status = _fx_utility_FAT_entry_write(media_ptr, FAT_index + i, FAT_index + i + 1);
|
||||
|
||||
/* 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 error status. */
|
||||
return(status);
|
||||
}
|
||||
}
|
||||
|
||||
/* Now place an EOF in the last cluster entry. */
|
||||
status = _fx_utility_FAT_entry_write(media_ptr, FAT_index + clusters - 1, 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 error status. */
|
||||
return(status);
|
||||
}
|
||||
|
||||
#ifdef FX_FAULT_TOLERANT
|
||||
|
||||
/* Flush the cached individual FAT entries */
|
||||
_fx_utility_FAT_flush(media_ptr);
|
||||
|
||||
#endif
|
||||
|
||||
/* Actually link up the new clusters to the file. */
|
||||
|
||||
/* Determine if there are already clusters allocated for this file. */
|
||||
if (file_ptr -> fx_file_total_clusters)
|
||||
{
|
||||
|
||||
/* Linkup the last cluster. */
|
||||
status = _fx_utility_FAT_entry_write(media_ptr,
|
||||
file_ptr -> fx_file_last_physical_cluster, FAT_index);
|
||||
|
||||
/* 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 error status. */
|
||||
return(status);
|
||||
}
|
||||
|
||||
/* Determine if we are adding a sector after a write filled the previously
|
||||
allocated cluster exactly. */
|
||||
if ((file_ptr -> fx_file_current_relative_sector >=
|
||||
(media_ptr -> fx_media_sectors_per_cluster - 1)) &&
|
||||
(file_ptr -> fx_file_current_logical_offset >=
|
||||
media_ptr -> fx_media_bytes_per_sector))
|
||||
{
|
||||
|
||||
/* Yes, we need to adjust all of the pertinent file parameters for
|
||||
access into this newly allocated cluster. */
|
||||
file_ptr -> fx_file_current_physical_cluster = FAT_index;
|
||||
file_ptr -> fx_file_current_relative_cluster++;
|
||||
file_ptr -> fx_file_current_relative_sector = 0;
|
||||
file_ptr -> fx_file_current_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));
|
||||
file_ptr -> fx_file_current_logical_offset = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* These new clusters are also the first! Setup the initial
|
||||
file parameters. */
|
||||
file_ptr -> fx_file_first_physical_cluster = FAT_index;
|
||||
file_ptr -> fx_file_current_physical_cluster = file_ptr -> fx_file_first_physical_cluster;
|
||||
file_ptr -> fx_file_current_relative_cluster = 0;
|
||||
file_ptr -> fx_file_current_logical_sector = ((ULONG)media_ptr -> fx_media_data_sector_start) +
|
||||
(((ULONG64)(file_ptr -> fx_file_first_physical_cluster - FX_FAT_ENTRY_START)) *
|
||||
((ULONG)media_ptr -> fx_media_sectors_per_cluster));
|
||||
file_ptr -> fx_file_current_logical_offset = 0;
|
||||
file_ptr -> fx_file_current_file_offset = 0;
|
||||
|
||||
/* Update the first cluster in the directory entry. */
|
||||
file_ptr -> fx_file_dir_entry.fx_dir_entry_cluster = FAT_index;
|
||||
}
|
||||
|
||||
/* Remember the last physical cluster. */
|
||||
file_ptr -> fx_file_last_physical_cluster = FAT_index + clusters - 1;
|
||||
|
||||
|
||||
/* Check for wrap-around when updating the available size. */
|
||||
/* Update the available size. */
|
||||
file_ptr -> fx_file_current_available_size =
|
||||
file_ptr -> fx_file_current_available_size + (bytes_per_cluster * clusters);
|
||||
|
||||
|
||||
/* Increment the total clusters for this file. */
|
||||
file_ptr -> fx_file_total_clusters =
|
||||
file_ptr -> fx_file_total_clusters + clusters;
|
||||
|
||||
/* Decrease the available clusters on the media. */
|
||||
media_ptr -> fx_media_available_clusters =
|
||||
media_ptr -> fx_media_available_clusters - clusters;
|
||||
|
||||
#if defined(FX_UPDATE_FILE_SIZE_ON_ALLOCATE) || defined(FX_ENABLE_FAULT_TOLERANT)
|
||||
|
||||
/* Set the file size the current size plus what what was added. */
|
||||
file_ptr -> fx_file_current_file_size += size;
|
||||
|
||||
/* Copy the new file size into the directory entry. */
|
||||
file_ptr -> fx_file_dir_entry.fx_dir_entry_file_size = file_ptr -> fx_file_current_file_size;
|
||||
#endif
|
||||
|
||||
#ifdef FX_ENABLE_FAULT_TOLERANT
|
||||
if (media_ptr -> fx_media_fault_tolerant_enabled)
|
||||
{
|
||||
|
||||
/* Clear undo phase. */
|
||||
media_ptr -> fx_media_fault_tolerant_state &= (UCHAR)(~FX_FAULT_TOLERANT_STATE_SET_FAT_CHAIN & 0xff);
|
||||
}
|
||||
#endif /* FX_ENABLE_FAULT_TOLERANT */
|
||||
|
||||
/* Update the trace event with the new size. */
|
||||
FX_TRACE_EVENT_UPDATE(trace_event, trace_timestamp, FX_TRACE_FILE_ALLOCATE, 0, 0, 0, file_ptr -> fx_file_current_file_size);
|
||||
|
||||
/* Write the directory entry to the media. */
|
||||
status = _fx_directory_entry_write(media_ptr, &(file_ptr -> fx_file_dir_entry));
|
||||
|
||||
/* Check for a good 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 error status. */
|
||||
return(status);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
#ifdef FX_ENABLE_FAULT_TOLERANT
|
||||
FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
|
||||
#endif /* FX_ENABLE_FAULT_TOLERANT */
|
||||
|
||||
/* Release media protection. */
|
||||
FX_UNPROTECT
|
||||
|
||||
/* Not enough contiguous space on the media. Return error status. */
|
||||
return(FX_NO_MORE_SPACE);
|
||||
}
|
||||
|
||||
#ifdef FX_FAULT_TOLERANT
|
||||
|
||||
/* Flush the cached individual FAT entries */
|
||||
_fx_utility_FAT_flush(media_ptr);
|
||||
#endif
|
||||
|
||||
/* Flush the internal logical sector cache. */
|
||||
status = _fx_utility_logical_sector_flush(media_ptr, ((ULONG64) 1), (ULONG64)(media_ptr -> fx_media_sectors_per_FAT), FX_FALSE);
|
||||
|
||||
#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);
|
||||
}
|
||||
|
||||
if (media_ptr -> fx_media_fault_tolerant_enabled)
|
||||
{
|
||||
|
||||
/* Copy the new file size into the directory entry. */
|
||||
file_ptr -> fx_file_dir_entry.fx_dir_entry_file_size = file_ptr -> fx_file_current_file_size;
|
||||
}
|
||||
|
||||
/* End transaction. */
|
||||
status = _fx_fault_tolerant_transaction_end(media_ptr);
|
||||
#endif /* FX_ENABLE_FAULT_TOLERANT */
|
||||
|
||||
/* Release media protection. */
|
||||
FX_UNPROTECT
|
||||
|
||||
/* Return status to the caller. */
|
||||
return(status);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,583 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** FileX Component */
|
||||
/** */
|
||||
/** File */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
#define FX_SOURCE_CODE
|
||||
|
||||
|
||||
/* Include necessary system files. */
|
||||
|
||||
#include "fx_api.h"
|
||||
#include "fx_system.h"
|
||||
#include "fx_file.h"
|
||||
#include "fx_utility.h"
|
||||
#include "fx_directory.h"
|
||||
#ifdef FX_ENABLE_FAULT_TOLERANT
|
||||
#include "fx_fault_tolerant.h"
|
||||
#endif /* FX_ENABLE_FAULT_TOLERANT */
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _fx_file_extended_best_effort_allocate PORTABLE C */
|
||||
/* 6.1 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function attempts to allocate the number of consecutive */
|
||||
/* clusters required to satisfy the user's request. If there are not */
|
||||
/* enough clusters, the largest set of clusters are allocated and */
|
||||
/* linked to the file. If there are no free clusters, an error */
|
||||
/* code is returned to the caller. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* file_ptr File control block pointer */
|
||||
/* size Number of bytes to allocate */
|
||||
/* actual_size_allocated Number of bytes allocated */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* return status */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* _fx_directory_entry_write Update directory entry */
|
||||
/* _fx_utility_FAT_entry_read Read a FAT entry */
|
||||
/* _fx_utility_FAT_entry_write Write a FAT entry */
|
||||
/* _fx_utility_FAT_flush Flush written FAT entries */
|
||||
/* _fx_utility_logical_sector_flush Flush the written log 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 */
|
||||
/* _fx_fault_tolerant_set_FAT_chain Set data of FAT chain */
|
||||
/* */
|
||||
/* 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_file_extended_best_effort_allocate(FX_FILE *file_ptr, ULONG64 size, ULONG64 *actual_size_allocated)
|
||||
{
|
||||
|
||||
UINT status;
|
||||
ULONG i;
|
||||
UINT found;
|
||||
ULONG bytes_per_cluster;
|
||||
ULONG FAT_index, start_FAT_index;
|
||||
ULONG FAT_value;
|
||||
ULONG clusters, maximum_clusters;
|
||||
FX_MEDIA *media_ptr;
|
||||
|
||||
|
||||
#ifdef TX_ENABLE_EVENT_TRACE
|
||||
TX_TRACE_BUFFER_ENTRY *trace_event;
|
||||
ULONG trace_timestamp;
|
||||
#endif
|
||||
|
||||
|
||||
/* First, determine if the file is still open. */
|
||||
if (file_ptr -> fx_file_id != FX_FILE_ID)
|
||||
{
|
||||
|
||||
/* Return the file not open error status. */
|
||||
return(FX_NOT_OPEN);
|
||||
}
|
||||
|
||||
#ifndef FX_MEDIA_STATISTICS_DISABLE
|
||||
/* Setup pointer to media structure. */
|
||||
media_ptr = file_ptr -> fx_file_media_ptr;
|
||||
|
||||
/* Increment the number of times this service has been called. */
|
||||
media_ptr -> fx_media_file_best_effort_allocates++;
|
||||
#endif
|
||||
|
||||
/* Make sure this file is open for writing. */
|
||||
if (file_ptr -> fx_file_open_mode != FX_OPEN_FOR_WRITE)
|
||||
{
|
||||
|
||||
/* Return the access error exception - a write was attempted from
|
||||
a file opened for reading! */
|
||||
return(FX_ACCESS_ERROR);
|
||||
}
|
||||
|
||||
/* Determine if the requested allocation is for zero bytes. */
|
||||
if (size == 0)
|
||||
{
|
||||
|
||||
/* Return a size allocated of zero. */
|
||||
*actual_size_allocated = 0;
|
||||
|
||||
/* Return a successful completion - nothing needs to be done. */
|
||||
return(FX_SUCCESS);
|
||||
}
|
||||
|
||||
/* Setup pointer to associated media control block. */
|
||||
media_ptr = file_ptr -> fx_file_media_ptr;
|
||||
|
||||
/* If trace is enabled, insert this event into the trace buffer. */
|
||||
FX_TRACE_IN_LINE_INSERT(FX_TRACE_FILE_BEST_EFFORT_ALLOCATE, file_ptr, size, 0, 0, FX_TRACE_FILE_EVENTS, &trace_event, &trace_timestamp)
|
||||
|
||||
/* Protect against other threads accessing the media. */
|
||||
FX_PROTECT
|
||||
|
||||
#ifdef FX_ENABLE_FAULT_TOLERANT
|
||||
/* Start transaction. */
|
||||
_fx_fault_tolerant_transaction_start(media_ptr);
|
||||
#endif /* FX_ENABLE_FAULT_TOLERANT */
|
||||
|
||||
/* Check for write protect at the media level (set by driver). */
|
||||
if (media_ptr -> fx_media_driver_write_protect)
|
||||
{
|
||||
|
||||
#ifdef FX_ENABLE_FAULT_TOLERANT
|
||||
FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
|
||||
#endif /* FX_ENABLE_FAULT_TOLERANT */
|
||||
|
||||
/* Release media protection. */
|
||||
FX_UNPROTECT
|
||||
|
||||
/* Return write protect error. */
|
||||
return(FX_WRITE_PROTECT);
|
||||
}
|
||||
|
||||
/* Calculate the number of bytes per cluster. */
|
||||
bytes_per_cluster = ((ULONG)media_ptr -> fx_media_bytes_per_sector) *
|
||||
((ULONG)media_ptr -> fx_media_sectors_per_cluster);
|
||||
|
||||
/* Check for invalid value. */
|
||||
if (bytes_per_cluster == 0)
|
||||
{
|
||||
|
||||
#ifdef FX_ENABLE_FAULT_TOLERANT
|
||||
FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
|
||||
#endif /* FX_ENABLE_FAULT_TOLERANT */
|
||||
|
||||
/* Release media protection. */
|
||||
FX_UNPROTECT
|
||||
|
||||
/* Invalid media, return error. */
|
||||
return(FX_MEDIA_INVALID);
|
||||
}
|
||||
|
||||
/* Calculate the number of consecutive clusters needed to satisfy this
|
||||
request. */
|
||||
clusters = (ULONG)(((size + bytes_per_cluster - 1) / bytes_per_cluster));
|
||||
|
||||
/* Determine if cluster count is 0. */
|
||||
if (clusters == 0)
|
||||
{
|
||||
|
||||
#ifdef FX_ENABLE_FAULT_TOLERANT
|
||||
FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
|
||||
#endif /* FX_ENABLE_FAULT_TOLERANT */
|
||||
|
||||
/* Release media protection. */
|
||||
FX_UNPROTECT
|
||||
|
||||
/* Size overflow when rounding to the next cluster, return an error status. */
|
||||
return(FX_NO_MORE_SPACE);
|
||||
}
|
||||
|
||||
/* Determine if there are no available clusters on the media. */
|
||||
if (!media_ptr -> fx_media_available_clusters)
|
||||
{
|
||||
|
||||
#ifdef FX_ENABLE_FAULT_TOLERANT
|
||||
FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
|
||||
#endif /* FX_ENABLE_FAULT_TOLERANT */
|
||||
|
||||
/* Release media protection. */
|
||||
FX_UNPROTECT
|
||||
|
||||
/* Return a size allocated of zero, since no clusters were available. */
|
||||
*actual_size_allocated = 0;
|
||||
|
||||
/* Not enough clusters, return an error status. */
|
||||
return(FX_NO_MORE_SPACE);
|
||||
}
|
||||
|
||||
/* Determine if the requested file allocation would exceed the physical limit of the file. */
|
||||
if (((file_ptr -> fx_file_current_available_size + (((ULONG64) clusters) * ((ULONG64) bytes_per_cluster))) < file_ptr -> fx_file_current_available_size) ||
|
||||
((file_ptr -> fx_file_current_available_size + (((ULONG64) clusters) * ((ULONG64) bytes_per_cluster))) > 0xFFFFFFFFULL))
|
||||
{
|
||||
|
||||
#ifdef FX_ENABLE_FAULT_TOLERANT
|
||||
FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
|
||||
#endif /* FX_ENABLE_FAULT_TOLERANT */
|
||||
|
||||
/* Release media protection. */
|
||||
FX_UNPROTECT
|
||||
|
||||
/* Return the no more space error, since the new file size would be larger than
|
||||
the 32-bit field to represent it in the file's directory entry. */
|
||||
return(FX_NO_MORE_SPACE);
|
||||
}
|
||||
|
||||
/* Now we need to find the consecutive clusters. */
|
||||
found = FX_FALSE;
|
||||
FAT_index = FX_FAT_ENTRY_START;
|
||||
maximum_clusters = 0;
|
||||
start_FAT_index = FAT_index;
|
||||
|
||||
while (FAT_index < (media_ptr -> fx_media_total_clusters + FX_FAT_ENTRY_START))
|
||||
{
|
||||
|
||||
/* Determine if enough consecutive FAT entries are available. */
|
||||
i = 0;
|
||||
|
||||
|
||||
do
|
||||
{
|
||||
|
||||
/* Read a FAT entry. */
|
||||
status = _fx_utility_FAT_entry_read(media_ptr, (FAT_index + i), &FAT_value);
|
||||
|
||||
/* Check for a successful 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 error status. */
|
||||
return(status);
|
||||
}
|
||||
|
||||
/* Determine if the entry is free. */
|
||||
if (FAT_value != FX_FREE_CLUSTER)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
/* Otherwise, increment the consecutive FAT indices. */
|
||||
i++;
|
||||
} while ((i < clusters) && ((FAT_index + i) < media_ptr -> fx_media_total_clusters + FX_FAT_ENTRY_START));
|
||||
|
||||
/* Determine if a new maximum number of clusters has been found. */
|
||||
if (i > maximum_clusters)
|
||||
{
|
||||
|
||||
/* Yes, remember the maximum number of clusters and the starting
|
||||
cluster. */
|
||||
maximum_clusters = i;
|
||||
start_FAT_index = FAT_index;
|
||||
}
|
||||
|
||||
/* Determine if we found enough FAT entries. */
|
||||
if (i >= clusters)
|
||||
{
|
||||
|
||||
/* Yes, we have found enough FAT entries - set the found
|
||||
flag and get out of this loop. */
|
||||
found = FX_TRUE;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* Position to the next possibly free FAT entry. */
|
||||
FAT_index = FAT_index + i + 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Determine if the total request could not be satisfied, but a partial allocation
|
||||
could be satisfied. */
|
||||
if (maximum_clusters)
|
||||
{
|
||||
|
||||
/* Yes, there was at least one cluster. Prepare to return this
|
||||
to the caller. */
|
||||
FAT_index = start_FAT_index;
|
||||
clusters = maximum_clusters;
|
||||
found = FX_TRUE;
|
||||
}
|
||||
|
||||
/* Determine if we found enough consecutive clusters to satisfy the
|
||||
request. */
|
||||
if (found)
|
||||
{
|
||||
|
||||
#ifdef FX_ENABLE_FAULT_TOLERANT
|
||||
if (media_ptr -> fx_media_fault_tolerant_enabled)
|
||||
{
|
||||
|
||||
/* Record the FAT chain being applied to the file system. This information aids
|
||||
recovery effort if fault happens. */
|
||||
media_ptr -> fx_media_fault_tolerant_state |= FX_FAULT_TOLERANT_STATE_SET_FAT_CHAIN;
|
||||
_fx_fault_tolerant_set_FAT_chain(media_ptr, FX_FALSE, file_ptr -> fx_file_last_physical_cluster,
|
||||
FAT_index, media_ptr -> fx_media_fat_last, media_ptr -> fx_media_fat_last);
|
||||
}
|
||||
#endif /* FX_ENABLE_FAULT_TOLERANT */
|
||||
|
||||
|
||||
/* Update the link pointers in the new clusters. */
|
||||
for (i = 0; i < (clusters - 1); i++)
|
||||
{
|
||||
|
||||
/* Update the cluster links. Since the allocation is
|
||||
sequential, we just have to link each FAT entry to the
|
||||
next one. */
|
||||
status = _fx_utility_FAT_entry_write(media_ptr, FAT_index + i, FAT_index + i + 1);
|
||||
|
||||
/* 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 error status. */
|
||||
return(status);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Now place an EOF in the last cluster entry. */
|
||||
status = _fx_utility_FAT_entry_write(media_ptr, FAT_index + clusters - 1, 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 error status. */
|
||||
return(status);
|
||||
}
|
||||
|
||||
#ifdef FX_FAULT_TOLERANT
|
||||
|
||||
/* Flush the cached individual FAT entries */
|
||||
_fx_utility_FAT_flush(media_ptr);
|
||||
#endif
|
||||
|
||||
/* Actually link up the new clusters to the file. */
|
||||
|
||||
/* Determine if there are already clusters allocated for this file. */
|
||||
if (file_ptr -> fx_file_total_clusters)
|
||||
{
|
||||
|
||||
|
||||
/* Linkup the last cluster. */
|
||||
status = _fx_utility_FAT_entry_write(media_ptr,
|
||||
file_ptr -> fx_file_last_physical_cluster, FAT_index);
|
||||
|
||||
/* 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 error status. */
|
||||
return(status);
|
||||
}
|
||||
|
||||
/* Determine if we are adding a sector after a write filled the previously
|
||||
allocated cluster exactly. */
|
||||
if ((file_ptr -> fx_file_current_relative_sector >=
|
||||
(media_ptr -> fx_media_sectors_per_cluster - 1)) &&
|
||||
(file_ptr -> fx_file_current_logical_offset >=
|
||||
media_ptr -> fx_media_bytes_per_sector))
|
||||
{
|
||||
|
||||
/* Yes, we need to adjust all of the pertinent file parameters for
|
||||
access into this newly allocated cluster. */
|
||||
file_ptr -> fx_file_current_physical_cluster = FAT_index;
|
||||
file_ptr -> fx_file_current_relative_cluster++;
|
||||
file_ptr -> fx_file_current_relative_sector = 0;
|
||||
file_ptr -> fx_file_current_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));
|
||||
file_ptr -> fx_file_current_logical_offset = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* These new clusters are also the first! Setup the initial
|
||||
file parameters. */
|
||||
file_ptr -> fx_file_first_physical_cluster = FAT_index;
|
||||
file_ptr -> fx_file_current_physical_cluster = file_ptr -> fx_file_first_physical_cluster;
|
||||
file_ptr -> fx_file_current_relative_cluster = 0;
|
||||
file_ptr -> fx_file_current_logical_sector = ((ULONG)media_ptr -> fx_media_data_sector_start) +
|
||||
(((ULONG64)(file_ptr -> fx_file_first_physical_cluster - FX_FAT_ENTRY_START)) *
|
||||
((ULONG)media_ptr -> fx_media_sectors_per_cluster));
|
||||
file_ptr -> fx_file_current_logical_offset = 0;
|
||||
file_ptr -> fx_file_current_file_offset = 0;
|
||||
|
||||
/* Setup the consecutive clusters at the beginning of the file. */
|
||||
file_ptr -> fx_file_consecutive_cluster = clusters;
|
||||
|
||||
/* Update the first cluster in the directory entry. */
|
||||
file_ptr -> fx_file_dir_entry.fx_dir_entry_cluster = FAT_index;
|
||||
|
||||
#ifdef FX_ENABLE_FAULT_TOLERANT
|
||||
if (media_ptr -> fx_media_fault_tolerant_enabled)
|
||||
{
|
||||
|
||||
/* Clear undo phase. */
|
||||
media_ptr -> fx_media_fault_tolerant_state &= (UCHAR)(~FX_FAULT_TOLERANT_STATE_SET_FAT_CHAIN & 0xff);
|
||||
}
|
||||
#endif /* FX_ENABLE_FAULT_TOLERANT */
|
||||
}
|
||||
|
||||
/* Remember the last physical cluster. */
|
||||
file_ptr -> fx_file_last_physical_cluster = FAT_index + clusters - 1;
|
||||
|
||||
/* Update the available size. */
|
||||
|
||||
/* Normal condition, update the available size. */
|
||||
file_ptr -> fx_file_current_available_size =
|
||||
file_ptr -> fx_file_current_available_size + bytes_per_cluster * clusters;
|
||||
|
||||
/* Increment the total clusters for this file. */
|
||||
file_ptr -> fx_file_total_clusters =
|
||||
file_ptr -> fx_file_total_clusters + clusters;
|
||||
|
||||
/* Decrease the available clusters on the media. */
|
||||
media_ptr -> fx_media_available_clusters =
|
||||
media_ptr -> fx_media_available_clusters - clusters;
|
||||
|
||||
/* Return the actual size allocated. */
|
||||
*actual_size_allocated = ((ULONG64)clusters) * bytes_per_cluster;
|
||||
|
||||
#if defined(FX_UPDATE_FILE_SIZE_ON_ALLOCATE) || defined(FX_ENABLE_FAULT_TOLERANT)
|
||||
|
||||
/* Set the file size the current size plus what what was added. */
|
||||
if (size < *actual_size_allocated)
|
||||
{
|
||||
file_ptr -> fx_file_current_file_size += size;
|
||||
}
|
||||
else
|
||||
{
|
||||
file_ptr -> fx_file_current_file_size += *actual_size_allocated;
|
||||
}
|
||||
|
||||
/* Copy the new file size into the directory entry. */
|
||||
file_ptr -> fx_file_dir_entry.fx_dir_entry_file_size = file_ptr -> fx_file_current_file_size;
|
||||
#endif
|
||||
|
||||
/* Update the trace event with the bytes allocated. */
|
||||
FX_TRACE_EVENT_UPDATE(trace_event, trace_timestamp, FX_TRACE_FILE_BEST_EFFORT_ALLOCATE, 0, 0, *actual_size_allocated, 0);
|
||||
|
||||
/* Write the directory entry to the media. */
|
||||
status = _fx_directory_entry_write(media_ptr, &(file_ptr -> fx_file_dir_entry));
|
||||
|
||||
/* Check for a good 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 error status. */
|
||||
return(status);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
#ifdef FX_ENABLE_FAULT_TOLERANT
|
||||
FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
|
||||
#endif /* FX_ENABLE_FAULT_TOLERANT */
|
||||
|
||||
/* Release media protection. */
|
||||
FX_UNPROTECT
|
||||
|
||||
/* Return a size allocated of zero, since no clusters were available. */
|
||||
*actual_size_allocated = 0;
|
||||
|
||||
/* Not enough contiguous space on the media. Return error status. */
|
||||
return(FX_NO_MORE_SPACE);
|
||||
}
|
||||
|
||||
#ifdef FX_FAULT_TOLERANT
|
||||
|
||||
/* Flush the cached individual FAT entries */
|
||||
_fx_utility_FAT_flush(media_ptr);
|
||||
#endif
|
||||
|
||||
/* Flush the internal logical sector cache. */
|
||||
status = _fx_utility_logical_sector_flush(media_ptr, ((ULONG64) 1), (ULONG64) (media_ptr -> fx_media_sectors_per_FAT), FX_FALSE);
|
||||
|
||||
#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
|
||||
|
||||
/* Return status to the caller. */
|
||||
return(status);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,163 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** FileX Component */
|
||||
/** */
|
||||
/** File */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
#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"
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _fx_file_extended_relative_seek PORTABLE C */
|
||||
/* 6.1 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function positions the internal file pointers to the specified */
|
||||
/* byte relative offset such that the next read or write operation is */
|
||||
/* performed there. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* file_ptr File control block pointer */
|
||||
/* byte_offset Byte offset of the seek */
|
||||
/* seek_from Direction for relative seek, */
|
||||
/* legal values are: */
|
||||
/* */
|
||||
/* FX_SEEK_BEGIN */
|
||||
/* FX_SEEK_END */
|
||||
/* FX_SEEK_FORWARD */
|
||||
/* FX_SEEK_BACK */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* return status */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* _fx_file_extended_seek Seek to specified position */
|
||||
/* */
|
||||
/* 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_file_extended_relative_seek(FX_FILE *file_ptr, ULONG64 byte_offset, UINT seek_from)
|
||||
{
|
||||
|
||||
#ifndef FX_MEDIA_STATISTICS_DISABLE
|
||||
FX_MEDIA *media_ptr;
|
||||
|
||||
/* First, determine if the file is still open. */
|
||||
if (file_ptr -> fx_file_id != FX_FILE_ID)
|
||||
{
|
||||
|
||||
/* Return the file not open error status. */
|
||||
return(FX_NOT_OPEN);
|
||||
}
|
||||
|
||||
/* Setup pointer to media structure. */
|
||||
media_ptr = file_ptr -> fx_file_media_ptr;
|
||||
|
||||
/* Increment the number of times this service has been called. */
|
||||
media_ptr -> fx_media_file_relative_seeks++;
|
||||
#endif
|
||||
|
||||
/* If trace is enabled, insert this event into the trace buffer. */
|
||||
FX_TRACE_IN_LINE_INSERT(FX_TRACE_FILE_RELATIVE_SEEK, file_ptr, byte_offset, seek_from, file_ptr -> fx_file_current_file_offset, FX_TRACE_FILE_EVENTS, 0, 0)
|
||||
|
||||
/* Determine if seeking from the beginning is requested. */
|
||||
if (seek_from == FX_SEEK_BEGIN)
|
||||
{
|
||||
|
||||
/* Yes, use the base file seek routine to seek from the beginning of
|
||||
the file. */
|
||||
return(_fx_file_extended_seek(file_ptr, byte_offset));
|
||||
}
|
||||
/* Otherwise, determine if seeking from the end is requested. */
|
||||
else if (seek_from == FX_SEEK_END)
|
||||
{
|
||||
|
||||
/* Yes, seek from the end of the file. */
|
||||
|
||||
/* Determine if the requested seek offset is greater than
|
||||
the file size. */
|
||||
if (byte_offset >= file_ptr -> fx_file_current_file_size)
|
||||
{
|
||||
|
||||
/* Yes, just seek to the beginning of the file. */
|
||||
return(_fx_file_extended_seek(file_ptr, ((ULONG64) 0)));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* Logically seek from the end of the file. */
|
||||
return(_fx_file_extended_seek(file_ptr, file_ptr -> fx_file_current_file_size - byte_offset));
|
||||
}
|
||||
}
|
||||
/* Otherwise, determine if seeking from the current position is requested. */
|
||||
else if (seek_from == FX_SEEK_FORWARD)
|
||||
{
|
||||
|
||||
/* Yes, just seek ahead from the current file position. */
|
||||
return(_fx_file_extended_seek(file_ptr, file_ptr -> fx_file_current_file_offset + byte_offset));
|
||||
}
|
||||
/* Otherwise, seeking backward from the current position is assumed. */
|
||||
else
|
||||
{
|
||||
|
||||
/* Determine if the backward offset is greater than the current file offset. */
|
||||
if (byte_offset >= file_ptr -> fx_file_current_file_offset)
|
||||
{
|
||||
|
||||
/* Yes, just position the file to the beginning. */
|
||||
return(_fx_file_extended_seek(file_ptr, ((ULONG64) 0)));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* Seek backward relative to the current position. */
|
||||
return(_fx_file_extended_seek(file_ptr, file_ptr -> fx_file_current_file_offset - byte_offset));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,300 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** FileX Component */
|
||||
/** */
|
||||
/** File */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
#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"
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _fx_file_extended_seek PORTABLE C */
|
||||
/* 6.1.7 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function positions the internal file pointers to the specified */
|
||||
/* byte offset such that the next read or write operation will be */
|
||||
/* performed there. If the byte offset is greater than the size, the */
|
||||
/* file pointers will be positioned to the end of the file. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* file_ptr File control block pointer */
|
||||
/* byte_offset Byte offset into the file */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* return status */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* _fx_utility_FAT_entry_read Read a FAT entry */
|
||||
/* */
|
||||
/* 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 */
|
||||
/* 06-02-2021 Bhupendra Naphade Modified comment(s), fixed */
|
||||
/* relative cluster logic, */
|
||||
/* resulting in version 6.1.7 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
UINT _fx_file_extended_seek(FX_FILE *file_ptr, ULONG64 byte_offset)
|
||||
{
|
||||
|
||||
UINT status;
|
||||
ULONG cluster;
|
||||
ULONG contents = 0;
|
||||
ULONG bytes_per_cluster;
|
||||
ULONG last_cluster;
|
||||
ULONG cluster_count;
|
||||
ULONG64 bytes_remaining;
|
||||
FX_MEDIA *media_ptr;
|
||||
|
||||
|
||||
/* First, determine if the file is still open. */
|
||||
if (file_ptr -> fx_file_id != FX_FILE_ID)
|
||||
{
|
||||
|
||||
/* Return the file not open error status. */
|
||||
return(FX_NOT_OPEN);
|
||||
}
|
||||
|
||||
#ifndef FX_MEDIA_STATISTICS_DISABLE
|
||||
/* Setup pointer to media structure. */
|
||||
media_ptr = file_ptr -> fx_file_media_ptr;
|
||||
|
||||
/* Increment the number of times this service has been called. */
|
||||
media_ptr -> fx_media_file_seeks++;
|
||||
#endif
|
||||
|
||||
/* Setup pointer to associated media control block. */
|
||||
media_ptr = file_ptr -> fx_file_media_ptr;
|
||||
|
||||
/* If trace is enabled, insert this event into the trace buffer. */
|
||||
FX_TRACE_IN_LINE_INSERT(FX_TRACE_FILE_SEEK, file_ptr, byte_offset, file_ptr -> fx_file_current_file_offset, 0, FX_TRACE_FILE_EVENTS, 0, 0)
|
||||
|
||||
/* Protect against other threads accessing the media. */
|
||||
FX_PROTECT
|
||||
|
||||
/* Check if we actually have to do anything. */
|
||||
if (byte_offset == file_ptr -> fx_file_current_file_offset)
|
||||
{
|
||||
|
||||
/* Release media protection. */
|
||||
FX_UNPROTECT
|
||||
|
||||
/* Seek is complete, return successful status. */
|
||||
return(FX_SUCCESS);
|
||||
}
|
||||
|
||||
/* Calculate the number of bytes per cluster. */
|
||||
bytes_per_cluster = ((ULONG)media_ptr -> fx_media_bytes_per_sector) *
|
||||
((ULONG)media_ptr -> fx_media_sectors_per_cluster);
|
||||
|
||||
/* Check for invalid value. */
|
||||
if (bytes_per_cluster == 0)
|
||||
{
|
||||
|
||||
/* Release media protection. */
|
||||
FX_UNPROTECT
|
||||
|
||||
/* Invalid media, return error. */
|
||||
return(FX_MEDIA_INVALID);
|
||||
}
|
||||
|
||||
/* See if we need to adjust the byte offset. */
|
||||
if (byte_offset > file_ptr -> fx_file_current_file_size)
|
||||
{
|
||||
|
||||
/* Adjust the byte offset down to the file size. */
|
||||
byte_offset = file_ptr -> fx_file_current_file_size;
|
||||
}
|
||||
|
||||
/* Check if the desired position within the leading consecutive clusters. */
|
||||
if (byte_offset >= (ULONG64)file_ptr -> fx_file_consecutive_cluster * (ULONG64)bytes_per_cluster)
|
||||
{
|
||||
|
||||
/* At this point, we are ready to walk list of clusters to setup the
|
||||
seek position of this file. */
|
||||
|
||||
/* check if byte_offset is greater than where we were left off earlier */
|
||||
if ((ULONG64)file_ptr -> fx_file_current_relative_cluster * (ULONG64)bytes_per_cluster < byte_offset)
|
||||
{
|
||||
|
||||
cluster = file_ptr -> fx_file_current_physical_cluster;
|
||||
|
||||
bytes_remaining = byte_offset -
|
||||
file_ptr -> fx_file_current_relative_cluster * bytes_per_cluster;
|
||||
|
||||
cluster_count = file_ptr -> fx_file_current_relative_cluster;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
cluster = file_ptr -> fx_file_first_physical_cluster +
|
||||
(file_ptr -> fx_file_consecutive_cluster - 1);
|
||||
bytes_remaining = byte_offset -
|
||||
(file_ptr -> fx_file_consecutive_cluster - 1) * bytes_per_cluster;
|
||||
cluster_count = (file_ptr -> fx_file_consecutive_cluster - 1);
|
||||
}
|
||||
|
||||
|
||||
/* Follow the link of FAT entries. */
|
||||
while ((cluster >= FX_FAT_ENTRY_START) && (cluster < media_ptr -> fx_media_fat_reserved))
|
||||
{
|
||||
|
||||
/* Increment the number of clusters. */
|
||||
cluster_count++;
|
||||
|
||||
/* Read the current cluster entry from the FAT. */
|
||||
status = _fx_utility_FAT_entry_read(media_ptr, cluster, &contents);
|
||||
|
||||
/* Check the return value. */
|
||||
if (status != FX_SUCCESS)
|
||||
{
|
||||
|
||||
/* Release media protection. */
|
||||
FX_UNPROTECT
|
||||
|
||||
/* Return the error status. */
|
||||
return(status);
|
||||
}
|
||||
|
||||
/* Save the last valid cluster. */
|
||||
last_cluster = cluster;
|
||||
|
||||
/* Setup for the next cluster. */
|
||||
cluster = contents;
|
||||
|
||||
/* Determine if this is the last written cluster. */
|
||||
if (bytes_remaining > bytes_per_cluster)
|
||||
{
|
||||
|
||||
/* Still more seeking, just decrement the working byte offset. */
|
||||
bytes_remaining = bytes_remaining - bytes_per_cluster;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* Remember this cluster number. */
|
||||
file_ptr -> fx_file_current_physical_cluster = last_cluster;
|
||||
|
||||
/* Remember the relative cluster. */
|
||||
file_ptr -> fx_file_current_relative_cluster = cluster_count - 1;
|
||||
|
||||
/* If the remaining bytes exactly fits the cluster size, check for
|
||||
a possible adjustment to the next cluster. */
|
||||
if ((bytes_remaining == bytes_per_cluster) &&
|
||||
(cluster >= FX_FAT_ENTRY_START) && (cluster < media_ptr -> fx_media_fat_reserved))
|
||||
{
|
||||
|
||||
/* We need to position to next allocated cluster. */
|
||||
file_ptr -> fx_file_current_physical_cluster = cluster;
|
||||
file_ptr -> fx_file_current_relative_cluster++;
|
||||
|
||||
/* Clear the remaining bytes. */
|
||||
bytes_remaining = 0;
|
||||
}
|
||||
|
||||
/* This is the cluster that contains the seek position. */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Check for errors in traversal of the FAT chain. */
|
||||
if (byte_offset > (((ULONG64) bytes_per_cluster) * ((ULONG64) cluster_count)))
|
||||
{
|
||||
|
||||
/* Release media protection. */
|
||||
FX_UNPROTECT
|
||||
|
||||
/* This is an error that suggests a corrupt file. */
|
||||
return(FX_FILE_CORRUPT);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* we should directly access the desired cluster */
|
||||
file_ptr -> fx_file_current_relative_cluster = (ULONG)(byte_offset / bytes_per_cluster);
|
||||
|
||||
file_ptr -> fx_file_current_physical_cluster =
|
||||
file_ptr -> fx_file_first_physical_cluster + file_ptr -> fx_file_current_relative_cluster;
|
||||
|
||||
bytes_remaining = byte_offset % bytes_per_cluster;
|
||||
}
|
||||
|
||||
|
||||
/* Determine if the remaining bytes fit exactly into the cluster size. */
|
||||
if (bytes_remaining == bytes_per_cluster)
|
||||
{
|
||||
|
||||
/* Position to the end of the cluster. */
|
||||
file_ptr -> fx_file_current_logical_sector = (ULONG)(((ULONG)media_ptr -> fx_media_data_sector_start) +
|
||||
(((ULONG64)file_ptr -> fx_file_current_physical_cluster - FX_FAT_ENTRY_START) *
|
||||
((ULONG)media_ptr -> fx_media_sectors_per_cluster)) +
|
||||
((bytes_remaining - 1) / (ULONG)media_ptr -> fx_media_bytes_per_sector));
|
||||
file_ptr -> fx_file_current_relative_sector = (UINT)(((bytes_remaining - 1) / (ULONG)media_ptr -> fx_media_bytes_per_sector));
|
||||
file_ptr -> fx_file_current_file_offset = byte_offset;
|
||||
file_ptr -> fx_file_current_logical_offset = media_ptr -> fx_media_bytes_per_sector;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* Position the pointers to the new offset. */
|
||||
file_ptr -> fx_file_current_logical_sector = (ULONG)(((ULONG)media_ptr -> fx_media_data_sector_start) +
|
||||
(((ULONG64)file_ptr -> fx_file_current_physical_cluster - FX_FAT_ENTRY_START) *
|
||||
((ULONG)media_ptr -> fx_media_sectors_per_cluster)) +
|
||||
(bytes_remaining / (ULONG)media_ptr -> fx_media_bytes_per_sector));
|
||||
file_ptr -> fx_file_current_relative_sector = (UINT)((bytes_remaining / (ULONG)media_ptr -> fx_media_bytes_per_sector));
|
||||
file_ptr -> fx_file_current_file_offset = byte_offset;
|
||||
file_ptr -> fx_file_current_logical_offset = (ULONG)(bytes_remaining % ((ULONG)media_ptr -> fx_media_bytes_per_sector));
|
||||
}
|
||||
|
||||
/* Release media protection. */
|
||||
FX_UNPROTECT
|
||||
|
||||
/* Seek is complete, return successful status. */
|
||||
return(FX_SUCCESS);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,347 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** FileX Component */
|
||||
/** */
|
||||
/** File */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
#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_file_extended_truncate PORTABLE C */
|
||||
/* 6.1 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function sets the file to the specified size, if smaller than */
|
||||
/* the current file size. If the new file size is less than the */
|
||||
/* current file read/write position, the internal file pointers will */
|
||||
/* also be modified. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* file_ptr File control block pointer */
|
||||
/* size New size of the file in bytes */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* return status */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* _fx_utility_FAT_entry_read Read a FAT entry */
|
||||
/* _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_file_extended_truncate(FX_FILE *file_ptr, ULONG64 size)
|
||||
{
|
||||
|
||||
UINT status;
|
||||
ULONG cluster;
|
||||
ULONG contents = 0;
|
||||
ULONG bytes_per_cluster;
|
||||
ULONG last_cluster;
|
||||
ULONG cluster_count;
|
||||
ULONG64 bytes_remaining;
|
||||
FX_MEDIA *media_ptr;
|
||||
|
||||
#ifndef FX_DONT_UPDATE_OPEN_FILES
|
||||
ULONG open_count;
|
||||
FX_FILE *search_ptr;
|
||||
#endif
|
||||
|
||||
#ifdef TX_ENABLE_EVENT_TRACE
|
||||
TX_TRACE_BUFFER_ENTRY *trace_event;
|
||||
ULONG trace_timestamp;
|
||||
#endif
|
||||
|
||||
|
||||
/* First, determine if the file is still open. */
|
||||
if (file_ptr -> fx_file_id != FX_FILE_ID)
|
||||
{
|
||||
|
||||
/* Return the file not open error status. */
|
||||
return(FX_NOT_OPEN);
|
||||
}
|
||||
|
||||
#ifndef FX_MEDIA_STATISTICS_DISABLE
|
||||
/* Setup pointer to media structure. */
|
||||
media_ptr = file_ptr -> fx_file_media_ptr;
|
||||
|
||||
/* Increment the number of times this service has been called. */
|
||||
media_ptr -> fx_media_file_truncates++;
|
||||
#endif
|
||||
|
||||
/* Setup pointer to associated media control block. */
|
||||
media_ptr = file_ptr -> fx_file_media_ptr;
|
||||
|
||||
/* If trace is enabled, insert this event into the trace buffer. */
|
||||
FX_TRACE_IN_LINE_INSERT(FX_TRACE_FILE_TRUNCATE, file_ptr, size, file_ptr -> fx_file_current_file_size, 0, FX_TRACE_FILE_EVENTS, &trace_event, &trace_timestamp)
|
||||
|
||||
/* Protect against other threads accessing the media. */
|
||||
FX_PROTECT
|
||||
|
||||
/* Make sure this file is open for writing. */
|
||||
if (file_ptr -> fx_file_open_mode != FX_OPEN_FOR_WRITE)
|
||||
{
|
||||
|
||||
/* Release media protection. */
|
||||
FX_UNPROTECT
|
||||
|
||||
/* Return the access error exception - a write was attempted from
|
||||
a file opened for reading! */
|
||||
return(FX_ACCESS_ERROR);
|
||||
}
|
||||
|
||||
/* 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);
|
||||
}
|
||||
|
||||
/* Setup the new file size - if less than the current size. */
|
||||
if (size < file_ptr -> fx_file_current_file_size)
|
||||
{
|
||||
|
||||
/* Setup the new size. */
|
||||
file_ptr -> fx_file_current_file_size = size;
|
||||
|
||||
/* Set the modified flag as well. */
|
||||
file_ptr -> fx_file_modified = FX_TRUE;
|
||||
|
||||
/* Update the trace event with the truncated size. */
|
||||
FX_TRACE_EVENT_UPDATE(trace_event, trace_timestamp, FX_TRACE_FILE_TRUNCATE, 0, 0, 0, size)
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* Update the trace event with the truncated size. */
|
||||
FX_TRACE_EVENT_UPDATE(trace_event, trace_timestamp, FX_TRACE_FILE_TRUNCATE, 0, 0, 0, file_ptr -> fx_file_current_file_size)
|
||||
|
||||
/* Release media protection. */
|
||||
FX_UNPROTECT
|
||||
|
||||
/* Just return, the new size is larger than the current size. */
|
||||
return(FX_SUCCESS);
|
||||
}
|
||||
|
||||
#ifndef FX_DONT_UPDATE_OPEN_FILES
|
||||
|
||||
/* Search the opened files list to see if the same file is opened for reading. */
|
||||
open_count = media_ptr -> fx_media_opened_file_count;
|
||||
search_ptr = media_ptr -> fx_media_opened_file_list;
|
||||
while (open_count)
|
||||
{
|
||||
|
||||
/* Is this file the same file opened for reading? */
|
||||
if ((search_ptr != file_ptr) &&
|
||||
(search_ptr -> fx_file_dir_entry.fx_dir_entry_log_sector ==
|
||||
file_ptr -> fx_file_dir_entry.fx_dir_entry_log_sector) &&
|
||||
(search_ptr -> fx_file_dir_entry.fx_dir_entry_byte_offset ==
|
||||
file_ptr -> fx_file_dir_entry.fx_dir_entry_byte_offset))
|
||||
{
|
||||
|
||||
/* Yes, the same file is opened for reading. */
|
||||
|
||||
/* Setup the new file size. */
|
||||
search_ptr -> fx_file_current_file_size = size;
|
||||
search_ptr -> fx_file_dir_entry.fx_dir_entry_file_size = size;
|
||||
}
|
||||
|
||||
/* Adjust the pointer and decrement the search count. */
|
||||
search_ptr = search_ptr -> fx_file_opened_next;
|
||||
open_count--;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Now check to see if the read/write internal file pointers need
|
||||
to be adjusted. */
|
||||
if (file_ptr -> fx_file_current_file_offset > file_ptr -> fx_file_current_file_size)
|
||||
{
|
||||
|
||||
/* Calculate the number of bytes per cluster. */
|
||||
bytes_per_cluster = ((ULONG)media_ptr -> fx_media_bytes_per_sector) *
|
||||
((ULONG)media_ptr -> fx_media_sectors_per_cluster);
|
||||
|
||||
/* At this point, we are ready to walk list of clusters to setup the
|
||||
seek position of this file. */
|
||||
cluster = file_ptr -> fx_file_first_physical_cluster;
|
||||
bytes_remaining = size;
|
||||
last_cluster = 0;
|
||||
cluster_count = 0;
|
||||
|
||||
/* Follow the link of FAT entries. */
|
||||
while ((cluster >= FX_FAT_ENTRY_START) && (cluster < media_ptr -> fx_media_fat_reserved))
|
||||
{
|
||||
|
||||
/* Increment the number of clusters. */
|
||||
cluster_count++;
|
||||
|
||||
/* Read the current cluster entry from the FAT. */
|
||||
status = _fx_utility_FAT_entry_read(media_ptr, cluster, &contents);
|
||||
|
||||
/* Check the return value. */
|
||||
if (status != FX_SUCCESS)
|
||||
{
|
||||
|
||||
/* Release media protection. */
|
||||
FX_UNPROTECT
|
||||
|
||||
/* Return the error status. */
|
||||
return(status);
|
||||
}
|
||||
|
||||
/* Save the last valid cluster. */
|
||||
last_cluster = cluster;
|
||||
|
||||
/* Setup for the next cluster. */
|
||||
cluster = contents;
|
||||
|
||||
/* Determine if this is the last written cluster. */
|
||||
if (bytes_remaining >= bytes_per_cluster)
|
||||
{
|
||||
|
||||
/* Still more seeking, just decrement the working byte offset. */
|
||||
bytes_remaining = bytes_remaining - bytes_per_cluster;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* This is the cluster that contains the seek position. */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Check for errors in traversal of the FAT chain. */
|
||||
if (size > (((ULONG64) bytes_per_cluster) * ((ULONG64) cluster_count)))
|
||||
{
|
||||
|
||||
/* Release media protection. */
|
||||
FX_UNPROTECT
|
||||
|
||||
/* This is an error that suggests a corrupt file. */
|
||||
return(FX_FILE_CORRUPT);
|
||||
}
|
||||
|
||||
/* Position the pointers to the new offset. */
|
||||
file_ptr -> fx_file_current_physical_cluster = last_cluster;
|
||||
file_ptr -> fx_file_current_relative_cluster = cluster_count - 1;
|
||||
file_ptr -> fx_file_current_logical_sector = ((ULONG)media_ptr -> fx_media_data_sector_start) +
|
||||
(((ULONG64)file_ptr -> fx_file_current_physical_cluster - FX_FAT_ENTRY_START) *
|
||||
((ULONG)media_ptr -> fx_media_sectors_per_cluster)) +
|
||||
(bytes_remaining / (ULONG)media_ptr -> fx_media_bytes_per_sector);
|
||||
file_ptr -> fx_file_current_relative_sector = (UINT)((bytes_remaining / (ULONG)media_ptr -> fx_media_bytes_per_sector));
|
||||
file_ptr -> fx_file_current_file_offset = size;
|
||||
file_ptr -> fx_file_current_logical_offset = (ULONG)bytes_remaining % ((ULONG)media_ptr -> fx_media_bytes_per_sector);
|
||||
}
|
||||
|
||||
#ifdef FX_ENABLE_FAULT_TOLERANT
|
||||
if (media_ptr -> fx_media_fault_tolerant_enabled)
|
||||
{
|
||||
|
||||
/* Start transaction. */
|
||||
_fx_fault_tolerant_transaction_start(media_ptr);
|
||||
|
||||
/* Copy the new file size into the directory entry. */
|
||||
file_ptr -> fx_file_dir_entry.fx_dir_entry_file_size = file_ptr -> fx_file_current_file_size;
|
||||
|
||||
/* Write the directory entry to the media. */
|
||||
status = _fx_directory_entry_write(media_ptr, &(file_ptr -> fx_file_dir_entry));
|
||||
|
||||
/* Check for a good status. */
|
||||
if (status != FX_SUCCESS)
|
||||
{
|
||||
|
||||
FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
|
||||
|
||||
/* Release media protection. */
|
||||
FX_UNPROTECT
|
||||
|
||||
/* Error writing the directory. */
|
||||
return(status);
|
||||
}
|
||||
|
||||
/* End transaction. */
|
||||
status = _fx_fault_tolerant_transaction_end(media_ptr);
|
||||
|
||||
/* Check for a good status. */
|
||||
if (status != FX_SUCCESS)
|
||||
{
|
||||
|
||||
/* Release media protection. */
|
||||
FX_UNPROTECT
|
||||
|
||||
/* Error writing the directory. */
|
||||
return(status);
|
||||
}
|
||||
|
||||
/* Update maximum size used if necessary. */
|
||||
if (size < file_ptr -> fx_file_maximum_size_used)
|
||||
{
|
||||
file_ptr -> fx_file_maximum_size_used = size;
|
||||
}
|
||||
}
|
||||
#endif /* FX_ENABLE_FAULT_TOLERANT */
|
||||
|
||||
/* Release media protection. */
|
||||
FX_UNPROTECT
|
||||
|
||||
/* Truncate is complete, return successful status. */
|
||||
return(FX_SUCCESS);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,814 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** FileX Component */
|
||||
/** */
|
||||
/** File */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
#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_file_extended_truncate_release PORTABLE C */
|
||||
/* 6.1.3 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function sets the file to the specified size, if smaller than */
|
||||
/* the current file size. If the new file size is less than the */
|
||||
/* current file read/write position, the internal file pointers will */
|
||||
/* also be modified. Any unused clusters are released back to the */
|
||||
/* media. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* file_ptr File control block pointer */
|
||||
/* size New size of the file in bytes */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* return status */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* _fx_directory_entry_write Write directory entry */
|
||||
/* _fx_utility_FAT_entry_read Read a FAT entry */
|
||||
/* _fx_utility_FAT_entry_write Write a FAT entry */
|
||||
/* _fx_utility_FAT_flush Flush written FAT entries */
|
||||
/* _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 */
|
||||
/* _fx_fault_tolerant_set_FAT_chain Set data of FAT chain */
|
||||
/* */
|
||||
/* 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 */
|
||||
/* 12-31-2020 William E. Lamie Modified comment(s), fixed */
|
||||
/* available cluster issue, */
|
||||
/* resulting in version 6.1.3 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
UINT _fx_file_extended_truncate_release(FX_FILE *file_ptr, ULONG64 size)
|
||||
{
|
||||
|
||||
UINT status;
|
||||
ULONG cluster;
|
||||
ULONG contents;
|
||||
ULONG bytes_per_cluster;
|
||||
ULONG last_cluster;
|
||||
ULONG cluster_count;
|
||||
ULONG64 bytes_remaining;
|
||||
FX_MEDIA *media_ptr;
|
||||
|
||||
|
||||
#ifndef FX_DONT_UPDATE_OPEN_FILES
|
||||
ULONG open_count;
|
||||
FX_FILE *search_ptr;
|
||||
#endif
|
||||
|
||||
#ifdef TX_ENABLE_EVENT_TRACE
|
||||
TX_TRACE_BUFFER_ENTRY *trace_event;
|
||||
ULONG trace_timestamp;
|
||||
#endif
|
||||
|
||||
|
||||
/* First, determine if the file is still open. */
|
||||
if (file_ptr -> fx_file_id != FX_FILE_ID)
|
||||
{
|
||||
|
||||
/* Return the file not open error status. */
|
||||
return(FX_NOT_OPEN);
|
||||
}
|
||||
|
||||
#ifndef FX_MEDIA_STATISTICS_DISABLE
|
||||
/* Setup pointer to media structure. */
|
||||
media_ptr = file_ptr -> fx_file_media_ptr;
|
||||
|
||||
/* Increment the number of times this service has been called. */
|
||||
media_ptr -> fx_media_file_truncate_releases++;
|
||||
#endif
|
||||
|
||||
/* Setup pointer to associated media control block. */
|
||||
media_ptr = file_ptr -> fx_file_media_ptr;
|
||||
|
||||
/* If trace is enabled, insert this event into the trace buffer. */
|
||||
FX_TRACE_IN_LINE_INSERT(FX_TRACE_FILE_TRUNCATE_RELEASE, file_ptr, size, file_ptr -> fx_file_current_file_size, 0, FX_TRACE_FILE_EVENTS, &trace_event, &trace_timestamp)
|
||||
|
||||
/* Protect against other threads accessing the media. */
|
||||
FX_PROTECT
|
||||
|
||||
#ifdef FX_ENABLE_FAULT_TOLERANT
|
||||
/* Start transaction. */
|
||||
_fx_fault_tolerant_transaction_start(media_ptr);
|
||||
#endif /* FX_ENABLE_FAULT_TOLERANT */
|
||||
|
||||
/* Make sure this file is open for writing. */
|
||||
if (file_ptr -> fx_file_open_mode != FX_OPEN_FOR_WRITE)
|
||||
{
|
||||
|
||||
#ifdef FX_ENABLE_FAULT_TOLERANT
|
||||
FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
|
||||
#endif /* FX_ENABLE_FAULT_TOLERANT */
|
||||
|
||||
/* Release media protection. */
|
||||
FX_UNPROTECT
|
||||
|
||||
/* Return the access error exception - a write was attempted from
|
||||
a file opened for reading! */
|
||||
return(FX_ACCESS_ERROR);
|
||||
}
|
||||
|
||||
/* Check for write protect at the media level (set by driver). */
|
||||
if (media_ptr -> fx_media_driver_write_protect)
|
||||
{
|
||||
|
||||
#ifdef FX_ENABLE_FAULT_TOLERANT
|
||||
FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
|
||||
#endif /* FX_ENABLE_FAULT_TOLERANT */
|
||||
|
||||
/* Release media protection. */
|
||||
FX_UNPROTECT
|
||||
|
||||
/* Return write protect error. */
|
||||
return(FX_WRITE_PROTECT);
|
||||
}
|
||||
|
||||
/* Calculate the number of bytes per cluster. */
|
||||
bytes_per_cluster = ((ULONG)media_ptr -> fx_media_bytes_per_sector) *
|
||||
((ULONG)media_ptr -> fx_media_sectors_per_cluster);
|
||||
|
||||
/* Check for invalid value. */
|
||||
if (bytes_per_cluster == 0)
|
||||
{
|
||||
|
||||
#ifdef FX_ENABLE_FAULT_TOLERANT
|
||||
FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
|
||||
#endif /* FX_ENABLE_FAULT_TOLERANT */
|
||||
|
||||
/* Release media protection. */
|
||||
FX_UNPROTECT
|
||||
|
||||
/* Invalid media, return error. */
|
||||
return(FX_MEDIA_INVALID);
|
||||
}
|
||||
|
||||
/* Setup the new file available size - if less than the current available size. */
|
||||
if (size < file_ptr -> fx_file_current_available_size)
|
||||
{
|
||||
|
||||
/* Yes, the file needs to be truncated. */
|
||||
|
||||
/* Update the available file size. */
|
||||
file_ptr -> fx_file_current_available_size = ((size + bytes_per_cluster - 1) / bytes_per_cluster) * bytes_per_cluster;
|
||||
|
||||
/* Is the new available size less than the actual file size? */
|
||||
if (size < file_ptr -> fx_file_current_file_size)
|
||||
{
|
||||
|
||||
/* Setup the new file size. */
|
||||
file_ptr -> fx_file_current_file_size = size;
|
||||
|
||||
/* Set the modified flag. */
|
||||
file_ptr -> fx_file_modified = FX_TRUE;
|
||||
|
||||
/* Copy the new file size into the directory entry. */
|
||||
file_ptr -> fx_file_dir_entry.fx_dir_entry_file_size = size;
|
||||
|
||||
/* Set the first cluster to NULL. */
|
||||
if (size == 0)
|
||||
{
|
||||
|
||||
/* Yes, the first cluster needs to be cleared since the entire
|
||||
file is going to be truncated. */
|
||||
file_ptr -> fx_file_dir_entry.fx_dir_entry_cluster = FX_NULL;
|
||||
}
|
||||
|
||||
/* Write the directory entry to the media. */
|
||||
status = _fx_directory_entry_write(media_ptr, &(file_ptr -> fx_file_dir_entry));
|
||||
|
||||
/* Check for a good 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
|
||||
|
||||
/* Error writing the directory. */
|
||||
return(status);
|
||||
}
|
||||
}
|
||||
|
||||
/* Update the trace event with the truncated size. */
|
||||
FX_TRACE_EVENT_UPDATE(trace_event, trace_timestamp, FX_TRACE_FILE_TRUNCATE_RELEASE, 0, 0, 0, file_ptr -> fx_file_current_file_size)
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* Update the trace event with the truncated size. */
|
||||
FX_TRACE_EVENT_UPDATE(trace_event, trace_timestamp, FX_TRACE_FILE_TRUNCATE_RELEASE, 0, 0, 0, file_ptr -> fx_file_current_file_size)
|
||||
|
||||
#ifdef FX_ENABLE_FAULT_TOLERANT
|
||||
FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
|
||||
#endif /* FX_ENABLE_FAULT_TOLERANT */
|
||||
|
||||
/* Release media protection. */
|
||||
FX_UNPROTECT
|
||||
|
||||
/* Just return, the truncate size is larger than the available size. */
|
||||
return(FX_SUCCESS);
|
||||
}
|
||||
|
||||
/* Calculate the number of bytes per cluster. */
|
||||
bytes_per_cluster = ((ULONG)media_ptr -> fx_media_bytes_per_sector) *
|
||||
((ULONG)media_ptr -> fx_media_sectors_per_cluster);
|
||||
|
||||
/* Now check to see if the read/write internal file pointers need
|
||||
to be adjusted. */
|
||||
if (file_ptr -> fx_file_current_file_offset > file_ptr -> fx_file_current_file_size)
|
||||
{
|
||||
|
||||
|
||||
/* At this point, we are ready to walk list of clusters to setup the
|
||||
seek position of this file. */
|
||||
cluster = file_ptr -> fx_file_first_physical_cluster;
|
||||
bytes_remaining = size;
|
||||
last_cluster = 0;
|
||||
cluster_count = 0;
|
||||
|
||||
/* Follow the link of FAT entries. */
|
||||
while ((cluster >= FX_FAT_ENTRY_START) && (cluster < media_ptr -> fx_media_fat_reserved))
|
||||
{
|
||||
|
||||
/* Increment the number of clusters. */
|
||||
cluster_count++;
|
||||
|
||||
|
||||
/* Read the current cluster entry from the FAT. */
|
||||
status = _fx_utility_FAT_entry_read(media_ptr, cluster, &contents);
|
||||
|
||||
/* Check the return value. */
|
||||
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 status. */
|
||||
return(status);
|
||||
}
|
||||
|
||||
/* Save the last valid cluster. */
|
||||
last_cluster = cluster;
|
||||
|
||||
/* Setup for the next cluster. */
|
||||
cluster = contents;
|
||||
|
||||
/* Determine if this is the last written cluster. */
|
||||
if (bytes_remaining >= bytes_per_cluster)
|
||||
{
|
||||
|
||||
/* Still more seeking, just decrement the working byte offset. */
|
||||
bytes_remaining = bytes_remaining - bytes_per_cluster;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* This is the cluster that contains the seek position. */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Check for errors in traversal of the FAT chain. */
|
||||
if (size > (((ULONG64) bytes_per_cluster) * ((ULONG64) cluster_count)))
|
||||
{
|
||||
|
||||
#ifdef FX_ENABLE_FAULT_TOLERANT
|
||||
FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
|
||||
#endif /* FX_ENABLE_FAULT_TOLERANT */
|
||||
|
||||
/* Release media protection. */
|
||||
FX_UNPROTECT
|
||||
|
||||
/* This is an error that suggests a corrupt file. */
|
||||
return(FX_FILE_CORRUPT);
|
||||
}
|
||||
|
||||
/* Position the pointers to the new offset. */
|
||||
file_ptr -> fx_file_current_physical_cluster = last_cluster;
|
||||
file_ptr -> fx_file_current_relative_cluster = cluster_count - 1;
|
||||
file_ptr -> fx_file_current_logical_sector = ((ULONG)media_ptr -> fx_media_data_sector_start) +
|
||||
(((ULONG64)file_ptr -> fx_file_current_physical_cluster - FX_FAT_ENTRY_START) *
|
||||
((ULONG)media_ptr -> fx_media_sectors_per_cluster)) +
|
||||
(bytes_remaining / (ULONG)media_ptr -> fx_media_bytes_per_sector);
|
||||
file_ptr -> fx_file_current_relative_sector = (UINT)((bytes_remaining / (ULONG)media_ptr -> fx_media_bytes_per_sector));
|
||||
file_ptr -> fx_file_current_file_offset = size;
|
||||
file_ptr -> fx_file_current_logical_offset = (ULONG)bytes_remaining % ((ULONG)media_ptr -> fx_media_bytes_per_sector);
|
||||
}
|
||||
|
||||
/* Determine how many clusters are actually in-use now. */
|
||||
cluster_count = (ULONG) (file_ptr -> fx_file_current_available_size + (((ULONG64) bytes_per_cluster) - ((ULONG64) 1)))/bytes_per_cluster;
|
||||
|
||||
/* Save the number of clusters in-use. */
|
||||
file_ptr -> fx_file_total_clusters = cluster_count;
|
||||
|
||||
/* At this point, we are ready to walk list of clusters to find the clusters
|
||||
that can be released. */
|
||||
cluster = file_ptr -> fx_file_first_physical_cluster;
|
||||
|
||||
#ifdef FX_ENABLE_FAULT_TOLERANT
|
||||
/* Is this the last used cluster? */
|
||||
if ((cluster_count == 0) && (media_ptr -> fx_media_fault_tolerant_enabled))
|
||||
{
|
||||
|
||||
/* Set undo log. */
|
||||
status = _fx_fault_tolerant_set_FAT_chain(media_ptr, FX_FALSE, FX_FREE_CLUSTER,
|
||||
media_ptr -> fx_media_fat_last, cluster, media_ptr -> fx_media_fat_last);
|
||||
|
||||
/* 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);
|
||||
}
|
||||
|
||||
file_ptr -> fx_file_last_physical_cluster = cluster;
|
||||
}
|
||||
#endif /* FX_ENABLE_FAULT_TOLERANT */
|
||||
|
||||
/* Follow the link of FAT entries. */
|
||||
while ((cluster >= FX_FAT_ENTRY_START) && (cluster < media_ptr -> fx_media_fat_reserved))
|
||||
{
|
||||
|
||||
/* Read the current cluster entry from the FAT. */
|
||||
status = _fx_utility_FAT_entry_read(media_ptr, cluster, &contents);
|
||||
|
||||
/* Check the return value. */
|
||||
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 status. */
|
||||
return(status);
|
||||
}
|
||||
|
||||
/* Determine if are more clusters to release. */
|
||||
if (cluster_count > 0)
|
||||
{
|
||||
|
||||
/* Decrement the number of clusters. */
|
||||
cluster_count--;
|
||||
|
||||
/* Is this the last used cluster? */
|
||||
if (cluster_count == 0)
|
||||
{
|
||||
{
|
||||
|
||||
#ifdef FX_ENABLE_FAULT_TOLERANT
|
||||
if (media_ptr -> fx_media_fault_tolerant_enabled)
|
||||
{
|
||||
|
||||
/* Set undo phase. */
|
||||
media_ptr -> fx_media_fault_tolerant_state |= FX_FAULT_TOLERANT_STATE_SET_FAT_CHAIN;
|
||||
|
||||
/* Read the current cluster entry from the FAT. */
|
||||
status = _fx_utility_FAT_entry_read(media_ptr, cluster, &contents);
|
||||
|
||||
/* Check the return value. */
|
||||
if (status != FX_SUCCESS)
|
||||
{
|
||||
|
||||
FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
|
||||
|
||||
/* Release media protection. */
|
||||
FX_UNPROTECT
|
||||
|
||||
/* Return the error status. */
|
||||
return(status);
|
||||
}
|
||||
|
||||
/* Set undo log. */
|
||||
status = _fx_fault_tolerant_set_FAT_chain(media_ptr, FX_FALSE, cluster,
|
||||
media_ptr -> fx_media_fat_last, contents, media_ptr -> fx_media_fat_last);
|
||||
|
||||
/* 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 */
|
||||
|
||||
/* Yes, it should be designated as last cluster. */
|
||||
status = _fx_utility_FAT_entry_write(media_ptr, cluster, media_ptr -> fx_media_fat_last);
|
||||
|
||||
/* Check the return value. */
|
||||
if (status)
|
||||
{
|
||||
|
||||
#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 status. */
|
||||
return(status);
|
||||
}
|
||||
|
||||
#ifdef FX_ENABLE_FAULT_TOLERANT
|
||||
if (media_ptr -> fx_media_fault_tolerant_enabled)
|
||||
{
|
||||
|
||||
/* Clear undo phase. */
|
||||
media_ptr -> fx_media_fault_tolerant_state &= (UCHAR)(~FX_FAULT_TOLERANT_STATE_SET_FAT_CHAIN & 0xff);
|
||||
}
|
||||
#endif /* FX_ENABLE_FAULT_TOLERANT */
|
||||
}
|
||||
|
||||
file_ptr -> fx_file_last_physical_cluster = cluster;
|
||||
|
||||
#ifdef FX_FAULT_TOLERANT
|
||||
|
||||
/* Flush the cached individual FAT entries. */
|
||||
status = _fx_utility_FAT_flush(media_ptr);
|
||||
|
||||
/* Check the return value. */
|
||||
if (status)
|
||||
{
|
||||
|
||||
#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 status. */
|
||||
return(status);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* This is a cluster after the clusters used by the file, release
|
||||
it back to the media. */
|
||||
|
||||
#ifdef FX_ENABLE_FAULT_TOLERANT
|
||||
if (media_ptr -> fx_media_fault_tolerant_enabled == FX_FALSE)
|
||||
{
|
||||
#endif /* FX_ENABLE_FAULT_TOLERANT */
|
||||
|
||||
status = _fx_utility_FAT_entry_write(media_ptr, cluster, FX_FREE_CLUSTER);
|
||||
|
||||
/* Check the return value. */
|
||||
if (status)
|
||||
{
|
||||
|
||||
#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 status. */
|
||||
return(status);
|
||||
}
|
||||
|
||||
/* Increment the number of available clusters. */
|
||||
media_ptr -> fx_media_available_clusters++;
|
||||
|
||||
#ifdef FX_ENABLE_FAULT_TOLERANT
|
||||
}
|
||||
#endif /* FX_ENABLE_FAULT_TOLERANT */
|
||||
}
|
||||
|
||||
/* Setup for the next cluster. */
|
||||
cluster = contents;
|
||||
}
|
||||
|
||||
/* Determine if we need to adjust the number of leading consecutive clusters. */
|
||||
if (file_ptr -> fx_file_consecutive_cluster > file_ptr -> fx_file_total_clusters)
|
||||
{
|
||||
|
||||
/* Adjust the leading consecutive cluster count. */
|
||||
file_ptr -> fx_file_consecutive_cluster = file_ptr -> fx_file_total_clusters;
|
||||
}
|
||||
|
||||
/* Determine if the file available size has been truncated to zero. */
|
||||
if (file_ptr -> fx_file_current_available_size == 0)
|
||||
{
|
||||
|
||||
/* Yes, the first cluster has already been released. Update the file info
|
||||
to indicate the file has no clusters. */
|
||||
file_ptr -> fx_file_last_physical_cluster = 0;
|
||||
file_ptr -> fx_file_first_physical_cluster = 0;
|
||||
file_ptr -> fx_file_current_physical_cluster = 0;
|
||||
file_ptr -> fx_file_current_logical_sector = 0;
|
||||
file_ptr -> fx_file_current_relative_cluster = 0;
|
||||
file_ptr -> fx_file_current_relative_sector = 0;
|
||||
file_ptr -> fx_file_current_available_size = 0;
|
||||
file_ptr -> fx_file_consecutive_cluster = 1;
|
||||
}
|
||||
|
||||
#ifndef FX_DONT_UPDATE_OPEN_FILES
|
||||
|
||||
/* Search the opened files list to see if the same file is opened for reading. */
|
||||
open_count = media_ptr -> fx_media_opened_file_count;
|
||||
search_ptr = media_ptr -> fx_media_opened_file_list;
|
||||
while (open_count)
|
||||
{
|
||||
|
||||
/* Is this file the same file opened for reading? */
|
||||
if ((search_ptr != file_ptr) &&
|
||||
(search_ptr -> fx_file_dir_entry.fx_dir_entry_log_sector ==
|
||||
file_ptr -> fx_file_dir_entry.fx_dir_entry_log_sector) &&
|
||||
(search_ptr -> fx_file_dir_entry.fx_dir_entry_byte_offset ==
|
||||
file_ptr -> fx_file_dir_entry.fx_dir_entry_byte_offset))
|
||||
{
|
||||
|
||||
/* Yes, the same file is opened for reading. */
|
||||
|
||||
/* Setup the new file size. */
|
||||
search_ptr -> fx_file_current_file_size = size;
|
||||
|
||||
/* Setup the new total clusters. */
|
||||
search_ptr -> fx_file_total_clusters = file_ptr -> fx_file_total_clusters;
|
||||
|
||||
/* Copy the directory entry. */
|
||||
search_ptr -> fx_file_dir_entry.fx_dir_entry_cluster = file_ptr -> fx_file_dir_entry.fx_dir_entry_cluster;
|
||||
search_ptr -> fx_file_dir_entry.fx_dir_entry_file_size = file_ptr -> fx_file_dir_entry.fx_dir_entry_file_size;
|
||||
search_ptr -> fx_file_dir_entry.fx_dir_entry_log_sector = file_ptr -> fx_file_dir_entry.fx_dir_entry_log_sector;
|
||||
search_ptr -> fx_file_dir_entry.fx_dir_entry_byte_offset = file_ptr -> fx_file_dir_entry.fx_dir_entry_byte_offset;
|
||||
|
||||
/* Setup the other file parameters. */
|
||||
search_ptr -> fx_file_last_physical_cluster = file_ptr -> fx_file_last_physical_cluster;
|
||||
search_ptr -> fx_file_first_physical_cluster = file_ptr -> fx_file_first_physical_cluster;
|
||||
search_ptr -> fx_file_current_available_size = file_ptr -> fx_file_current_available_size;
|
||||
search_ptr -> fx_file_consecutive_cluster = file_ptr -> fx_file_consecutive_cluster;
|
||||
|
||||
/* Determine if the truncated file is smaller than the current file offset. */
|
||||
if (search_ptr -> fx_file_current_file_offset > size)
|
||||
{
|
||||
|
||||
/* Yes, the current file parameters need to be changed since the file was
|
||||
truncated to a position prior to the current file position. */
|
||||
|
||||
/* Calculate the number of bytes per cluster. */
|
||||
bytes_per_cluster = ((ULONG)media_ptr -> fx_media_bytes_per_sector) *
|
||||
((ULONG)media_ptr -> fx_media_sectors_per_cluster);
|
||||
|
||||
/* At this point, we are ready to walk list of clusters to setup the
|
||||
seek position of this file. */
|
||||
cluster = search_ptr -> fx_file_first_physical_cluster;
|
||||
bytes_remaining = size;
|
||||
last_cluster = 0;
|
||||
cluster_count = 0;
|
||||
|
||||
/* Follow the link of FAT entries. */
|
||||
while ((cluster >= FX_FAT_ENTRY_START) && (cluster < media_ptr -> fx_media_fat_reserved))
|
||||
{
|
||||
|
||||
/* Increment the number of clusters. */
|
||||
cluster_count++;
|
||||
|
||||
|
||||
/* Read the current cluster entry from the FAT. */
|
||||
status = _fx_utility_FAT_entry_read(media_ptr, cluster, &contents);
|
||||
|
||||
/* Check the return value. */
|
||||
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 status. */
|
||||
return(status);
|
||||
}
|
||||
|
||||
/* Save the last valid cluster. */
|
||||
last_cluster = cluster;
|
||||
|
||||
/* Setup for the next cluster. */
|
||||
cluster = contents;
|
||||
|
||||
/* Determine if this is the last written cluster. */
|
||||
if (bytes_remaining >= bytes_per_cluster)
|
||||
{
|
||||
|
||||
/* Still more seeking, just decrement the working byte offset. */
|
||||
bytes_remaining = bytes_remaining - bytes_per_cluster;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* This is the cluster that contains the seek position. */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Check for errors in traversal of the FAT chain. */
|
||||
if (size > (((ULONG64) bytes_per_cluster) * ((ULONG64) cluster_count)))
|
||||
{
|
||||
|
||||
#ifdef FX_ENABLE_FAULT_TOLERANT
|
||||
FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
|
||||
#endif /* FX_ENABLE_FAULT_TOLERANT */
|
||||
|
||||
/* Release media protection. */
|
||||
FX_UNPROTECT
|
||||
|
||||
/* This is an error that suggests a corrupt file. */
|
||||
return(FX_FILE_CORRUPT);
|
||||
}
|
||||
|
||||
/* Position the pointers to the new offset. */
|
||||
|
||||
/* Determine if there is at least one cluster. */
|
||||
if (cluster_count)
|
||||
{
|
||||
|
||||
/* Calculate real file parameters. */
|
||||
search_ptr -> fx_file_current_physical_cluster = last_cluster;
|
||||
search_ptr -> fx_file_current_relative_cluster = cluster_count - 1;
|
||||
search_ptr -> fx_file_current_logical_sector = ((ULONG)media_ptr -> fx_media_data_sector_start) +
|
||||
(((ULONG64)search_ptr -> fx_file_current_physical_cluster - FX_FAT_ENTRY_START) *
|
||||
((ULONG)media_ptr -> fx_media_sectors_per_cluster)) +
|
||||
(bytes_remaining / (ULONG)media_ptr -> fx_media_bytes_per_sector);
|
||||
search_ptr -> fx_file_current_relative_sector = (UINT)((bytes_remaining / (ULONG)media_ptr -> fx_media_bytes_per_sector));
|
||||
search_ptr -> fx_file_current_file_offset = size;
|
||||
search_ptr -> fx_file_current_logical_offset = (ULONG)bytes_remaining % ((ULONG)media_ptr -> fx_media_bytes_per_sector);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* Calculate zero-length file parameters. */
|
||||
search_ptr -> fx_file_current_physical_cluster = 0;
|
||||
search_ptr -> fx_file_current_relative_cluster = 0;
|
||||
search_ptr -> fx_file_current_logical_sector = 0;
|
||||
search_ptr -> fx_file_current_relative_sector = 0;
|
||||
search_ptr -> fx_file_current_file_offset = 0;
|
||||
search_ptr -> fx_file_current_logical_offset = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Adjust the pointer and decrement the search count. */
|
||||
search_ptr = search_ptr -> fx_file_opened_next;
|
||||
open_count--;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef FX_FAULT_TOLERANT
|
||||
|
||||
/* Flush the cached individual FAT entries */
|
||||
status = _fx_utility_FAT_flush(media_ptr);
|
||||
|
||||
/* Check the return value. */
|
||||
if (status)
|
||||
{
|
||||
|
||||
#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 status. */
|
||||
return(status);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef FX_ENABLE_FAULT_TOLERANT
|
||||
if (media_ptr -> fx_media_fault_tolerant_enabled &&
|
||||
(media_ptr -> fx_media_fault_tolerant_state & FX_FAULT_TOLERANT_STATE_STARTED))
|
||||
{
|
||||
|
||||
/* Copy the new file size into the directory entry. */
|
||||
file_ptr -> fx_file_dir_entry.fx_dir_entry_file_size = file_ptr -> fx_file_current_file_size;
|
||||
}
|
||||
|
||||
/* Write the directory entry to the media. */
|
||||
status = _fx_directory_entry_write(media_ptr, &(file_ptr -> fx_file_dir_entry));
|
||||
|
||||
/* Check for a good status. */
|
||||
if (status != FX_SUCCESS)
|
||||
{
|
||||
|
||||
FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
|
||||
|
||||
/* Release media protection. */
|
||||
FX_UNPROTECT
|
||||
|
||||
/* Error writing the directory. */
|
||||
return(status);
|
||||
}
|
||||
|
||||
/* End transaction. */
|
||||
status = _fx_fault_tolerant_transaction_end(media_ptr);
|
||||
|
||||
/* Check for a bad status. */
|
||||
if (status != FX_SUCCESS)
|
||||
{
|
||||
|
||||
/* Release media protection. */
|
||||
FX_UNPROTECT
|
||||
|
||||
/* Return the bad status. */
|
||||
return(status);
|
||||
}
|
||||
|
||||
/* Update maximum size used if necessary. */
|
||||
if (size < file_ptr -> fx_file_maximum_size_used)
|
||||
{
|
||||
file_ptr -> fx_file_maximum_size_used = size;
|
||||
}
|
||||
#endif /* FX_ENABLE_FAULT_TOLERANT */
|
||||
|
||||
/* Release media protection. */
|
||||
FX_UNPROTECT
|
||||
|
||||
/* Truncate is complete, return successful status. */
|
||||
return(FX_SUCCESS);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,543 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** FileX Component */
|
||||
/** */
|
||||
/** File */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
#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"
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _fx_file_open PORTABLE C */
|
||||
/* 6.1 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function first attempts to find the specified file. If found, */
|
||||
/* the open request is validated and the file is opened. During the */
|
||||
/* opening process, all of the FAT entries for this file are examined */
|
||||
/* for their integrity. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* media_ptr Media control block pointer */
|
||||
/* file_ptr File control block pointer */
|
||||
/* file_name Name pointer */
|
||||
/* open_type Type of open requested */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* return status */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* _fx_directory_search Search for the file name in */
|
||||
/* the directory structure */
|
||||
/* _fx_utility_FAT_entry_read Read a FAT entry */
|
||||
/* */
|
||||
/* 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), and */
|
||||
/* added conditional to */
|
||||
/* disable fast open and */
|
||||
/* consecutive detect, */
|
||||
/* resulting in version 6.1 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
UINT _fx_file_open(FX_MEDIA *media_ptr, FX_FILE *file_ptr, CHAR *file_name, UINT open_type)
|
||||
{
|
||||
|
||||
UINT status;
|
||||
#ifndef FX_DISABLE_CONSECUTIVE_DETECT
|
||||
UINT leading_consecutive;
|
||||
#endif /* FX_DISABLE_CONSECUTIVE_DETECT */
|
||||
ULONG cluster;
|
||||
ULONG contents = 0;
|
||||
ULONG open_count;
|
||||
FX_FILE *tail_ptr;
|
||||
FX_FILE *search_ptr;
|
||||
ULONG bytes_per_cluster;
|
||||
UINT last_cluster;
|
||||
ULONG cluster_count;
|
||||
ULONG64 bytes_available;
|
||||
ULONG64 bytes_remaining;
|
||||
ULONG fat_last;
|
||||
#ifndef FX_DISABLE_FAST_OPEN
|
||||
UINT fast_open;
|
||||
#endif /* FX_DISABLE_FAST_OPEN */
|
||||
UCHAR not_a_file_attr;
|
||||
|
||||
|
||||
/* 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);
|
||||
}
|
||||
|
||||
#ifndef FX_MEDIA_STATISTICS_DISABLE
|
||||
|
||||
/* Increment the number of times this service has been called. */
|
||||
media_ptr -> fx_media_file_opens++;
|
||||
#endif
|
||||
|
||||
/* Clear the notify function. */
|
||||
file_ptr -> fx_file_write_notify = FX_NULL;
|
||||
|
||||
/* Determine the type of FAT and setup variables accordingly. */
|
||||
if (media_ptr -> fx_media_32_bit_FAT)
|
||||
{
|
||||
fat_last = FX_LAST_CLUSTER_1_32;
|
||||
not_a_file_attr = FX_DIRECTORY | FX_VOLUME;
|
||||
}
|
||||
else
|
||||
{
|
||||
fat_last = FX_LAST_CLUSTER_1;
|
||||
not_a_file_attr = FX_DIRECTORY | FX_VOLUME;
|
||||
}
|
||||
|
||||
#ifndef FX_DISABLE_FAST_OPEN
|
||||
/* Determine if a fast open is selected. */
|
||||
if (open_type == FX_OPEN_FOR_READ_FAST)
|
||||
{
|
||||
|
||||
/* Yes, convert the open type to a standard read. */
|
||||
open_type = FX_OPEN_FOR_READ;
|
||||
|
||||
/* Set the open fast flag. */
|
||||
fast_open = FX_TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* A fast open is not selected, set the flag to false. */
|
||||
fast_open = FX_FALSE;
|
||||
}
|
||||
#endif /* FX_DISABLE_FAST_OPEN */
|
||||
|
||||
/* If trace is enabled, register this object. */
|
||||
FX_TRACE_OBJECT_REGISTER(FX_TRACE_OBJECT_TYPE_FILE, file_ptr, file_name, 0, 0)
|
||||
|
||||
/* If trace is enabled, insert this event into the trace buffer. */
|
||||
FX_TRACE_IN_LINE_INSERT(FX_TRACE_FILE_OPEN, media_ptr, file_ptr, file_name, open_type, FX_TRACE_FILE_EVENTS, 0, 0)
|
||||
|
||||
/* Protect against other threads accessing the media. */
|
||||
FX_PROTECT
|
||||
|
||||
/* Setup file name pointer. */
|
||||
file_ptr -> fx_file_dir_entry.fx_dir_entry_name = file_ptr -> fx_file_name_buffer;
|
||||
file_ptr -> fx_file_dir_entry.fx_dir_entry_short_name[0] = 0;
|
||||
|
||||
/* Search the system for the supplied file name. */
|
||||
status = _fx_directory_search(media_ptr, file_name, &(file_ptr -> fx_file_dir_entry), FX_NULL, FX_NULL);
|
||||
|
||||
/* Determine if the search was successful. */
|
||||
if (status != FX_SUCCESS)
|
||||
{
|
||||
|
||||
/* Release media protection. */
|
||||
FX_UNPROTECT
|
||||
|
||||
/* Return the error code. */
|
||||
return(status);
|
||||
}
|
||||
|
||||
/* Check to make sure the found entry is a file. */
|
||||
if (file_ptr -> fx_file_dir_entry.fx_dir_entry_attributes & not_a_file_attr)
|
||||
{
|
||||
|
||||
/* Release media protection. */
|
||||
FX_UNPROTECT
|
||||
|
||||
/* Return the not a file error code. */
|
||||
return(FX_NOT_A_FILE);
|
||||
}
|
||||
|
||||
#ifdef FX_SINGLE_OPEN_LEGACY
|
||||
/* Check to make sure the access is okay. */
|
||||
if (open_type == FX_OPEN_FOR_READ)
|
||||
{
|
||||
|
||||
/* Check the list of open files for others open for writing. */
|
||||
open_count = media_ptr -> fx_media_opened_file_count;
|
||||
search_ptr = media_ptr -> fx_media_opened_file_list;
|
||||
while (open_count)
|
||||
{
|
||||
|
||||
/* Look at each opened file to see if the same file is opened
|
||||
for writing. */
|
||||
if ((search_ptr -> fx_file_dir_entry.fx_dir_entry_log_sector ==
|
||||
file_ptr -> fx_file_dir_entry.fx_dir_entry_log_sector) &&
|
||||
(search_ptr -> fx_file_dir_entry.fx_dir_entry_byte_offset ==
|
||||
file_ptr -> fx_file_dir_entry.fx_dir_entry_byte_offset) &&
|
||||
(search_ptr -> fx_file_open_mode))
|
||||
{
|
||||
|
||||
/* Release media protection. */
|
||||
FX_UNPROTECT
|
||||
|
||||
/* The file has been opened for writing by a previous call. */
|
||||
return(FX_ACCESS_ERROR);
|
||||
}
|
||||
|
||||
/* Adjust the pointer and decrement the search count. */
|
||||
search_ptr = search_ptr -> fx_file_opened_next;
|
||||
open_count--;
|
||||
}
|
||||
}
|
||||
else
|
||||
#else
|
||||
if (open_type == FX_OPEN_FOR_WRITE)
|
||||
#endif
|
||||
{
|
||||
|
||||
/* A open for write request is present, check the file attributes
|
||||
and the list of open files for any other open instance of
|
||||
this file. */
|
||||
if (media_ptr -> fx_media_driver_write_protect)
|
||||
{
|
||||
|
||||
/* Release media protection. */
|
||||
FX_UNPROTECT
|
||||
|
||||
/* Return write protect error. */
|
||||
return(FX_WRITE_PROTECT);
|
||||
}
|
||||
|
||||
if (file_ptr -> fx_file_dir_entry.fx_dir_entry_attributes & (UCHAR)(FX_READ_ONLY))
|
||||
{
|
||||
|
||||
/* Release media protection. */
|
||||
FX_UNPROTECT
|
||||
|
||||
/* Return the not a file error code. */
|
||||
return(FX_ACCESS_ERROR);
|
||||
}
|
||||
|
||||
/* Also search the opened files to see if this file is currently
|
||||
opened. */
|
||||
open_count = media_ptr -> fx_media_opened_file_count;
|
||||
search_ptr = media_ptr -> fx_media_opened_file_list;
|
||||
while (open_count)
|
||||
{
|
||||
|
||||
/* Look at each opened file to see if the same file is already opened. */
|
||||
#ifdef FX_SINGLE_OPEN_LEGACY
|
||||
if ((search_ptr -> fx_file_dir_entry.fx_dir_entry_log_sector ==
|
||||
file_ptr -> fx_file_dir_entry.fx_dir_entry_log_sector) &&
|
||||
(search_ptr -> fx_file_dir_entry.fx_dir_entry_byte_offset ==
|
||||
file_ptr -> fx_file_dir_entry.fx_dir_entry_byte_offset))
|
||||
#else
|
||||
/* Look at each opened file to see if the same file is already opened
|
||||
for writing. */
|
||||
if ((search_ptr -> fx_file_dir_entry.fx_dir_entry_log_sector ==
|
||||
file_ptr -> fx_file_dir_entry.fx_dir_entry_log_sector) &&
|
||||
(search_ptr -> fx_file_dir_entry.fx_dir_entry_byte_offset ==
|
||||
file_ptr -> fx_file_dir_entry.fx_dir_entry_byte_offset) &&
|
||||
(search_ptr -> fx_file_open_mode == FX_OPEN_FOR_WRITE))
|
||||
#endif
|
||||
{
|
||||
|
||||
/* Release media protection. */
|
||||
FX_UNPROTECT
|
||||
|
||||
/* The file is currently open. */
|
||||
return(FX_ACCESS_ERROR);
|
||||
}
|
||||
|
||||
/* Adjust the pointer and decrement the search count. */
|
||||
search_ptr = search_ptr -> fx_file_opened_next;
|
||||
open_count--;
|
||||
}
|
||||
}
|
||||
|
||||
/* At this point, we are ready to walk list of clusters to setup the
|
||||
initial condition of this file as well as to verify its integrity. */
|
||||
cluster = file_ptr -> fx_file_dir_entry.fx_dir_entry_cluster;
|
||||
bytes_remaining = file_ptr -> fx_file_dir_entry.fx_dir_entry_file_size;
|
||||
bytes_per_cluster = ((ULONG)media_ptr -> fx_media_bytes_per_sector) *
|
||||
((ULONG)media_ptr -> fx_media_sectors_per_cluster);
|
||||
file_ptr -> fx_file_current_physical_cluster = 0;
|
||||
|
||||
/* Check for invalid value. */
|
||||
if (bytes_per_cluster == 0)
|
||||
{
|
||||
|
||||
/* Release media protection. */
|
||||
FX_UNPROTECT
|
||||
|
||||
/* Invalid media, return error. */
|
||||
return(FX_MEDIA_INVALID);
|
||||
}
|
||||
|
||||
last_cluster = 0;
|
||||
cluster_count = 0;
|
||||
|
||||
#ifndef FX_DISABLE_CONSECUTIVE_DETECT
|
||||
leading_consecutive = 1;
|
||||
#endif /* FX_DISABLE_CONSECUTIVE_DETECT */
|
||||
file_ptr -> fx_file_consecutive_cluster = 1;
|
||||
#ifndef FX_DISABLE_FAST_OPEN
|
||||
|
||||
/* Determine if the file is being open for reading with the fast option. */
|
||||
if (fast_open)
|
||||
{
|
||||
|
||||
/* Calculate the bytes available. */
|
||||
bytes_available = ((bytes_remaining + bytes_per_cluster - 1) / bytes_per_cluster) * bytes_per_cluster;
|
||||
|
||||
}
|
||||
else
|
||||
#endif /* FX_DISABLE_FAST_OPEN */
|
||||
{
|
||||
|
||||
/* Follow the link of FAT entries. */
|
||||
while ((cluster >= FX_FAT_ENTRY_START) && (cluster < media_ptr -> fx_media_fat_reserved))
|
||||
{
|
||||
|
||||
/* Increment the number of clusters. */
|
||||
cluster_count++;
|
||||
|
||||
/* Read the current cluster entry from the FAT. */
|
||||
status = _fx_utility_FAT_entry_read(media_ptr, cluster, &contents);
|
||||
|
||||
/* Check the return value. */
|
||||
if (status != FX_SUCCESS)
|
||||
{
|
||||
|
||||
/* Release media protection. */
|
||||
FX_UNPROTECT
|
||||
|
||||
/* Return the error status. */
|
||||
return(status);
|
||||
}
|
||||
|
||||
/* Determine if the cluster is invalid (points to itself) or the count exceeds the total number of clusters. */
|
||||
if ((cluster == contents) || (cluster_count > media_ptr -> fx_media_total_clusters))
|
||||
{
|
||||
|
||||
/* Release media protection. */
|
||||
FX_UNPROTECT
|
||||
|
||||
/* Return the bad status. */
|
||||
return(FX_FAT_READ_ERROR);
|
||||
}
|
||||
|
||||
#ifndef FX_DISABLE_CONSECUTIVE_DETECT
|
||||
|
||||
/* Check if present and next clusters are consecutive */
|
||||
if (cluster + 1 == contents)
|
||||
{
|
||||
|
||||
/* Determine if clusters are consecutive so far. */
|
||||
if (leading_consecutive)
|
||||
{
|
||||
|
||||
/* Yes, increment the number of leading consecutive clusters. */
|
||||
file_ptr -> fx_file_consecutive_cluster++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* The clusters are no longer consecutive, clear the consecutive flag. */
|
||||
leading_consecutive = 0;
|
||||
}
|
||||
#endif /* FX_DISABLE_CONSECUTIVE_DETECT */
|
||||
|
||||
/* Save the last valid cluster. */
|
||||
last_cluster = cluster;
|
||||
|
||||
/* Setup for the next cluster. */
|
||||
cluster = contents;
|
||||
|
||||
/* Determine if this is the last written cluster. We need to remember this
|
||||
for open for writing. */
|
||||
if (bytes_remaining > bytes_per_cluster)
|
||||
{
|
||||
|
||||
/* Still more written clusters, just decrement the counter. */
|
||||
bytes_remaining = bytes_remaining - bytes_per_cluster;
|
||||
}
|
||||
else if (!file_ptr -> fx_file_current_physical_cluster)
|
||||
{
|
||||
|
||||
/* Remember this cluster number. */
|
||||
file_ptr -> fx_file_current_physical_cluster = last_cluster;
|
||||
|
||||
/* Remember the relative cluster. */
|
||||
file_ptr -> fx_file_current_relative_cluster = cluster_count - 1;
|
||||
|
||||
/* If the remaining bytes exactly fits the cluster size, check for
|
||||
a possible adjustment to the next cluster. */
|
||||
if ((bytes_remaining == bytes_per_cluster) &&
|
||||
(cluster >= FX_FAT_ENTRY_START) && (cluster < media_ptr -> fx_media_fat_reserved))
|
||||
{
|
||||
|
||||
/* We need to position to next allocated cluster. */
|
||||
file_ptr -> fx_file_current_physical_cluster = cluster;
|
||||
file_ptr -> fx_file_current_relative_cluster++;
|
||||
|
||||
/* Clear the remaining bytes. */
|
||||
bytes_remaining = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Determine if the number of clusters is large enough to support the
|
||||
specified file size. */
|
||||
bytes_available = ((ULONG64)media_ptr -> fx_media_bytes_per_sector) *
|
||||
((ULONG64)media_ptr -> fx_media_sectors_per_cluster) *
|
||||
((ULONG64)cluster_count);
|
||||
|
||||
/* Check the bytes available in the cluster chain against the directory entry file size. */
|
||||
if ((bytes_available < file_ptr -> fx_file_dir_entry.fx_dir_entry_file_size) ||
|
||||
((cluster_count) && (contents < fat_last)))
|
||||
{
|
||||
/* File is corrupt, release media protection. */
|
||||
FX_UNPROTECT
|
||||
|
||||
/* Return a corrupt file error status. */
|
||||
return(FX_FILE_CORRUPT);
|
||||
}
|
||||
}
|
||||
|
||||
/* The file is okay, populate the file control block and complete the
|
||||
file open process. */
|
||||
file_ptr -> fx_file_id = FX_FILE_ID;
|
||||
file_ptr -> fx_file_name = file_ptr -> fx_file_name_buffer;
|
||||
file_ptr -> fx_file_media_ptr = media_ptr;
|
||||
file_ptr -> fx_file_open_mode = open_type;
|
||||
file_ptr -> fx_file_modified = FX_FALSE;
|
||||
file_ptr -> fx_file_total_clusters = cluster_count;
|
||||
file_ptr -> fx_file_first_physical_cluster = file_ptr -> fx_file_dir_entry.fx_dir_entry_cluster;
|
||||
file_ptr -> fx_file_last_physical_cluster = last_cluster;
|
||||
file_ptr -> fx_file_current_file_size = file_ptr -> fx_file_dir_entry.fx_dir_entry_file_size;
|
||||
file_ptr -> fx_file_current_available_size = bytes_available;
|
||||
file_ptr -> fx_file_disable_burst_cache = FX_FALSE;
|
||||
|
||||
/* Set the current settings based on how the file was opened. */
|
||||
if (open_type == FX_OPEN_FOR_READ)
|
||||
{
|
||||
|
||||
/* Position the pointers to the beginning of the file. */
|
||||
file_ptr -> fx_file_current_physical_cluster = file_ptr -> fx_file_first_physical_cluster;
|
||||
file_ptr -> fx_file_current_relative_cluster = 0;
|
||||
file_ptr -> fx_file_current_logical_sector = ((ULONG)media_ptr -> fx_media_data_sector_start) +
|
||||
(((ULONG64)(file_ptr -> fx_file_first_physical_cluster - FX_FAT_ENTRY_START)) *
|
||||
((ULONG)media_ptr -> fx_media_sectors_per_cluster));
|
||||
file_ptr -> fx_file_current_relative_sector = 0;
|
||||
file_ptr -> fx_file_current_logical_offset = 0;
|
||||
file_ptr -> fx_file_current_file_offset = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* Open for writing - position the pointers to the end of the file. */
|
||||
|
||||
/* Determine if the remaining bytes fit exactly into the cluster size. */
|
||||
if (bytes_remaining == bytes_per_cluster)
|
||||
{
|
||||
|
||||
/* Position to the end of the cluster. */
|
||||
file_ptr -> fx_file_current_logical_sector = ((ULONG)media_ptr -> fx_media_data_sector_start) +
|
||||
(((ULONG64)file_ptr -> fx_file_current_physical_cluster - FX_FAT_ENTRY_START) *
|
||||
((ULONG)media_ptr -> fx_media_sectors_per_cluster)) +
|
||||
((ULONG)(((bytes_remaining - 1) / (ULONG)media_ptr -> fx_media_bytes_per_sector)));
|
||||
file_ptr -> fx_file_current_relative_sector = (ULONG)(((bytes_remaining - 1) / (ULONG)media_ptr -> fx_media_bytes_per_sector));
|
||||
file_ptr -> fx_file_current_file_offset = file_ptr -> fx_file_current_file_size;
|
||||
file_ptr -> fx_file_current_logical_offset = media_ptr -> fx_media_bytes_per_sector;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* Position file parameters at end of last cluster allocation. */
|
||||
file_ptr -> fx_file_current_logical_sector = ((ULONG)media_ptr -> fx_media_data_sector_start) +
|
||||
(((ULONG64)file_ptr -> fx_file_current_physical_cluster - FX_FAT_ENTRY_START) *
|
||||
((ULONG)media_ptr -> fx_media_sectors_per_cluster)) +
|
||||
((ULONG)((bytes_remaining / (ULONG)media_ptr -> fx_media_bytes_per_sector)));
|
||||
file_ptr -> fx_file_current_relative_sector = (ULONG)((bytes_remaining / (ULONG)media_ptr -> fx_media_bytes_per_sector));
|
||||
file_ptr -> fx_file_current_file_offset = file_ptr -> fx_file_current_file_size;
|
||||
file_ptr -> fx_file_current_logical_offset = (ULONG)bytes_remaining % ((ULONG)media_ptr -> fx_media_bytes_per_sector);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef FX_ENABLE_FAULT_TOLERANT
|
||||
/* By default, the whole file is used. */
|
||||
file_ptr -> fx_file_maximum_size_used = file_ptr -> fx_file_current_file_size;
|
||||
#endif /* FX_ENABLE_FAULT_TOLERANT */
|
||||
|
||||
/* Place newly opened file on the list of open files for
|
||||
this media. First, check for an empty list. */
|
||||
if (media_ptr -> fx_media_opened_file_list)
|
||||
{
|
||||
|
||||
/* Pickup tail pointer. */
|
||||
tail_ptr = (media_ptr -> fx_media_opened_file_list) -> fx_file_opened_previous;
|
||||
|
||||
/* Place the new file in the list. */
|
||||
(media_ptr -> fx_media_opened_file_list) -> fx_file_opened_previous = file_ptr;
|
||||
tail_ptr -> fx_file_opened_next = file_ptr;
|
||||
|
||||
/* Setup this file's opened links. */
|
||||
file_ptr -> fx_file_opened_previous = tail_ptr;
|
||||
file_ptr -> fx_file_opened_next = media_ptr -> fx_media_opened_file_list;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* The opened media list is empty. Add the media to empty list. */
|
||||
media_ptr -> fx_media_opened_file_list = file_ptr;
|
||||
file_ptr -> fx_file_opened_next = file_ptr;
|
||||
file_ptr -> fx_file_opened_previous = file_ptr;
|
||||
}
|
||||
|
||||
/* Increment the opened file counter. */
|
||||
media_ptr -> fx_media_opened_file_count++;
|
||||
|
||||
/* Release media protection. */
|
||||
FX_UNPROTECT
|
||||
|
||||
/* Open is complete, return successful status. */
|
||||
return(FX_SUCCESS);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,441 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** FileX Component */
|
||||
/** */
|
||||
/** File */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
#define FX_SOURCE_CODE
|
||||
|
||||
|
||||
/* Include necessary system files. */
|
||||
|
||||
#include "fx_api.h"
|
||||
#include "fx_system.h"
|
||||
#include "fx_file.h"
|
||||
#include "fx_utility.h"
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _fx_file_read PORTABLE C */
|
||||
/* 6.1 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function reads the specified number of bytes (or as many as */
|
||||
/* possible into the buffer supplied by the caller. The actual number */
|
||||
/* of bytes and the status of the read operation is returned to the */
|
||||
/* caller. In addition, various internal file pointers in the file */
|
||||
/* control block are also updated. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* file_ptr File control block pointer */
|
||||
/* buffer_ptr Buffer pointer */
|
||||
/* request_size Number of bytes requested */
|
||||
/* actual_size Pointer to variable for the */
|
||||
/* number of bytes read */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* return status */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* _fx_utility_FAT_entry_read Read a FAT entry */
|
||||
/* _fx_utility_logical_sector_read Read a logical sector */
|
||||
/* _fx_utility_memory_copy Fast memory copy routine */
|
||||
/* */
|
||||
/* 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), verified */
|
||||
/* memcpy usage, */
|
||||
/* resulting in version 6.1 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
UINT _fx_file_read(FX_FILE *file_ptr, VOID *buffer_ptr, ULONG request_size, ULONG *actual_size)
|
||||
{
|
||||
|
||||
UINT status;
|
||||
ULONG bytes_remaining, i;
|
||||
ULONG copy_bytes;
|
||||
UCHAR *destination_ptr;
|
||||
ULONG cluster, next_cluster;
|
||||
UINT sectors;
|
||||
FX_MEDIA *media_ptr;
|
||||
|
||||
#ifdef TX_ENABLE_EVENT_TRACE
|
||||
TX_TRACE_BUFFER_ENTRY *trace_event;
|
||||
ULONG trace_timestamp;
|
||||
#endif
|
||||
|
||||
|
||||
/* First, determine if the file is still open. */
|
||||
if (file_ptr -> fx_file_id != FX_FILE_ID)
|
||||
{
|
||||
|
||||
/* Return the file not open error status. */
|
||||
return(FX_NOT_OPEN);
|
||||
}
|
||||
|
||||
#ifndef FX_MEDIA_STATISTICS_DISABLE
|
||||
/* Setup pointer to media structure. */
|
||||
media_ptr = file_ptr -> fx_file_media_ptr;
|
||||
|
||||
/* Increment the number of times this service has been called. */
|
||||
media_ptr -> fx_media_file_reads++;
|
||||
#endif
|
||||
|
||||
/* Setup pointer to associated media control block. */
|
||||
media_ptr = file_ptr -> fx_file_media_ptr;
|
||||
|
||||
/* If trace is enabled, insert this event into the trace buffer. */
|
||||
FX_TRACE_IN_LINE_INSERT(FX_TRACE_FILE_READ, file_ptr, buffer_ptr, request_size, 0, FX_TRACE_FILE_EVENTS, &trace_event, &trace_timestamp)
|
||||
|
||||
/* Protect against other threads accessing the media. */
|
||||
FX_PROTECT
|
||||
|
||||
/* Next, determine if there is any more bytes to read in the file. */
|
||||
if (file_ptr -> fx_file_current_file_offset >=
|
||||
file_ptr -> fx_file_current_file_size)
|
||||
{
|
||||
|
||||
/* Release media protection. */
|
||||
FX_UNPROTECT
|
||||
|
||||
/* The file is at the end, return the proper status and set the
|
||||
actual size to 0. */
|
||||
*actual_size = 0;
|
||||
return(FX_END_OF_FILE);
|
||||
}
|
||||
|
||||
/* At this point there is something to read. */
|
||||
|
||||
/* Setup local buffer pointer. */
|
||||
destination_ptr = (UCHAR *)buffer_ptr;
|
||||
|
||||
/* Determine if there are less bytes left in the file than that specified
|
||||
by the request. If so, adjust the requested size. */
|
||||
if ((ULONG64)request_size >
|
||||
(file_ptr -> fx_file_current_file_size - file_ptr -> fx_file_current_file_offset))
|
||||
{
|
||||
|
||||
/* Adjust the bytes remaining to what's available. */
|
||||
request_size = (ULONG)(file_ptr -> fx_file_current_file_size - file_ptr -> fx_file_current_file_offset);
|
||||
}
|
||||
|
||||
/* Setup the remaining number of bytes to read. */
|
||||
bytes_remaining = request_size;
|
||||
|
||||
/* Loop to read all of the bytes. */
|
||||
while (bytes_remaining)
|
||||
{
|
||||
|
||||
/* Determine if a beginning or ending partial read is required. */
|
||||
if ((file_ptr -> fx_file_current_logical_offset) ||
|
||||
(bytes_remaining < media_ptr -> fx_media_bytes_per_sector))
|
||||
{
|
||||
|
||||
/* A partial sector read is required. */
|
||||
|
||||
/* Read the current logical sector. */
|
||||
status = _fx_utility_logical_sector_read(media_ptr,
|
||||
file_ptr -> fx_file_current_logical_sector,
|
||||
media_ptr -> fx_media_memory_buffer, ((ULONG) 1), FX_DATA_SECTOR);
|
||||
|
||||
/* Check for good completion status. */
|
||||
if (status != FX_SUCCESS)
|
||||
{
|
||||
|
||||
/* Release media protection. */
|
||||
FX_UNPROTECT
|
||||
|
||||
/* Return the error status. */
|
||||
return(status);
|
||||
}
|
||||
|
||||
/* Copy the appropriate number of bytes into the destination buffer. */
|
||||
copy_bytes = media_ptr -> fx_media_bytes_per_sector -
|
||||
file_ptr -> fx_file_current_logical_offset;
|
||||
|
||||
/* Check to see if only a portion of the read sector needs to be
|
||||
copied. */
|
||||
if (copy_bytes > bytes_remaining)
|
||||
{
|
||||
|
||||
/* Adjust the number of bytes to copy. */
|
||||
copy_bytes = bytes_remaining;
|
||||
}
|
||||
|
||||
/* Actually perform the memory copy. */
|
||||
_fx_utility_memory_copy(((UCHAR *)media_ptr -> fx_media_memory_buffer) + /* Use case of memcpy is verified. */
|
||||
file_ptr -> fx_file_current_logical_offset,
|
||||
destination_ptr, copy_bytes);
|
||||
|
||||
/* Increment the logical sector byte offset. */
|
||||
file_ptr -> fx_file_current_logical_offset =
|
||||
file_ptr -> fx_file_current_logical_offset + copy_bytes;
|
||||
|
||||
/* Adjust the remaining bytes to read. */
|
||||
bytes_remaining = bytes_remaining - copy_bytes;
|
||||
|
||||
/* Adjust the pointer to the destination buffer. */
|
||||
destination_ptr = destination_ptr + copy_bytes;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* Attempt to read multiple sectors directly into the destination
|
||||
buffer. */
|
||||
|
||||
/* Calculate the number of whole sectors to read directly into
|
||||
the destination buffer. */
|
||||
sectors = (UINT)(bytes_remaining / media_ptr -> fx_media_bytes_per_sector);
|
||||
|
||||
|
||||
next_cluster = cluster = file_ptr -> fx_file_current_physical_cluster;
|
||||
for (i = (media_ptr -> fx_media_sectors_per_cluster -
|
||||
file_ptr -> fx_file_current_relative_sector); i < sectors; i += media_ptr -> fx_media_sectors_per_cluster)
|
||||
{
|
||||
status = _fx_utility_FAT_entry_read(media_ptr, cluster, &next_cluster);
|
||||
|
||||
/* Determine if an error is present. */
|
||||
if ((status != FX_SUCCESS) || (next_cluster < FX_FAT_ENTRY_START) ||
|
||||
(next_cluster > media_ptr -> fx_media_fat_reserved))
|
||||
{
|
||||
|
||||
/* Release media protection. */
|
||||
FX_UNPROTECT
|
||||
|
||||
/* Send error message back to caller. */
|
||||
if (status != FX_SUCCESS)
|
||||
{
|
||||
return(status);
|
||||
}
|
||||
else
|
||||
{
|
||||
return(FX_FILE_CORRUPT);
|
||||
}
|
||||
}
|
||||
|
||||
if (next_cluster != cluster + 1)
|
||||
{
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
cluster = next_cluster;
|
||||
}
|
||||
}
|
||||
|
||||
if (i < sectors)
|
||||
{
|
||||
sectors = i;
|
||||
}
|
||||
|
||||
/* Determine if this is a single sector read request. If so, read the sector so it will
|
||||
come from the internal cache. */
|
||||
if (sectors == 1)
|
||||
{
|
||||
|
||||
/* Read the current logical sector. */
|
||||
status = _fx_utility_logical_sector_read(media_ptr,
|
||||
file_ptr -> fx_file_current_logical_sector,
|
||||
media_ptr -> fx_media_memory_buffer, ((ULONG) 1), FX_DATA_SECTOR);
|
||||
|
||||
/* Check for good completion status. */
|
||||
if (status != FX_SUCCESS)
|
||||
{
|
||||
|
||||
/* Release media protection. */
|
||||
FX_UNPROTECT
|
||||
|
||||
/* Return the error status. */
|
||||
return(status);
|
||||
}
|
||||
|
||||
/* Actually perform the memory copy. */
|
||||
_fx_utility_memory_copy((UCHAR *)media_ptr -> fx_media_memory_buffer, destination_ptr, media_ptr -> fx_media_bytes_per_sector); /* Use case of memcpy is verified. */
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* Multiple sector read request. Read all the sectors at once. */
|
||||
|
||||
/* Perform the data read directly into the user's buffer of
|
||||
the appropriate number of sectors. */
|
||||
media_ptr -> fx_media_disable_burst_cache = file_ptr -> fx_file_disable_burst_cache;
|
||||
status = _fx_utility_logical_sector_read(media_ptr, file_ptr -> fx_file_current_logical_sector,
|
||||
destination_ptr, (ULONG) sectors, FX_DATA_SECTOR);
|
||||
media_ptr -> fx_media_disable_burst_cache = FX_FALSE;
|
||||
|
||||
/* Check for good completion status. */
|
||||
if (status != FX_SUCCESS)
|
||||
{
|
||||
|
||||
/* Release media protection. */
|
||||
FX_UNPROTECT
|
||||
|
||||
/* Return the error status. */
|
||||
return(status);
|
||||
}
|
||||
}
|
||||
|
||||
/* Now adjust the various file pointers. */
|
||||
|
||||
/* Increment the current logical sector. Subtract one from
|
||||
the sector count because we are going to use the logical
|
||||
offset to do additional sector/cluster arithmetic below. */
|
||||
file_ptr -> fx_file_current_logical_sector =
|
||||
file_ptr -> fx_file_current_logical_sector +
|
||||
(sectors - 1);
|
||||
|
||||
/* Move the relative sector and cluster as well. */
|
||||
file_ptr -> fx_file_current_relative_cluster = file_ptr -> fx_file_current_relative_cluster +
|
||||
(file_ptr -> fx_file_current_relative_sector + (sectors - 1)) /
|
||||
media_ptr -> fx_media_sectors_per_cluster;
|
||||
|
||||
file_ptr -> fx_file_current_relative_sector =
|
||||
(file_ptr -> fx_file_current_relative_sector +
|
||||
(sectors - 1)) % media_ptr -> fx_media_sectors_per_cluster;
|
||||
|
||||
/* Increment the logical sector byte offset. */
|
||||
file_ptr -> fx_file_current_logical_offset =
|
||||
media_ptr -> fx_media_bytes_per_sector;
|
||||
|
||||
file_ptr -> fx_file_current_physical_cluster = cluster;
|
||||
|
||||
/* Adjust the remaining bytes. */
|
||||
bytes_remaining = bytes_remaining -
|
||||
(((ULONG)media_ptr -> fx_media_bytes_per_sector) * sectors);
|
||||
|
||||
/* Adjust the pointer to the destination buffer. */
|
||||
destination_ptr = destination_ptr +
|
||||
(((ULONG)media_ptr -> fx_media_bytes_per_sector) * sectors);
|
||||
}
|
||||
|
||||
/* At this point, we have either read a partial sector or have successfully
|
||||
read one or more whole sectors. Determine if we are at the end of
|
||||
the current logical sector. */
|
||||
if (file_ptr -> fx_file_current_logical_offset >=
|
||||
media_ptr -> fx_media_bytes_per_sector)
|
||||
{
|
||||
|
||||
/* Determine if we are at the exact physical end of the file at the end of reading. */
|
||||
if ((bytes_remaining == 0) && ((file_ptr -> fx_file_current_file_offset + (ULONG64)request_size) >=
|
||||
file_ptr -> fx_file_current_available_size))
|
||||
{
|
||||
|
||||
/* Skip the following file parameter adjustments. The next write will
|
||||
detect the logical offset out of the range of the sector and reset
|
||||
all of the pertinent information. */
|
||||
break;
|
||||
}
|
||||
|
||||
/* We need to move to the next logical sector, but first
|
||||
determine if the next logical sector is within the same
|
||||
cluster. */
|
||||
|
||||
/* Increment the current relative sector in the cluster. */
|
||||
file_ptr -> fx_file_current_relative_sector++;
|
||||
|
||||
/* Determine if this is in a new cluster. */
|
||||
if (file_ptr -> fx_file_current_relative_sector >=
|
||||
media_ptr -> fx_media_sectors_per_cluster)
|
||||
{
|
||||
|
||||
/* Read the FAT entry of the current cluster to find
|
||||
the next cluster. */
|
||||
status = _fx_utility_FAT_entry_read(media_ptr,
|
||||
file_ptr -> fx_file_current_physical_cluster, &next_cluster);
|
||||
|
||||
/* Determine if an error is present. */
|
||||
if ((status != FX_SUCCESS) || (next_cluster < FX_FAT_ENTRY_START) ||
|
||||
(next_cluster > media_ptr -> fx_media_fat_reserved))
|
||||
{
|
||||
|
||||
/* Release media protection. */
|
||||
FX_UNPROTECT
|
||||
|
||||
/* Send error message back to caller. */
|
||||
if (status != FX_SUCCESS)
|
||||
{
|
||||
return(status);
|
||||
}
|
||||
else
|
||||
{
|
||||
return(FX_FILE_CORRUPT);
|
||||
}
|
||||
}
|
||||
|
||||
/* Otherwise, we have a new cluster. Save it in the file
|
||||
control block and calculate a new logical sector value. */
|
||||
file_ptr -> fx_file_current_physical_cluster = next_cluster;
|
||||
file_ptr -> fx_file_current_relative_cluster++;
|
||||
file_ptr -> fx_file_current_logical_sector = ((ULONG)media_ptr -> fx_media_data_sector_start) +
|
||||
((((ULONG64)next_cluster) - FX_FAT_ENTRY_START) *
|
||||
((ULONG)media_ptr -> fx_media_sectors_per_cluster));
|
||||
file_ptr -> fx_file_current_relative_sector = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* Still within the same cluster so just increment the
|
||||
logical sector. */
|
||||
file_ptr -> fx_file_current_logical_sector++;
|
||||
}
|
||||
|
||||
/* In either case, we are now positioned at a new sector so
|
||||
clear the logical sector offset. */
|
||||
file_ptr -> fx_file_current_logical_offset = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Adjust the current file offset accordingly. */
|
||||
file_ptr -> fx_file_current_file_offset =
|
||||
file_ptr -> fx_file_current_file_offset + (ULONG64)request_size;
|
||||
|
||||
/* Store the number of bytes actually read. */
|
||||
*actual_size = request_size;
|
||||
|
||||
/* Update the trace event with the bytes read. */
|
||||
FX_TRACE_EVENT_UPDATE(trace_event, trace_timestamp, FX_TRACE_FILE_READ, 0, 0, 0, request_size)
|
||||
|
||||
/* Update the last accessed date. */
|
||||
file_ptr -> fx_file_dir_entry.fx_dir_entry_last_accessed_date = _fx_system_date;
|
||||
|
||||
/* Release media protection. */
|
||||
FX_UNPROTECT
|
||||
|
||||
/* Return a successful status to the caller. */
|
||||
return(FX_SUCCESS);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,90 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** FileX Component */
|
||||
/** */
|
||||
/** File */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
#define FX_SOURCE_CODE
|
||||
|
||||
|
||||
/* Include necessary system files. */
|
||||
|
||||
#include "fx_api.h"
|
||||
#include "fx_file.h"
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _fx_file_relative_seek PORTABLE C */
|
||||
/* 6.1 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function positions the internal file pointers to the specified */
|
||||
/* byte relative offset such that the next read or write operation is */
|
||||
/* performed there. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* file_ptr File control block pointer */
|
||||
/* byte_offset Byte offset of the seek */
|
||||
/* seek_from Direction for relative seek, */
|
||||
/* legal values are: */
|
||||
/* */
|
||||
/* FX_SEEK_BEGIN */
|
||||
/* FX_SEEK_END */
|
||||
/* FX_SEEK_FORWARD */
|
||||
/* FX_SEEK_BACK */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* return status */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* _fx_file_extended_relative_seek Seek to specified position */
|
||||
/* */
|
||||
/* 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), and */
|
||||
/* Added conditional to */
|
||||
/* disable one line function, */
|
||||
/* resulting in version 6.1 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
#ifndef FX_DISABLE_ONE_LINE_FUNCTION
|
||||
UINT _fx_file_relative_seek(FX_FILE *file_ptr, ULONG byte_offset, UINT seek_from)
|
||||
{
|
||||
|
||||
return(_fx_file_extended_relative_seek(file_ptr, (ULONG64)byte_offset, seek_from));
|
||||
}
|
||||
#endif /* FX_DISABLE_ONE_LINE_FUNCTION */
|
||||
|
||||
@@ -0,0 +1,550 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** FileX Component */
|
||||
/** */
|
||||
/** File */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
#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_file_rename PORTABLE C */
|
||||
/* 6.1 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function first attempts to find the specified file. If found, */
|
||||
/* the rename request is valid and the directory entry will be changed */
|
||||
/* to the new file name. Otherwise, if the file is not found, the */
|
||||
/* appropriate error code is returned to the caller. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* media_ptr Media control block pointer */
|
||||
/* old_file_name Old file name pointer */
|
||||
/* new_file_name New file name pointer */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* return status */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* _fx_directory_entry_write Write the new directory entry */
|
||||
/* _fx_directory_free_search Search for a free directory */
|
||||
/* entry in target directory */
|
||||
/* _fx_directory_name_extract Extract the new filename */
|
||||
/* _fx_directory_search Search for the file name in */
|
||||
/* the directory structure */
|
||||
/* _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 */
|
||||
/* */
|
||||
/* 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_file_rename(FX_MEDIA *media_ptr, CHAR *old_file_name, CHAR *new_file_name)
|
||||
{
|
||||
|
||||
ULONG i;
|
||||
CHAR *work_ptr;
|
||||
CHAR alpha, beta;
|
||||
UINT status;
|
||||
|
||||
#ifndef FX_DONT_UPDATE_OPEN_FILES
|
||||
ULONG open_count;
|
||||
FX_FILE *search_ptr;
|
||||
#endif
|
||||
CHAR *new_name_ptr;
|
||||
FX_DIR_ENTRY old_dir_entry, new_dir_entry;
|
||||
FX_DIR_ENTRY search_directory;
|
||||
#ifdef FX_RENAME_PATH_INHERIT
|
||||
UINT j;
|
||||
#endif
|
||||
UCHAR not_a_file_attr;
|
||||
|
||||
|
||||
#ifndef FX_MEDIA_STATISTICS_DISABLE
|
||||
|
||||
/* Increment the number of times this service has been called. */
|
||||
media_ptr -> fx_media_file_renames++;
|
||||
#endif
|
||||
|
||||
/* Setup pointers to media name buffers. */
|
||||
old_dir_entry.fx_dir_entry_name = media_ptr -> fx_media_name_buffer + FX_MAX_LONG_NAME_LEN;
|
||||
new_dir_entry.fx_dir_entry_name = media_ptr -> fx_media_name_buffer + FX_MAX_LONG_NAME_LEN * 2;
|
||||
search_directory.fx_dir_entry_name = media_ptr -> fx_media_name_buffer + FX_MAX_LONG_NAME_LEN * 3;
|
||||
|
||||
/* Clear the short name strings. */
|
||||
old_dir_entry.fx_dir_entry_short_name[0] = 0;
|
||||
new_dir_entry.fx_dir_entry_short_name[0] = 0;
|
||||
search_directory.fx_dir_entry_short_name[0] = 0;
|
||||
|
||||
/* 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 *)new_file_name;
|
||||
while (*work_ptr)
|
||||
{
|
||||
|
||||
/* 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);
|
||||
}
|
||||
|
||||
/* 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_FILE_RENAME, media_ptr, old_file_name, new_file_name, 0, FX_TRACE_FILE_EVENTS, 0, 0)
|
||||
|
||||
/* Protect against other threads accessing the media. */
|
||||
FX_PROTECT
|
||||
|
||||
#ifdef FX_ENABLE_FAULT_TOLERANT
|
||||
/* Start transaction. */
|
||||
_fx_fault_tolerant_transaction_start(media_ptr);
|
||||
#endif /* FX_ENABLE_FAULT_TOLERANT */
|
||||
|
||||
/* Check for write protect at the media level (set by driver). */
|
||||
if (media_ptr -> fx_media_driver_write_protect)
|
||||
{
|
||||
|
||||
#ifdef FX_ENABLE_FAULT_TOLERANT
|
||||
FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
|
||||
#endif /* FX_ENABLE_FAULT_TOLERANT */
|
||||
|
||||
/* Release media protection. */
|
||||
FX_UNPROTECT
|
||||
|
||||
/* Return write protect error. */
|
||||
return(FX_WRITE_PROTECT);
|
||||
}
|
||||
|
||||
/* Search the system for the supplied file name. */
|
||||
status = _fx_directory_search(media_ptr, old_file_name, &old_dir_entry, &search_directory, FX_NULL);
|
||||
|
||||
/* 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);
|
||||
}
|
||||
|
||||
not_a_file_attr = FX_DIRECTORY | FX_VOLUME;
|
||||
|
||||
/* Check to make sure the found entry is a file. */
|
||||
if (old_dir_entry.fx_dir_entry_attributes & not_a_file_attr)
|
||||
{
|
||||
|
||||
#ifdef FX_ENABLE_FAULT_TOLERANT
|
||||
FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
|
||||
#endif /* FX_ENABLE_FAULT_TOLERANT */
|
||||
|
||||
/* Release media protection. */
|
||||
FX_UNPROTECT
|
||||
|
||||
/* Return the not a file error code. */
|
||||
return(FX_NOT_A_FILE);
|
||||
}
|
||||
|
||||
#ifdef FX_RENAME_PATH_INHERIT
|
||||
|
||||
/* Determine if the source file name has a path and the target file name does not. */
|
||||
if (((old_file_name[0] == '/') || (old_file_name[0] == '\\')) && (new_file_name[0] != '/') && (new_file_name[0] != '\\'))
|
||||
{
|
||||
|
||||
/* In this case, we need to prepend the path of the old file name to that of the new file name. */
|
||||
|
||||
/* Setup pointer to the rename buffer. */
|
||||
work_ptr = (CHAR *)media_ptr -> fx_media_rename_buffer;
|
||||
|
||||
/* First, copy the path of the old file name. */
|
||||
i = 0;
|
||||
j = 0;
|
||||
while ((old_file_name[i]) && (i < FX_MAXIMUM_PATH))
|
||||
{
|
||||
|
||||
/* Copy a character into the rename buffer. */
|
||||
*work_ptr++ = old_file_name[i];
|
||||
|
||||
/* Determine if this character is directory separator. */
|
||||
if ((old_file_name[i] == '/') || (old_file_name[i] == '\\'))
|
||||
{
|
||||
|
||||
/* Yes, directory separator has been found - remember the index. */
|
||||
j = i;
|
||||
}
|
||||
|
||||
/* Move to next position in the old file name. */
|
||||
i++;
|
||||
}
|
||||
|
||||
/* At this point, we have the path stored in the rename buffer. */
|
||||
|
||||
/* Position past the last slash or backslash. */
|
||||
j++;
|
||||
|
||||
/* Reset the working pointer to the position after the last directory separator. */
|
||||
work_ptr = (CHAR *)&(media_ptr -> fx_media_rename_buffer[j]);
|
||||
|
||||
/* Now copy the new file name into the rename buffer. */
|
||||
i = 0;
|
||||
while ((new_file_name[i]) && (j < FX_MAXIMUM_PATH))
|
||||
{
|
||||
|
||||
/* Copy a character into the rename buffer. */
|
||||
*work_ptr++ = new_file_name[i];
|
||||
|
||||
/* Move to next character. */
|
||||
i++;
|
||||
j++;
|
||||
}
|
||||
|
||||
/* Determine if the path was successfully prepended. */
|
||||
if (new_file_name[i])
|
||||
{
|
||||
|
||||
/* No, there was not enough room in the destination buffer. */
|
||||
|
||||
#ifdef FX_ENABLE_FAULT_TOLERANT
|
||||
FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
|
||||
#endif /* FX_ENABLE_FAULT_TOLERANT */
|
||||
|
||||
/* Release media protection. */
|
||||
FX_UNPROTECT
|
||||
|
||||
/* Return the invalid path error code. */
|
||||
return(FX_INVALID_PATH);
|
||||
}
|
||||
|
||||
/* Place a NULL at the end of the string. */
|
||||
*work_ptr = (CHAR)FX_NULL;
|
||||
|
||||
/* At this point, we have successfully prepended the path in the new file name, override
|
||||
the new file name so it is used from now on. */
|
||||
new_file_name = (CHAR *)media_ptr -> fx_media_rename_buffer;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Search the target directory for the same file name. */
|
||||
status = _fx_directory_search(media_ptr, new_file_name, &new_dir_entry, &search_directory, &new_name_ptr);
|
||||
|
||||
/* Determine if the name already exists. */
|
||||
if (status == FX_SUCCESS)
|
||||
{
|
||||
|
||||
/* Determine if the new name simply has an ASCII case change. If so, simply let the processing
|
||||
continue. */
|
||||
i = 0;
|
||||
do
|
||||
{
|
||||
|
||||
/* Pickup an old name and new name character and convert to upper case if necessary. */
|
||||
alpha = old_file_name[i];
|
||||
if ((alpha >= 'a') && (alpha <= 'z'))
|
||||
{
|
||||
|
||||
/* Lower case, convert to upper case! */
|
||||
alpha = (CHAR)((INT)alpha - 0x20);
|
||||
}
|
||||
beta = new_file_name[i];
|
||||
if ((beta >= 'a') && (beta <= 'z'))
|
||||
{
|
||||
|
||||
/* Lower case, convert to upper case! */
|
||||
beta = (CHAR)((INT)beta - 0x20);
|
||||
}
|
||||
|
||||
/* Now compare the characters. */
|
||||
if ((alpha != beta) || (alpha == 0))
|
||||
{
|
||||
|
||||
/* Get out of this loop! */
|
||||
break;
|
||||
}
|
||||
|
||||
/* Move to next character. */
|
||||
i++;
|
||||
} while (i < (FX_MAXIMUM_PATH-1));
|
||||
|
||||
/* Now determine if the names match. */
|
||||
if (alpha != beta)
|
||||
{
|
||||
|
||||
/* No, the names do not match so simply return an error
|
||||
to the caller. */
|
||||
|
||||
#ifdef FX_ENABLE_FAULT_TOLERANT
|
||||
FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
|
||||
#endif /* FX_ENABLE_FAULT_TOLERANT */
|
||||
|
||||
/* Release media protection. */
|
||||
FX_UNPROTECT
|
||||
|
||||
/* Return the not a file error code. */
|
||||
return(FX_ALREADY_CREATED);
|
||||
}
|
||||
}
|
||||
|
||||
/* Change the file name and look for extra stuff at the end. */
|
||||
if (_fx_directory_name_extract(new_name_ptr, &new_dir_entry.fx_dir_entry_name[0]))
|
||||
{
|
||||
|
||||
#ifdef FX_ENABLE_FAULT_TOLERANT
|
||||
FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
|
||||
#endif /* FX_ENABLE_FAULT_TOLERANT */
|
||||
|
||||
/* Release media protection. */
|
||||
FX_UNPROTECT
|
||||
|
||||
/* Invalid name, return error status. */
|
||||
return(FX_INVALID_NAME);
|
||||
}
|
||||
|
||||
/* Search for a free spot in the target directory. */
|
||||
status = _fx_directory_free_search(media_ptr, &search_directory, &new_dir_entry);
|
||||
|
||||
/* Determine if a free spot was found. */
|
||||
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);
|
||||
}
|
||||
|
||||
/* Extract the new file name. */
|
||||
_fx_directory_name_extract(new_name_ptr, &new_dir_entry.fx_dir_entry_name[0]);
|
||||
|
||||
/* Determine if a long name is present. */
|
||||
if (new_dir_entry.fx_dir_entry_long_name_present)
|
||||
{
|
||||
|
||||
/* Yes, clear the short file name. */
|
||||
new_dir_entry.fx_dir_entry_short_name[0] = 0;
|
||||
}
|
||||
|
||||
/* Save the updated directory parameters. */
|
||||
new_dir_entry.fx_dir_entry_attributes = old_dir_entry.fx_dir_entry_attributes;
|
||||
new_dir_entry.fx_dir_entry_cluster = old_dir_entry.fx_dir_entry_cluster;
|
||||
new_dir_entry.fx_dir_entry_file_size = old_dir_entry.fx_dir_entry_file_size;
|
||||
|
||||
/* Save the reserved field. */
|
||||
new_dir_entry.fx_dir_entry_reserved = old_dir_entry.fx_dir_entry_reserved;
|
||||
|
||||
/* Set time and date stamps. */
|
||||
new_dir_entry.fx_dir_entry_created_time_ms = old_dir_entry.fx_dir_entry_created_time_ms;
|
||||
new_dir_entry.fx_dir_entry_created_time = old_dir_entry.fx_dir_entry_created_time;
|
||||
new_dir_entry.fx_dir_entry_created_date = old_dir_entry.fx_dir_entry_created_date;
|
||||
new_dir_entry.fx_dir_entry_last_accessed_date = old_dir_entry.fx_dir_entry_last_accessed_date;
|
||||
new_dir_entry.fx_dir_entry_time = old_dir_entry.fx_dir_entry_time;
|
||||
new_dir_entry.fx_dir_entry_date = old_dir_entry.fx_dir_entry_date;
|
||||
|
||||
|
||||
/* Is there a leading dot? */
|
||||
if (new_dir_entry.fx_dir_entry_name[0] == '.')
|
||||
{
|
||||
|
||||
/* Yes, toggle the hidden attribute bit. */
|
||||
new_dir_entry.fx_dir_entry_attributes |= FX_HIDDEN;
|
||||
}
|
||||
|
||||
#ifndef FX_MEDIA_DISABLE_SEARCH_CACHE
|
||||
|
||||
/* Invalidate the directory cache. */
|
||||
media_ptr -> fx_media_last_found_name[0] = FX_NULL;
|
||||
#endif
|
||||
|
||||
/* Now write out the directory entry. */
|
||||
status = _fx_directory_entry_write(media_ptr, &new_dir_entry);
|
||||
|
||||
/* 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);
|
||||
}
|
||||
|
||||
#ifndef FX_DONT_UPDATE_OPEN_FILES
|
||||
|
||||
/* Search the opened files to update any currently opened files. */
|
||||
open_count = media_ptr -> fx_media_opened_file_count;
|
||||
search_ptr = media_ptr -> fx_media_opened_file_list;
|
||||
while (open_count)
|
||||
{
|
||||
|
||||
/* Look at each opened file to see if it matches the file being renamed. */
|
||||
if ((search_ptr -> fx_file_dir_entry.fx_dir_entry_log_sector ==
|
||||
old_dir_entry.fx_dir_entry_log_sector) &&
|
||||
(search_ptr -> fx_file_dir_entry.fx_dir_entry_byte_offset ==
|
||||
old_dir_entry.fx_dir_entry_byte_offset))
|
||||
{
|
||||
|
||||
/* Yes, the file being renamed is already open. Update the file's
|
||||
information so that it is kept current. */
|
||||
search_ptr -> fx_file_dir_entry.fx_dir_entry_cluster = new_dir_entry.fx_dir_entry_cluster;
|
||||
search_ptr -> fx_file_dir_entry.fx_dir_entry_file_size = new_dir_entry.fx_dir_entry_file_size;
|
||||
search_ptr -> fx_file_dir_entry.fx_dir_entry_log_sector = new_dir_entry.fx_dir_entry_log_sector;
|
||||
search_ptr -> fx_file_dir_entry.fx_dir_entry_byte_offset = new_dir_entry.fx_dir_entry_byte_offset;
|
||||
|
||||
/* Copy the new name into the file's name buffer. */
|
||||
i = 0;
|
||||
while (i < (FX_MAX_LONG_NAME_LEN - 1))
|
||||
{
|
||||
|
||||
/* Copy byte of the new name. */
|
||||
search_ptr -> fx_file_dir_entry.fx_dir_entry_name[i] = new_dir_entry.fx_dir_entry_name[i];
|
||||
|
||||
/* Move to the next character. */
|
||||
i++;
|
||||
|
||||
/* Determine if we are at the end of the name. */
|
||||
if (new_dir_entry.fx_dir_entry_name[i] == FX_NULL)
|
||||
{
|
||||
|
||||
/* Determine if we are not at the maximum name size. */
|
||||
if (i < (FX_MAX_LONG_NAME_LEN - 1))
|
||||
{
|
||||
|
||||
/* Get out of the loop. */
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Set the NULL termination in the copy of the new name. */
|
||||
search_ptr -> fx_file_dir_entry.fx_dir_entry_name[i] = FX_NULL;
|
||||
}
|
||||
|
||||
/* Adjust the pointer and decrement the search count. */
|
||||
search_ptr = search_ptr -> fx_file_opened_next;
|
||||
open_count--;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Now we are ready to remove the old directory entry. */
|
||||
old_dir_entry.fx_dir_entry_name[0] = (CHAR)FX_DIR_ENTRY_FREE;
|
||||
old_dir_entry.fx_dir_entry_short_name[0] = (CHAR)FX_DIR_ENTRY_FREE;
|
||||
|
||||
/* Now wipe out the old directory entry. */
|
||||
status = _fx_directory_entry_write(media_ptr, &old_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
|
||||
|
||||
/* File rename is complete, return status. */
|
||||
return(status);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,83 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** FileX Component */
|
||||
/** */
|
||||
/** File */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
#define FX_SOURCE_CODE
|
||||
|
||||
|
||||
/* Include necessary system files. */
|
||||
|
||||
#include "fx_api.h"
|
||||
#include "fx_file.h"
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _fx_file_seek PORTABLE C */
|
||||
/* 6.1 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function positions the internal file pointers to the specified */
|
||||
/* byte offset such that the next read or write operation will be */
|
||||
/* performed there. If the byte offset is greater than the size, the */
|
||||
/* file pointers will be positioned to the end of the file. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* file_ptr File control block pointer */
|
||||
/* byte_offset Byte offset into the file */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* return status */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* _fx_file_extended_seek Seek to specified position */
|
||||
/* */
|
||||
/* 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), and */
|
||||
/* Added conditional to */
|
||||
/* disable one line function, */
|
||||
/* resulting in version 6.1 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
#ifndef FX_DISABLE_ONE_LINE_FUNCTION
|
||||
UINT _fx_file_seek(FX_FILE *file_ptr, ULONG byte_offset)
|
||||
{
|
||||
|
||||
return(_fx_file_extended_seek(file_ptr, (ULONG64) byte_offset));
|
||||
}
|
||||
#endif /* FX_DISABLE_ONE_LINE_FUNCTION */
|
||||
@@ -0,0 +1,83 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** FileX Component */
|
||||
/** */
|
||||
/** File */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
#define FX_SOURCE_CODE
|
||||
|
||||
|
||||
/* Include necessary system files. */
|
||||
|
||||
#include "fx_api.h"
|
||||
#include "fx_file.h"
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _fx_file_truncate PORTABLE C */
|
||||
/* 6.1 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function sets the file to the specified size, if smaller than */
|
||||
/* the current file size. If the new file size is less than the */
|
||||
/* current file read/write position, the internal file pointers will */
|
||||
/* also be modified. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* file_ptr File control block pointer */
|
||||
/* size New size of the file in bytes */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* return status */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* _fx_file_extended_truncate Truncate the file size */
|
||||
/* */
|
||||
/* 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), and */
|
||||
/* Added conditional to */
|
||||
/* disable one line function, */
|
||||
/* resulting in version 6.1 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
#ifndef FX_DISABLE_ONE_LINE_FUNCTION
|
||||
UINT _fx_file_truncate(FX_FILE *file_ptr, ULONG size)
|
||||
{
|
||||
|
||||
return(_fx_file_extended_truncate(file_ptr, (ULONG64)size));
|
||||
}
|
||||
#endif /* FX_DISABLE_ONE_LINE_FUNCTION */
|
||||
@@ -0,0 +1,86 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** FileX Component */
|
||||
/** */
|
||||
/** File */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
#define FX_SOURCE_CODE
|
||||
|
||||
|
||||
/* Include necessary system files. */
|
||||
|
||||
#include "fx_api.h"
|
||||
#include "fx_file.h"
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _fx_file_truncate_release PORTABLE C */
|
||||
/* 6.1 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function sets the file to the specified size, if smaller than */
|
||||
/* the current file size. If the new file size is less than the */
|
||||
/* current file read/write position, the internal file pointers will */
|
||||
/* also be modified. Any unused clusters are released back to the */
|
||||
/* media. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* file_ptr File control block pointer */
|
||||
/* size New size of the file in bytes */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* return status */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* _fx_file_extended_truncate_release Truncate the file size and */
|
||||
/* released unused clusters */
|
||||
/* */
|
||||
/* 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), and */
|
||||
/* Added conditional to */
|
||||
/* disable one line function, */
|
||||
/* resulting in version 6.1 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
#ifndef FX_DISABLE_ONE_LINE_FUNCTION
|
||||
UINT _fx_file_truncate_release(FX_FILE *file_ptr, ULONG size)
|
||||
{
|
||||
|
||||
return(_fx_file_extended_truncate_release(file_ptr, (ULONG64)size));
|
||||
}
|
||||
#endif /* FX_DISABLE_ONE_LINE_FUNCTION */
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,83 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** FileX Component */
|
||||
/** */
|
||||
/** File */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
#define FX_SOURCE_CODE
|
||||
|
||||
|
||||
/* Include necessary system files. */
|
||||
|
||||
#include "fx_api.h"
|
||||
#include "fx_file.h"
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _fx_file_write_notify_set PORTABLE C */
|
||||
/* 6.1 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function sets the notify function called whenever file is */
|
||||
/* is written to. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* file_ptr File control block pointer */
|
||||
/* file_write_notify Notify function called when */
|
||||
/* file is written to */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* FX_SUCCESS */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* 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_file_write_notify_set(FX_FILE *file_ptr, VOID (*file_write_notify)(FX_FILE *file))
|
||||
{
|
||||
|
||||
/* Set the notify function. */
|
||||
file_ptr -> fx_file_write_notify = file_write_notify;
|
||||
|
||||
/* Return successful status. */
|
||||
return(FX_SUCCESS);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,189 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** FileX Component */
|
||||
/** */
|
||||
/** Media */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
#define FX_SOURCE_CODE
|
||||
|
||||
|
||||
/* Include necessary system files. */
|
||||
|
||||
#include "fx_api.h"
|
||||
#include "fx_system.h"
|
||||
#include "fx_media.h"
|
||||
#include "fx_file.h"
|
||||
#include "fx_utility.h"
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _fx_media_abort PORTABLE C */
|
||||
/* 6.1 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function marks all open files for the specified media as */
|
||||
/* aborted and then removes the media control block from the open */
|
||||
/* media list and marks it as aborted as well. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* media_ptr Media control block pointer */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* return status */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* tx_mutex_delete Delete the mutex */
|
||||
/* */
|
||||
/* 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_media_abort(FX_MEDIA *media_ptr)
|
||||
{
|
||||
|
||||
FX_INT_SAVE_AREA
|
||||
ULONG open_count;
|
||||
FX_FILE *file_ptr;
|
||||
|
||||
|
||||
#ifndef FX_MEDIA_STATISTICS_DISABLE
|
||||
|
||||
/* Increment the number of times this service has been called. */
|
||||
media_ptr -> fx_media_aborts++;
|
||||
#endif
|
||||
|
||||
/* 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_MEDIA_ABORT, media_ptr, 0, 0, 0, FX_TRACE_MEDIA_EVENTS, 0, 0)
|
||||
|
||||
/* Protect against other threads accessing the media. */
|
||||
FX_PROTECT
|
||||
|
||||
/* Loop through the media's open files. */
|
||||
open_count = media_ptr -> fx_media_opened_file_count;
|
||||
file_ptr = media_ptr -> fx_media_opened_file_list;
|
||||
while (open_count)
|
||||
{
|
||||
|
||||
/* Mark the file as aborted. */
|
||||
file_ptr -> fx_file_id = FX_FILE_ABORTED_ID;
|
||||
|
||||
/* Adjust the pointer and decrement the file opened count. */
|
||||
file_ptr = file_ptr -> fx_file_opened_next;
|
||||
open_count--;
|
||||
}
|
||||
|
||||
/* Build the "abort" I/O driver request. */
|
||||
media_ptr -> fx_media_driver_request = FX_DRIVER_ABORT;
|
||||
media_ptr -> fx_media_driver_status = FX_IO_ERROR;
|
||||
|
||||
/* If trace is enabled, insert this event into the trace buffer. */
|
||||
FX_TRACE_IN_LINE_INSERT(FX_TRACE_INTERNAL_IO_DRIVER_ABORT, media_ptr, 0, 0, 0, FX_TRACE_INTERNAL_EVENTS, 0, 0)
|
||||
|
||||
/* Call the specified I/O driver with the abort request. */
|
||||
(media_ptr -> fx_media_driver_entry) (media_ptr);
|
||||
|
||||
/* Now remove this media from the open list. */
|
||||
|
||||
/* Lockout interrupts for media removal. */
|
||||
FX_DISABLE_INTS
|
||||
|
||||
/* See if the media is the only one on the media opened list. */
|
||||
if (_fx_system_media_opened_count == ((ULONG) 1))
|
||||
{
|
||||
|
||||
/* Only opened media, just set the opened list to NULL. */
|
||||
_fx_system_media_opened_ptr = FX_NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* Otherwise, not the only opened media, link-up the neighbors. */
|
||||
(media_ptr -> fx_media_opened_next) -> fx_media_opened_previous =
|
||||
media_ptr -> fx_media_opened_previous;
|
||||
(media_ptr -> fx_media_opened_previous) -> fx_media_opened_next =
|
||||
media_ptr -> fx_media_opened_next;
|
||||
|
||||
/* See if we have to update the opened list head pointer. */
|
||||
if (_fx_system_media_opened_ptr == media_ptr)
|
||||
{
|
||||
|
||||
/* Yes, move the head pointer to the next opened media. */
|
||||
_fx_system_media_opened_ptr = media_ptr -> fx_media_opened_next;
|
||||
}
|
||||
}
|
||||
|
||||
/* Decrement the opened media counter. */
|
||||
_fx_system_media_opened_count--;
|
||||
|
||||
/* Finally, Indicate that this media is aborted. */
|
||||
media_ptr -> fx_media_id = FX_MEDIA_ABORTED_ID;
|
||||
|
||||
/* Restore interrupt posture. */
|
||||
FX_RESTORE_INTS
|
||||
|
||||
/* Delete the media protection structure if FX_SINGLE_THREAD is not
|
||||
defined. */
|
||||
#ifndef FX_SINGLE_THREAD
|
||||
|
||||
#ifndef FX_DONT_CREATE_MUTEX
|
||||
|
||||
/* Note that the protection is never released. The mutex delete
|
||||
service will handle all threads waiting access to this media
|
||||
control block. */
|
||||
tx_mutex_delete(& (media_ptr -> fx_media_protect));
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef FX_DONT_CREATE_MUTEX
|
||||
|
||||
/* Release media protection. */
|
||||
FX_UNPROTECT
|
||||
#endif
|
||||
|
||||
/* Return status to the caller. */
|
||||
return(FX_SUCCESS);
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user