Initial version
This commit is contained in:
@@ -0,0 +1,21 @@
|
||||
Reliance Edge Credits
|
||||
=====================
|
||||
|
||||
This is a list (or partial list) of people who have made non-trivial or
|
||||
noteworthy contributions to the Reliance Edge project. It is sorted by name.
|
||||
Entries are formatted as below:
|
||||
|
||||
Real Name (githubaccount)
|
||||
Short description of how Real Name contributed to Reliance Edge.
|
||||
|
||||
The real name may be withheld by request and the GitHub account name might be
|
||||
missing if the contributor does not use GitHub.
|
||||
|
||||
Credits
|
||||
-------
|
||||
|
||||
Jean-Christophe Dubois (jcdubois)
|
||||
Created a user-space Linux port of Reliance Edge, ported the open-source host
|
||||
tools (including the formatter and image builder) to Linux, and created a FUSE
|
||||
(File System in User Space) implementation for Reliance Edge.
|
||||
|
340
FreeRTOSv10.2.1/FreeRTOS-Plus/Source/Reliance-Edge/LICENSE.txt
Normal file
340
FreeRTOSv10.2.1/FreeRTOS-Plus/Source/Reliance-Edge/LICENSE.txt
Normal file
@@ -0,0 +1,340 @@
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 2, June 1991
|
||||
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
License is intended to guarantee your freedom to share and change free
|
||||
software--to make sure the software is free for all its users. This
|
||||
General Public License applies to most of the Free Software
|
||||
Foundation's software and to any other program whose authors commit to
|
||||
using it. (Some other Free Software Foundation software is covered by
|
||||
the GNU Lesser General Public License instead.) You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
this service if you wish), that you receive source code or can get it
|
||||
if you want it, that you can change the software or use pieces of it
|
||||
in new free programs; and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid
|
||||
anyone to deny you these rights or to ask you to surrender the rights.
|
||||
These restrictions translate to certain responsibilities for you if you
|
||||
distribute copies of the software, or if you modify it.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must give the recipients all the rights that
|
||||
you have. You must make sure that they, too, receive or can get the
|
||||
source code. And you must show them these terms so they know their
|
||||
rights.
|
||||
|
||||
We protect your rights with two steps: (1) copyright the software, and
|
||||
(2) offer you this license which gives you legal permission to copy,
|
||||
distribute and/or modify the software.
|
||||
|
||||
Also, for each author's protection and ours, we want to make certain
|
||||
that everyone understands that there is no warranty for this free
|
||||
software. If the software is modified by someone else and passed on, we
|
||||
want its recipients to know that what they have is not the original, so
|
||||
that any problems introduced by others will not reflect on the original
|
||||
authors' reputations.
|
||||
|
||||
Finally, any free program is threatened constantly by software
|
||||
patents. We wish to avoid the danger that redistributors of a free
|
||||
program will individually obtain patent licenses, in effect making the
|
||||
program proprietary. To prevent this, we have made it clear that any
|
||||
patent must be licensed for everyone's free use or not licensed at all.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License applies to any program or other work which contains
|
||||
a notice placed by the copyright holder saying it may be distributed
|
||||
under the terms of this General Public License. The "Program", below,
|
||||
refers to any such program or work, and a "work based on the Program"
|
||||
means either the Program or any derivative work under copyright law:
|
||||
that is to say, a work containing the Program or a portion of it,
|
||||
either verbatim or with modifications and/or translated into another
|
||||
language. (Hereinafter, translation is included without limitation in
|
||||
the term "modification".) Each licensee is addressed as "you".
|
||||
|
||||
Activities other than copying, distribution and modification are not
|
||||
covered by this License; they are outside its scope. The act of
|
||||
running the Program is not restricted, and the output from the Program
|
||||
is covered only if its contents constitute a work based on the
|
||||
Program (independent of having been made by running the Program).
|
||||
Whether that is true depends on what the Program does.
|
||||
|
||||
1. You may copy and distribute verbatim copies of the Program's
|
||||
source code as you receive it, in any medium, provided that you
|
||||
conspicuously and appropriately publish on each copy an appropriate
|
||||
copyright notice and disclaimer of warranty; keep intact all the
|
||||
notices that refer to this License and to the absence of any warranty;
|
||||
and give any other recipients of the Program a copy of this License
|
||||
along with the Program.
|
||||
|
||||
You may charge a fee for the physical act of transferring a copy, and
|
||||
you may at your option offer warranty protection in exchange for a fee.
|
||||
|
||||
2. You may modify your copy or copies of the Program or any portion
|
||||
of it, thus forming a work based on the Program, and copy and
|
||||
distribute such modifications or work under the terms of Section 1
|
||||
above, provided that you also meet all of these conditions:
|
||||
|
||||
a) You must cause the modified files to carry prominent notices
|
||||
stating that you changed the files and the date of any change.
|
||||
|
||||
b) You must cause any work that you distribute or publish, that in
|
||||
whole or in part contains or is derived from the Program or any
|
||||
part thereof, to be licensed as a whole at no charge to all third
|
||||
parties under the terms of this License.
|
||||
|
||||
c) If the modified program normally reads commands interactively
|
||||
when run, you must cause it, when started running for such
|
||||
interactive use in the most ordinary way, to print or display an
|
||||
announcement including an appropriate copyright notice and a
|
||||
notice that there is no warranty (or else, saying that you provide
|
||||
a warranty) and that users may redistribute the program under
|
||||
these conditions, and telling the user how to view a copy of this
|
||||
License. (Exception: if the Program itself is interactive but
|
||||
does not normally print such an announcement, your work based on
|
||||
the Program is not required to print an announcement.)
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Program,
|
||||
and can be reasonably considered independent and separate works in
|
||||
themselves, then this License, and its terms, do not apply to those
|
||||
sections when you distribute them as separate works. But when you
|
||||
distribute the same sections as part of a whole which is a work based
|
||||
on the Program, the distribution of the whole must be on the terms of
|
||||
this License, whose permissions for other licensees extend to the
|
||||
entire whole, and thus to each and every part regardless of who wrote it.
|
||||
|
||||
Thus, it is not the intent of this section to claim rights or contest
|
||||
your rights to work written entirely by you; rather, the intent is to
|
||||
exercise the right to control the distribution of derivative or
|
||||
collective works based on the Program.
|
||||
|
||||
In addition, mere aggregation of another work not based on the Program
|
||||
with the Program (or with a work based on the Program) on a volume of
|
||||
a storage or distribution medium does not bring the other work under
|
||||
the scope of this License.
|
||||
|
||||
3. You may copy and distribute the Program (or a work based on it,
|
||||
under Section 2) in object code or executable form under the terms of
|
||||
Sections 1 and 2 above provided that you also do one of the following:
|
||||
|
||||
a) Accompany it with the complete corresponding machine-readable
|
||||
source code, which must be distributed under the terms of Sections
|
||||
1 and 2 above on a medium customarily used for software interchange; or,
|
||||
|
||||
b) Accompany it with a written offer, valid for at least three
|
||||
years, to give any third party, for a charge no more than your
|
||||
cost of physically performing source distribution, a complete
|
||||
machine-readable copy of the corresponding source code, to be
|
||||
distributed under the terms of Sections 1 and 2 above on a medium
|
||||
customarily used for software interchange; or,
|
||||
|
||||
c) Accompany it with the information you received as to the offer
|
||||
to distribute corresponding source code. (This alternative is
|
||||
allowed only for noncommercial distribution and only if you
|
||||
received the program in object code or executable form with such
|
||||
an offer, in accord with Subsection b above.)
|
||||
|
||||
The source code for a work means the preferred form of the work for
|
||||
making modifications to it. For an executable work, complete source
|
||||
code means all the source code for all modules it contains, plus any
|
||||
associated interface definition files, plus the scripts used to
|
||||
control compilation and installation of the executable. However, as a
|
||||
special exception, the source code distributed need not include
|
||||
anything that is normally distributed (in either source or binary
|
||||
form) with the major components (compiler, kernel, and so on) of the
|
||||
operating system on which the executable runs, unless that component
|
||||
itself accompanies the executable.
|
||||
|
||||
If distribution of executable or object code is made by offering
|
||||
access to copy from a designated place, then offering equivalent
|
||||
access to copy the source code from the same place counts as
|
||||
distribution of the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
|
||||
4. You may not copy, modify, sublicense, or distribute the Program
|
||||
except as expressly provided under this License. Any attempt
|
||||
otherwise to copy, modify, sublicense or distribute the Program is
|
||||
void, and will automatically terminate your rights under this License.
|
||||
However, parties who have received copies, or rights, from you under
|
||||
this License will not have their licenses terminated so long as such
|
||||
parties remain in full compliance.
|
||||
|
||||
5. You are not required to accept this License, since you have not
|
||||
signed it. However, nothing else grants you permission to modify or
|
||||
distribute the Program or its derivative works. These actions are
|
||||
prohibited by law if you do not accept this License. Therefore, by
|
||||
modifying or distributing the Program (or any work based on the
|
||||
Program), you indicate your acceptance of this License to do so, and
|
||||
all its terms and conditions for copying, distributing or modifying
|
||||
the Program or works based on it.
|
||||
|
||||
6. Each time you redistribute the Program (or any work based on the
|
||||
Program), the recipient automatically receives a license from the
|
||||
original licensor to copy, distribute or modify the Program subject to
|
||||
these terms and conditions. You may not impose any further
|
||||
restrictions on the recipients' exercise of the rights granted herein.
|
||||
You are not responsible for enforcing compliance by third parties to
|
||||
this License.
|
||||
|
||||
7. If, as a consequence of a court judgment or allegation of patent
|
||||
infringement or for any other reason (not limited to patent issues),
|
||||
conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot
|
||||
distribute so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you
|
||||
may not distribute the Program at all. For example, if a patent
|
||||
license would not permit royalty-free redistribution of the Program by
|
||||
all those who receive copies directly or indirectly through you, then
|
||||
the only way you could satisfy both it and this License would be to
|
||||
refrain entirely from distribution of the Program.
|
||||
|
||||
If any portion of this section is held invalid or unenforceable under
|
||||
any particular circumstance, the balance of the section is intended to
|
||||
apply and the section as a whole is intended to apply in other
|
||||
circumstances.
|
||||
|
||||
It is not the purpose of this section to induce you to infringe any
|
||||
patents or other property right claims or to contest validity of any
|
||||
such claims; this section has the sole purpose of protecting the
|
||||
integrity of the free software distribution system, which is
|
||||
implemented by public license practices. Many people have made
|
||||
generous contributions to the wide range of software distributed
|
||||
through that system in reliance on consistent application of that
|
||||
system; it is up to the author/donor to decide if he or she is willing
|
||||
to distribute software through any other system and a licensee cannot
|
||||
impose that choice.
|
||||
|
||||
This section is intended to make thoroughly clear what is believed to
|
||||
be a consequence of the rest of this License.
|
||||
|
||||
8. If the distribution and/or use of the Program is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Program under this License
|
||||
may add an explicit geographical distribution limitation excluding
|
||||
those countries, so that distribution is permitted only in or among
|
||||
countries not thus excluded. In such case, this License incorporates
|
||||
the limitation as if written in the body of this License.
|
||||
|
||||
9. The Free Software Foundation may publish revised and/or new versions
|
||||
of the General Public License from time to time. Such new versions will
|
||||
be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the Program
|
||||
specifies a version number of this License which applies to it and "any
|
||||
later version", you have the option of following the terms and conditions
|
||||
either of that version or of any later version published by the Free
|
||||
Software Foundation. If the Program does not specify a version number of
|
||||
this License, you may choose any version ever published by the Free Software
|
||||
Foundation.
|
||||
|
||||
10. If you wish to incorporate parts of the Program into other free
|
||||
programs whose distribution conditions are different, write to the author
|
||||
to ask for permission. For software which is copyrighted by the Free
|
||||
Software Foundation, write to the Free Software Foundation; we sometimes
|
||||
make exceptions for this. Our decision will be guided by the two goals
|
||||
of preserving the free status of all derivatives of our free software and
|
||||
of promoting the sharing and reuse of software generally.
|
||||
|
||||
NO WARRANTY
|
||||
|
||||
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
|
||||
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
|
||||
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
|
||||
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
|
||||
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
|
||||
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
|
||||
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
|
||||
REPAIR OR CORRECTION.
|
||||
|
||||
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
|
||||
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
|
||||
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
|
||||
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
|
||||
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
|
||||
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
|
||||
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGES.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
free software which everyone can redistribute and change under these terms.
|
||||
|
||||
To do so, attach the following notices to the program. It is safest
|
||||
to attach them to the start of each source file to most effectively
|
||||
convey the exclusion of warranty; and each file should have at least
|
||||
the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program is interactive, make it output a short notice like this
|
||||
when it starts in an interactive mode:
|
||||
|
||||
Gnomovision version 69, Copyright (C) year name of author
|
||||
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type `show c' for details.
|
||||
|
||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||
parts of the General Public License. Of course, the commands you use may
|
||||
be called something other than `show w' and `show c'; they could even be
|
||||
mouse-clicks or menu items--whatever suits your program.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or your
|
||||
school, if any, to sign a "copyright disclaimer" for the program, if
|
||||
necessary. Here is a sample; alter the names:
|
||||
|
||||
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
|
||||
`Gnomovision' (which makes passes at compilers) written by James Hacker.
|
||||
|
||||
<signature of Ty Coon>, 1 April 1989
|
||||
Ty Coon, President of Vice
|
||||
|
||||
This General Public License does not permit incorporating your program into
|
||||
proprietary programs. If your program is a subroutine library, you may
|
||||
consider it more useful to permit linking proprietary applications with the
|
||||
library. If this is what you want to do, use the GNU Lesser General
|
||||
Public License instead of this License.
|
||||
|
123
FreeRTOSv10.2.1/FreeRTOS-Plus/Source/Reliance-Edge/README.md
Normal file
123
FreeRTOSv10.2.1/FreeRTOS-Plus/Source/Reliance-Edge/README.md
Normal file
@@ -0,0 +1,123 @@
|
||||
# Reliance Edge
|
||||
|
||||
Reliance Edge is a small, portable, highly reliable power-fail safe file system
|
||||
for resource-constrained embedded systems like microcontrollers. It is written
|
||||
in C and provides a familiar POSIX-like file system API, making it easy to use
|
||||
in your application; or an alternate minimalist API if your application has
|
||||
simple storage needs. Reliance Edge is highly configurable and can be tuned to
|
||||
the precise needs of your application.
|
||||
|
||||
## Getting Help
|
||||
|
||||
You will find this section later in our readme as well - but we wanted to tell
|
||||
you up front: DATALIGHT WANTS TO HEAR FROM YOU! Whether it's just to make
|
||||
comments about the product, to suggest new features, or to tell us what you
|
||||
don't like - reach out! All comments and inquiries can be directed to
|
||||
<RelianceEdgeSupport@datalight.com>.
|
||||
|
||||
## Documentation
|
||||
|
||||
The complete documentation for Reliance Edge is distributed separately. It
|
||||
includes an API reference and detailed discussions of various aspects of using
|
||||
Reliance Edge, including porting, building, configuring, and testing. This
|
||||
complete documentation, called the _Developer's Guide_, can be obtained for free
|
||||
from here:
|
||||
|
||||
<http://www.datalight.com/reliance-edge>
|
||||
|
||||
In addition this README, see doc/release_notes.md for a list of updates
|
||||
to Reliance Edge and a list of known issues. There is also a quick-start
|
||||
guide in the doc/ directory that describes step-by-step how to compile
|
||||
and run Reliance Edge in a simulated Windows environment.
|
||||
|
||||
## Why Use Reliance Edge?
|
||||
|
||||
Reliance Edge is ideal for small embedded systems with data storage
|
||||
requirements, especially if there is a chance of sudden power loss or other
|
||||
system failures. Compared to "raw" disk access, using a file system like
|
||||
Reliance Edge removes the burden of tracking which sectors belong to which
|
||||
objects, and allows data to be updated more reliably. Compared to the FAT file
|
||||
system, using Reliance Edge eliminates the possibility that file system data
|
||||
will be left in an inconsistent state, corrupting the disk; Reliance Edge does
|
||||
not need a fsck/CHKDSK utility. Compared to journaling file systems, Reliance
|
||||
Edge has less overhead and results in less storage media wear for longer device
|
||||
lifetimes.
|
||||
|
||||
Reliance Edge uses a unique transactional model that not only prevents file
|
||||
system corruption but also allows a set of changes to be made in an atomic "all
|
||||
or nothing" fashion. This is very useful for applications that make sets of
|
||||
interrelated changes. By using the features of Reliance Edge, a set of changes
|
||||
can be incorporated into a single atomic transaction, which is committed in its
|
||||
entirety or not at all even if interrupted by power loss; this means the
|
||||
application does not need code to recover from partially-finished updates.
|
||||
|
||||
## Hardware
|
||||
|
||||
The typical hardware for Reliance Edge is a 32-bit microcontroller, but other
|
||||
targets are possible. In its typical configurations, Reliance Edge needs at
|
||||
least 4 KB to 5 KB of RAM, 11 to 18 KB of code space (on the ROM or NOR flash),
|
||||
and 500 to 700 bytes of stack.
|
||||
|
||||
Reliance Edge is not designed for high-end embedded systems that run complicated
|
||||
operating systems like Linux or Windows Embedded Compact. Embedded systems of
|
||||
that variety are better served by other file systems, like Datalight's
|
||||
[Reliance Nitro](http://www.datalight.com/products/embedded-file-systems/reliance-nitro).
|
||||
|
||||
## Getting Reliance Edge Working
|
||||
|
||||
Before you can use Reliance Edge, it must be ported and configured. At a
|
||||
minimum, porting includes filling-in functions so that Reliance Edge can issue
|
||||
commands to your storage medium; depending on your needs, other functions may
|
||||
need to be filled in as well. These functions reside in a subdirectory in the
|
||||
os/ directory; see os/stub/ for a blank set of functions. Configuring includes
|
||||
creating a project directory (start by copying projects/newproj) and creating
|
||||
the two configuration files (redconf.h/redconf.c) using the Reliance Edge
|
||||
Configuration Utility (which can be downloaded from
|
||||
<http://www.datalight.com/reliance-edge>).
|
||||
|
||||
These topics are covered in much greater detail in the _Developer's Guide_,
|
||||
linked above.
|
||||
|
||||
## Using Reliance Edge
|
||||
|
||||
Using Reliance Edge is a simple matter of including the primary Reliance Edge
|
||||
application header in your application (either include/redposix.h or
|
||||
include/redfse.h) and compiling and linking against Reliance Edge binaries.
|
||||
The Reliance Edge driver must be initialized before it is used (via the
|
||||
red\_init() or RedFseInit() functions) and then volumes can be mounted and file
|
||||
and directory functions invoked. The Reliance Edge API is documented in the
|
||||
_Developer's Guide_ (linked above) and also via comments in the source code.
|
||||
|
||||
## Licensing
|
||||
|
||||
Reliance Edge is an open-source project licensed under the GNU General Public
|
||||
License v2 (GPLv2). Businesses and individuals that for commercial or other
|
||||
reasons cannot comply with the terms of the GPLv2 license may obtain a
|
||||
commercial license before incorporating Reliance Edge into proprietary software
|
||||
for distribution in any form. Visit <http://www.datalight.com/reliance-edge>
|
||||
for more information. The commercial distribution also includes extra tests and
|
||||
tools not distributed with the GPLv2 version.
|
||||
|
||||
See LICENSE.txt for the full license terms of this distribution of the product.
|
||||
|
||||
## Getting Help
|
||||
|
||||
If you need assistance using Reliance Edge, and you have already consulted the
|
||||
_Developer's Guide_, contact <RelianceEdgeSupport@datalight.com>.
|
||||
|
||||
In the near future, a community forum or message board will be set up to
|
||||
facilitate discussion of Reliance Edge and allow users to get help from
|
||||
Datalight and from each other. In the meantime, please use the email address
|
||||
given above.
|
||||
|
||||
## Contributing
|
||||
|
||||
Contributions to Reliance Edge are welcome. Our policy is that Datalight must
|
||||
own the copyright of all code incorporated into Reliance Edge; if contributing a
|
||||
significant amount of code, you will be asked to file a copyright assignment
|
||||
agreement. See CONTRIBUTING.txt for further details and contribution
|
||||
guidelines.
|
||||
|
||||
To report bugs, please create a GitHub issue or contact
|
||||
<RelianceEdgeSupport@datalight.com>.
|
||||
|
140
FreeRTOSv10.2.1/FreeRTOS-Plus/Source/Reliance-Edge/README.txt
Normal file
140
FreeRTOSv10.2.1/FreeRTOS-Plus/Source/Reliance-Edge/README.txt
Normal file
@@ -0,0 +1,140 @@
|
||||
|
||||
|
||||
RELIANCE EDGE
|
||||
|
||||
|
||||
Reliance Edge is a small, portable, highly reliable power-fail safe file
|
||||
system for resource-constrained embedded systems like microcontrollers.
|
||||
It is written in C and provides a familiar POSIX-like file system API,
|
||||
making it easy to use in your application; or an alternate minimalist
|
||||
API if your application has simple storage needs. Reliance Edge is
|
||||
highly configurable and can be tuned to the precise needs of your
|
||||
application.
|
||||
|
||||
|
||||
Getting Help
|
||||
|
||||
You will find this section later in our readme as well - but we wanted
|
||||
to tell you up front: DATALIGHT WANTS TO HEAR FROM YOU! Whether it's
|
||||
just to make comments about the product, to suggest new features, or to
|
||||
tell us what you don't like - reach out! All comments and inquiries can
|
||||
be directed to RelianceEdgeSupport@datalight.com.
|
||||
|
||||
|
||||
Documentation
|
||||
|
||||
The complete documentation for Reliance Edge is distributed separately.
|
||||
It includes an API reference and detailed discussions of various aspects
|
||||
of using Reliance Edge, including porting, building, configuring, and
|
||||
testing. This complete documentation, called the _Developer's Guide_,
|
||||
can be obtained for free from here:
|
||||
|
||||
http://www.datalight.com/reliance-edge
|
||||
|
||||
In addition this README, see doc/release_notes.md for a list of updates
|
||||
to Reliance Edge and a list of known issues. There is also a quick-start
|
||||
guide in the doc/ directory that describes step-by-step how to compile
|
||||
and run Reliance Edge in a simulated Windows environment.
|
||||
|
||||
|
||||
Why Use Reliance Edge?
|
||||
|
||||
Reliance Edge is ideal for small embedded systems with data storage
|
||||
requirements, especially if there is a chance of sudden power loss or
|
||||
other system failures. Compared to "raw" disk access, using a file
|
||||
system like Reliance Edge removes the burden of tracking which sectors
|
||||
belong to which objects, and allows data to be updated more reliably.
|
||||
Compared to the FAT file system, using Reliance Edge eliminates the
|
||||
possibility that file system data will be left in an inconsistent state,
|
||||
corrupting the disk; Reliance Edge does not need a fsck/CHKDSK utility.
|
||||
Compared to journaling file systems, Reliance Edge has less overhead and
|
||||
results in less storage media wear for longer device lifetimes.
|
||||
|
||||
Reliance Edge uses a unique transactional model that not only prevents
|
||||
file system corruption but also allows a set of changes to be made in an
|
||||
atomic "all or nothing" fashion. This is very useful for applications
|
||||
that make sets of interrelated changes. By using the features of
|
||||
Reliance Edge, a set of changes can be incorporated into a single atomic
|
||||
transaction, which is committed in its entirety or not at all even if
|
||||
interrupted by power loss; this means the application does not need code
|
||||
to recover from partially-finished updates.
|
||||
|
||||
|
||||
Hardware
|
||||
|
||||
The typical hardware for Reliance Edge is a 32-bit microcontroller, but
|
||||
other targets are possible. In its typical configurations, Reliance Edge
|
||||
needs at least 4 KB to 5 KB of RAM, 11 to 18 KB of code space (on the
|
||||
ROM or NOR flash), and 500 to 700 bytes of stack.
|
||||
|
||||
Reliance Edge is not designed for high-end embedded systems that run
|
||||
complicated operating systems like Linux or Windows Embedded Compact.
|
||||
Embedded systems of that variety are better served by other file
|
||||
systems, like Datalight's Reliance Nitro.
|
||||
|
||||
|
||||
Getting Reliance Edge Working
|
||||
|
||||
Before you can use Reliance Edge, it must be ported and configured. At a
|
||||
minimum, porting includes filling-in functions so that Reliance Edge can
|
||||
issue commands to your storage medium; depending on your needs, other
|
||||
functions may need to be filled in as well. These functions reside in a
|
||||
subdirectory in the os/ directory; see os/stub/ for a blank set of
|
||||
functions. Configuring includes creating a project directory (start by
|
||||
copying projects/newproj) and creating the two configuration files
|
||||
(redconf.h/redconf.c) using the Reliance Edge Configuration Utility
|
||||
(which can be downloaded from http://www.datalight.com/reliance-edge).
|
||||
|
||||
These topics are covered in much greater detail in the _Developer's
|
||||
Guide_, linked above.
|
||||
|
||||
|
||||
Using Reliance Edge
|
||||
|
||||
Using Reliance Edge is a simple matter of including the primary Reliance
|
||||
Edge application header in your application (either include/redposix.h
|
||||
or include/redfse.h) and compiling and linking against Reliance Edge
|
||||
binaries. The Reliance Edge driver must be initialized before it is used
|
||||
(via the red_init() or RedFseInit() functions) and then volumes can be
|
||||
mounted and file and directory functions invoked. The Reliance Edge API
|
||||
is documented in the _Developer's Guide_ (linked above) and also via
|
||||
comments in the source code.
|
||||
|
||||
|
||||
Licensing
|
||||
|
||||
Reliance Edge is an open-source project licensed under the GNU General
|
||||
Public License v2 (GPLv2). Businesses and individuals that for
|
||||
commercial or other reasons cannot comply with the terms of the GPLv2
|
||||
license may obtain a commercial license before incorporating Reliance
|
||||
Edge into proprietary software for distribution in any form. Visit
|
||||
http://www.datalight.com/reliance-edge for more information. The
|
||||
commercial distribution also includes extra tests and tools not
|
||||
distributed with the GPLv2 version.
|
||||
|
||||
See LICENSE.txt for the full license terms of this distribution of the
|
||||
product.
|
||||
|
||||
|
||||
Getting Help
|
||||
|
||||
If you need assistance using Reliance Edge, and you have already
|
||||
consulted the _Developer's Guide_, contact
|
||||
RelianceEdgeSupport@datalight.com.
|
||||
|
||||
In the near future, a community forum or message board will be set up to
|
||||
facilitate discussion of Reliance Edge and allow users to get help from
|
||||
Datalight and from each other. In the meantime, please use the email
|
||||
address given above.
|
||||
|
||||
|
||||
Contributing
|
||||
|
||||
Contributions to Reliance Edge are welcome. Our policy is that Datalight
|
||||
must own the copyright of all code incorporated into Reliance Edge; if
|
||||
contributing a significant amount of code, you will be asked to file a
|
||||
copyright assignment agreement. See CONTRIBUTING.txt for further details
|
||||
and contribution guidelines.
|
||||
|
||||
To report bugs, please create a GitHub issue or contact
|
||||
RelianceEdgeSupport@datalight.com.
|
@@ -0,0 +1,198 @@
|
||||
/* ----> DO NOT REMOVE THE FOLLOWING NOTICE <----
|
||||
|
||||
Copyright (c) 2014-2015 Datalight, Inc.
|
||||
All Rights Reserved Worldwide.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; use version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but "AS-IS," WITHOUT ANY WARRANTY; without even the implied warranty
|
||||
of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
/* Businesses and individuals that for commercial or other reasons cannot
|
||||
comply with the terms of the GPLv2 license may obtain a commercial license
|
||||
before incorporating Reliance Edge into proprietary software for
|
||||
distribution in any form. Visit http://www.datalight.com/reliance-edge for
|
||||
more information.
|
||||
*/
|
||||
/** @file
|
||||
@brief Implements block device I/O using logical blocks as the units.
|
||||
|
||||
The OS block device implementations operate on sectors. The core does I/O
|
||||
in terms of logical blocks: this module translates from logical blocks to
|
||||
sectors.
|
||||
|
||||
If bBlockIoRetries is greater than 0 for the current volume, then this
|
||||
module will retry block device calls on failure up to the configured number
|
||||
of times. This behavior caters to the type of unreliable hardware and
|
||||
drivers that are sometimes found in the IoT world, where one operation may
|
||||
fail but the next may still succeed.
|
||||
*/
|
||||
#include <redfs.h>
|
||||
#include <redcore.h>
|
||||
|
||||
|
||||
/** @brief Read a range of logical blocks.
|
||||
|
||||
@param bVolNum The volume whose block device is being read from.
|
||||
@param ulBlockStart The first block to read.
|
||||
@param ulBlockCount The number of blocks to read.
|
||||
@param pBuffer The buffer to populate with the data read.
|
||||
|
||||
@return A negated ::REDSTATUS code indicating the operation result.
|
||||
|
||||
@retval 0 Operation was successful.
|
||||
@retval -RED_EIO A disk I/O error occurred.
|
||||
@retval -RED_EINVAL Invalid parameters.
|
||||
*/
|
||||
REDSTATUS RedIoRead(
|
||||
uint8_t bVolNum,
|
||||
uint32_t ulBlockStart,
|
||||
uint32_t ulBlockCount,
|
||||
void *pBuffer)
|
||||
{
|
||||
REDSTATUS ret = 0;
|
||||
|
||||
if( (bVolNum >= REDCONF_VOLUME_COUNT)
|
||||
|| (ulBlockStart >= gaRedVolume[bVolNum].ulBlockCount)
|
||||
|| ((gaRedVolume[bVolNum].ulBlockCount - ulBlockStart) < ulBlockCount)
|
||||
|| (ulBlockCount == 0U)
|
||||
|| (pBuffer == NULL))
|
||||
{
|
||||
REDERROR();
|
||||
ret = -RED_EINVAL;
|
||||
}
|
||||
else
|
||||
{
|
||||
uint8_t bSectorShift = gaRedVolume[bVolNum].bBlockSectorShift;
|
||||
uint64_t ullSectorStart = (uint64_t)ulBlockStart << bSectorShift;
|
||||
uint32_t ulSectorCount = ulBlockCount << bSectorShift;
|
||||
uint8_t bRetryIdx;
|
||||
|
||||
REDASSERT(bSectorShift < 32U);
|
||||
REDASSERT((ulSectorCount >> bSectorShift) == ulBlockCount);
|
||||
|
||||
for(bRetryIdx = 0U; bRetryIdx <= gpRedVolConf->bBlockIoRetries; bRetryIdx++)
|
||||
{
|
||||
ret = RedOsBDevRead(bVolNum, ullSectorStart, ulSectorCount, pBuffer);
|
||||
|
||||
if(ret == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CRITICAL_ASSERT(ret == 0);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
#if REDCONF_READ_ONLY == 0
|
||||
/** @brief Write a range of logical blocks.
|
||||
|
||||
@param bVolNum The volume whose block device is being written to.
|
||||
@param ulBlockStart The first block to write.
|
||||
@param ulBlockCount The number of blocks to write.
|
||||
@param pBuffer The buffer containing the data to write.
|
||||
|
||||
@return A negated ::REDSTATUS code indicating the operation result.
|
||||
|
||||
@retval 0 Operation was successful.
|
||||
@retval -RED_EIO A disk I/O error occurred.
|
||||
@retval -RED_EINVAL Invalid parameters.
|
||||
*/
|
||||
REDSTATUS RedIoWrite(
|
||||
uint8_t bVolNum,
|
||||
uint32_t ulBlockStart,
|
||||
uint32_t ulBlockCount,
|
||||
const void *pBuffer)
|
||||
{
|
||||
REDSTATUS ret = 0;
|
||||
|
||||
if( (bVolNum >= REDCONF_VOLUME_COUNT)
|
||||
|| (ulBlockStart >= gaRedVolume[bVolNum].ulBlockCount)
|
||||
|| ((gaRedVolume[bVolNum].ulBlockCount - ulBlockStart) < ulBlockCount)
|
||||
|| (ulBlockCount == 0U)
|
||||
|| (pBuffer == NULL))
|
||||
{
|
||||
REDERROR();
|
||||
ret = -RED_EINVAL;
|
||||
}
|
||||
else
|
||||
{
|
||||
uint8_t bSectorShift = gaRedVolume[bVolNum].bBlockSectorShift;
|
||||
uint64_t ullSectorStart = (uint64_t)ulBlockStart << bSectorShift;
|
||||
uint32_t ulSectorCount = ulBlockCount << bSectorShift;
|
||||
uint8_t bRetryIdx;
|
||||
|
||||
REDASSERT(bSectorShift < 32U);
|
||||
REDASSERT((ulSectorCount >> bSectorShift) == ulBlockCount);
|
||||
|
||||
for(bRetryIdx = 0U; bRetryIdx <= gpRedVolConf->bBlockIoRetries; bRetryIdx++)
|
||||
{
|
||||
ret = RedOsBDevWrite(bVolNum, ullSectorStart, ulSectorCount, pBuffer);
|
||||
|
||||
if(ret == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CRITICAL_ASSERT(ret == 0);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/** @brief Flush any caches beneath the file system.
|
||||
|
||||
@param bVolNum The volume number of the volume whose block device is being
|
||||
flushed.
|
||||
|
||||
@return A negated ::REDSTATUS code indicating the operation result.
|
||||
|
||||
@retval 0 Operation was successful.
|
||||
@retval -RED_EINVAL @p bVolNum is an invalid volume number.
|
||||
@retval -RED_EIO A disk I/O error occurred.
|
||||
*/
|
||||
REDSTATUS RedIoFlush(
|
||||
uint8_t bVolNum)
|
||||
{
|
||||
REDSTATUS ret = 0;
|
||||
|
||||
if(bVolNum >= REDCONF_VOLUME_COUNT)
|
||||
{
|
||||
REDERROR();
|
||||
ret = -RED_EINVAL;
|
||||
}
|
||||
else
|
||||
{
|
||||
uint8_t bRetryIdx;
|
||||
|
||||
for(bRetryIdx = 0U; bRetryIdx <= gpRedVolConf->bBlockIoRetries; bRetryIdx++)
|
||||
{
|
||||
ret = RedOsBDevFlush(bVolNum);
|
||||
|
||||
if(ret == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CRITICAL_ASSERT(ret == 0);
|
||||
|
||||
return ret;
|
||||
}
|
||||
#endif /* REDCONF_READ_ONLY == 0 */
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,958 @@
|
||||
/* ----> DO NOT REMOVE THE FOLLOWING NOTICE <----
|
||||
|
||||
Copyright (c) 2014-2015 Datalight, Inc.
|
||||
All Rights Reserved Worldwide.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; use version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but "AS-IS," WITHOUT ANY WARRANTY; without even the implied warranty
|
||||
of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
/* Businesses and individuals that for commercial or other reasons cannot
|
||||
comply with the terms of the GPLv2 license may obtain a commercial license
|
||||
before incorporating Reliance Edge into proprietary software for
|
||||
distribution in any form. Visit http://www.datalight.com/reliance-edge for
|
||||
more information.
|
||||
*/
|
||||
/** @file
|
||||
@brief Implements directory operations.
|
||||
*/
|
||||
#include <redfs.h>
|
||||
|
||||
#if REDCONF_API_POSIX == 1
|
||||
|
||||
#include <redcore.h>
|
||||
|
||||
|
||||
#define DIR_INDEX_INVALID UINT32_MAX
|
||||
|
||||
#if (REDCONF_NAME_MAX % 4U) != 0U
|
||||
#define DIRENT_PADDING (4U - (REDCONF_NAME_MAX % 4U))
|
||||
#else
|
||||
#define DIRENT_PADDING (0U)
|
||||
#endif
|
||||
#define DIRENT_SIZE (4U + REDCONF_NAME_MAX + DIRENT_PADDING)
|
||||
#define DIRENTS_PER_BLOCK (REDCONF_BLOCK_SIZE / DIRENT_SIZE)
|
||||
#define DIRENTS_MAX (uint32_t)REDMIN(UINT32_MAX, UINT64_SUFFIX(1) * INODE_DATA_BLOCKS * DIRENTS_PER_BLOCK)
|
||||
|
||||
|
||||
/** @brief On-disk directory entry.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
/** The inode number that the directory entry points at. If the directory
|
||||
entry is available, this holds INODE_INVALID.
|
||||
*/
|
||||
uint32_t ulInode;
|
||||
|
||||
/** The name of the directory entry. For names shorter than
|
||||
REDCONF_NAME_MAX, unused bytes in the array are zeroed. For names of
|
||||
the maximum length, the string is not null terminated.
|
||||
*/
|
||||
char acName[REDCONF_NAME_MAX];
|
||||
|
||||
#if DIRENT_PADDING > 0U
|
||||
/** Unused padding so that ulInode is always aligned on a four-byte
|
||||
boundary.
|
||||
*/
|
||||
uint8_t abPadding[DIRENT_PADDING];
|
||||
#endif
|
||||
} DIRENT;
|
||||
|
||||
|
||||
#if (REDCONF_READ_ONLY == 0) && (REDCONF_API_POSIX_RENAME == 1)
|
||||
static REDSTATUS DirCyclicRenameCheck(uint32_t ulSrcInode, const CINODE *pDstPInode);
|
||||
#endif
|
||||
#if REDCONF_READ_ONLY == 0
|
||||
static REDSTATUS DirEntryWrite(CINODE *pPInode, uint32_t ulIdx, uint32_t ulInode, const char *pszName, uint32_t ulNameLen);
|
||||
static uint64_t DirEntryIndexToOffset(uint32_t ulIdx);
|
||||
#endif
|
||||
static uint32_t DirOffsetToEntryIndex(uint64_t ullOffset);
|
||||
|
||||
|
||||
#if REDCONF_READ_ONLY == 0
|
||||
/** @brief Create a new entry in a directory.
|
||||
|
||||
@param pPInode A pointer to the cached inode structure of the directory
|
||||
to which the new entry will be added.
|
||||
@param pszName The name to be given to the new entry, terminated by a
|
||||
null or a path separator.
|
||||
@param ulInode The inode number the new name will point at.
|
||||
|
||||
@return A negated ::REDSTATUS code indicating the operation result.
|
||||
|
||||
@retval 0 Operation was successful.
|
||||
@retval -RED_EIO A disk I/O error occurred.
|
||||
@retval -RED_ENOSPC There is not enough space on the volume to
|
||||
create the new directory entry; or the directory
|
||||
is full.
|
||||
@retval -RED_ENOTDIR @p pPInode is not a directory.
|
||||
@retval -RED_ENAMETOOLONG @p pszName is too long.
|
||||
@retval -RED_EEXIST @p pszName already exists in @p ulPInode.
|
||||
@retval -RED_EINVAL @p pPInode is not a mounted dirty cached inode
|
||||
structure; or @p pszName is not a valid name.
|
||||
*/
|
||||
REDSTATUS RedDirEntryCreate(
|
||||
CINODE *pPInode,
|
||||
const char *pszName,
|
||||
uint32_t ulInode)
|
||||
{
|
||||
REDSTATUS ret;
|
||||
|
||||
if(!CINODE_IS_DIRTY(pPInode) || (pszName == NULL) || !INODE_IS_VALID(ulInode))
|
||||
{
|
||||
ret = -RED_EINVAL;
|
||||
}
|
||||
else if(!pPInode->fDirectory)
|
||||
{
|
||||
ret = -RED_ENOTDIR;
|
||||
}
|
||||
else
|
||||
{
|
||||
uint32_t ulNameLen = RedNameLen(pszName);
|
||||
|
||||
if(ulNameLen == 0U)
|
||||
{
|
||||
ret = -RED_EINVAL;
|
||||
}
|
||||
else if(ulNameLen > REDCONF_NAME_MAX)
|
||||
{
|
||||
ret = -RED_ENAMETOOLONG;
|
||||
}
|
||||
else
|
||||
{
|
||||
uint32_t ulEntryIdx;
|
||||
|
||||
ret = RedDirEntryLookup(pPInode, pszName, &ulEntryIdx, NULL);
|
||||
if(ret == 0)
|
||||
{
|
||||
ret = -RED_EEXIST;
|
||||
}
|
||||
else if(ret == -RED_ENOENT)
|
||||
{
|
||||
if(ulEntryIdx == DIR_INDEX_INVALID)
|
||||
{
|
||||
ret = -RED_ENOSPC;
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Unexpected error, no action.
|
||||
*/
|
||||
}
|
||||
|
||||
if(ret == 0)
|
||||
{
|
||||
ret = DirEntryWrite(pPInode, ulEntryIdx, ulInode, pszName, ulNameLen);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
#endif /* REDCONF_READ_ONLY == 0 */
|
||||
|
||||
|
||||
#if DELETE_SUPPORTED
|
||||
/** @brief Delete an existing directory entry.
|
||||
|
||||
@param pPInode A pointer to the cached inode structure of the directory
|
||||
containing the entry to be deleted.
|
||||
@param ulDeleteIdx Position within the directory of the entry to be
|
||||
deleted.
|
||||
|
||||
@return A negated ::REDSTATUS code indicating the operation result.
|
||||
|
||||
@retval 0 Operation was successful.
|
||||
@retval -RED_EIO A disk I/O error occurred.
|
||||
@retval -RED_ENOSPC The file system does not have enough space to modify
|
||||
the parent directory to perform the deletion.
|
||||
@retval -RED_ENOTDIR @p pPInode is not a directory.
|
||||
@retval -RED_EINVAL @p pPInode is not a mounted dirty cached inode
|
||||
structure; or @p ulIdx is out of range.
|
||||
*/
|
||||
REDSTATUS RedDirEntryDelete(
|
||||
CINODE *pPInode,
|
||||
uint32_t ulDeleteIdx)
|
||||
{
|
||||
REDSTATUS ret = 0;
|
||||
|
||||
if(!CINODE_IS_DIRTY(pPInode) || (ulDeleteIdx >= DIRENTS_MAX))
|
||||
{
|
||||
ret = -RED_EINVAL;
|
||||
}
|
||||
else if(!pPInode->fDirectory)
|
||||
{
|
||||
ret = -RED_ENOTDIR;
|
||||
}
|
||||
else if((DirEntryIndexToOffset(ulDeleteIdx) + DIRENT_SIZE) == pPInode->pInodeBuf->ullSize)
|
||||
{
|
||||
/* Start searching one behind the index to be deleted.
|
||||
*/
|
||||
uint32_t ulTruncIdx = ulDeleteIdx - 1U;
|
||||
bool fDone = false;
|
||||
|
||||
/* We are deleting the last dirent in the directory, so search
|
||||
backwards to find the last populated dirent, allowing us to truncate
|
||||
the directory to that point.
|
||||
*/
|
||||
while((ret == 0) && (ulTruncIdx != UINT32_MAX) && !fDone)
|
||||
{
|
||||
ret = RedInodeDataSeekAndRead(pPInode, ulTruncIdx / DIRENTS_PER_BLOCK);
|
||||
|
||||
if(ret == 0)
|
||||
{
|
||||
const DIRENT *pDirents = CAST_CONST_DIRENT_PTR(pPInode->pbData);
|
||||
uint32_t ulBlockIdx = ulTruncIdx % DIRENTS_PER_BLOCK;
|
||||
|
||||
do
|
||||
{
|
||||
if(pDirents[ulBlockIdx].ulInode != INODE_INVALID)
|
||||
{
|
||||
fDone = true;
|
||||
break;
|
||||
}
|
||||
|
||||
ulTruncIdx--;
|
||||
ulBlockIdx--;
|
||||
} while(ulBlockIdx != UINT32_MAX);
|
||||
}
|
||||
else if(ret == -RED_ENODATA)
|
||||
{
|
||||
ret = 0;
|
||||
|
||||
REDASSERT((ulTruncIdx % DIRENTS_PER_BLOCK) == 0U);
|
||||
ulTruncIdx -= DIRENTS_PER_BLOCK;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Unexpected error, loop will terminate; nothing else
|
||||
to be done.
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
/* Currently ulTruncIdx represents the last valid dirent index, or
|
||||
UINT32_MAX if the directory is now empty. Increment it so that it
|
||||
represents the first invalid entry, which will be truncated.
|
||||
*/
|
||||
ulTruncIdx++;
|
||||
|
||||
/* Truncate the directory, deleting the requested entry and any empty
|
||||
dirents at the end of the directory.
|
||||
*/
|
||||
if(ret == 0)
|
||||
{
|
||||
ret = RedInodeDataTruncate(pPInode, DirEntryIndexToOffset(ulTruncIdx));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* The dirent to delete is not the last entry in the directory, so just
|
||||
zero it.
|
||||
*/
|
||||
ret = DirEntryWrite(pPInode, ulDeleteIdx, INODE_INVALID, "", 0U);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
#endif /* DELETE_SUPPORTED */
|
||||
|
||||
|
||||
/** @brief Perform a case-sensitive search of a directory for a given name.
|
||||
|
||||
If found, then position of the entry within the directory and the inode
|
||||
number it points to are returned. As an optimization for directory entry
|
||||
creation, in the case where the requested entry does not exist, the position
|
||||
of the first available (unused) entry is returned.
|
||||
|
||||
@param pPInode A pointer to the cached inode structure of the directory
|
||||
to search.
|
||||
@param pszName The name of the desired entry, terminated by either a
|
||||
null or a path separator.
|
||||
@param pulEntryIdx On successful return, meaning that the desired entry
|
||||
exists, populated with the position of the entry. If
|
||||
returning an -RED_ENOENT error, populated with the
|
||||
position of the first available entry, or set to
|
||||
DIR_INDEX_INVALID if the directory is full. Optional.
|
||||
@param pulInode On successful return, populated with the inode number
|
||||
that the name points to. Optional; may be `NULL`.
|
||||
|
||||
@return A negated ::REDSTATUS code indicating the operation result.
|
||||
|
||||
@retval 0 Operation was successful.
|
||||
@retval -RED_EIO A disk I/O error occurred.
|
||||
@retval -RED_ENOENT @p pszName does not name an existing file or
|
||||
directory.
|
||||
@retval -RED_ENOTDIR @p pPInode is not a directory.
|
||||
@retval -RED_EINVAL @p pPInode is not a mounted cached inode
|
||||
structure; or @p pszName is not a valid name; or
|
||||
@p pulEntryIdx is `NULL`.
|
||||
@retval -RED_ENAMETOOLONG @p pszName is too long.
|
||||
*/
|
||||
REDSTATUS RedDirEntryLookup(
|
||||
CINODE *pPInode,
|
||||
const char *pszName,
|
||||
uint32_t *pulEntryIdx,
|
||||
uint32_t *pulInode)
|
||||
{
|
||||
REDSTATUS ret = 0;
|
||||
|
||||
if(!CINODE_IS_MOUNTED(pPInode) || (pszName == NULL))
|
||||
{
|
||||
ret = -RED_EINVAL;
|
||||
}
|
||||
else if(!pPInode->fDirectory)
|
||||
{
|
||||
ret = -RED_ENOTDIR;
|
||||
}
|
||||
else
|
||||
{
|
||||
uint32_t ulNameLen = RedNameLen(pszName);
|
||||
|
||||
if(ulNameLen == 0U)
|
||||
{
|
||||
ret = -RED_EINVAL;
|
||||
}
|
||||
else if(ulNameLen > REDCONF_NAME_MAX)
|
||||
{
|
||||
ret = -RED_ENAMETOOLONG;
|
||||
}
|
||||
else
|
||||
{
|
||||
uint32_t ulIdx = 0U;
|
||||
uint32_t ulDirentCount = DirOffsetToEntryIndex(pPInode->pInodeBuf->ullSize);
|
||||
uint32_t ulFreeIdx = DIR_INDEX_INVALID; /* Index of first free dirent. */
|
||||
|
||||
/* Loop over the directory blocks, searching each block for a
|
||||
dirent that matches the given name.
|
||||
*/
|
||||
while((ret == 0) && (ulIdx < ulDirentCount))
|
||||
{
|
||||
ret = RedInodeDataSeekAndRead(pPInode, ulIdx / DIRENTS_PER_BLOCK);
|
||||
|
||||
if(ret == 0)
|
||||
{
|
||||
const DIRENT *pDirents = CAST_CONST_DIRENT_PTR(pPInode->pbData);
|
||||
uint32_t ulBlockLastIdx = REDMIN(DIRENTS_PER_BLOCK, ulDirentCount - ulIdx);
|
||||
uint32_t ulBlockIdx;
|
||||
|
||||
for(ulBlockIdx = 0U; ulBlockIdx < ulBlockLastIdx; ulBlockIdx++)
|
||||
{
|
||||
const DIRENT *pDirent = &pDirents[ulBlockIdx];
|
||||
|
||||
if(pDirent->ulInode != INODE_INVALID)
|
||||
{
|
||||
/* The name in the dirent will not be null
|
||||
terminated if it is of the maximum length, so
|
||||
use a bounded string compare and then make sure
|
||||
there is nothing more to the name.
|
||||
*/
|
||||
if( (RedStrNCmp(pDirent->acName, pszName, ulNameLen) == 0)
|
||||
&& ((ulNameLen == REDCONF_NAME_MAX) || (pDirent->acName[ulNameLen] == '\0')))
|
||||
{
|
||||
/* Found a matching dirent, stop and return its
|
||||
information.
|
||||
*/
|
||||
if(pulInode != NULL)
|
||||
{
|
||||
*pulInode = pDirent->ulInode;
|
||||
|
||||
#ifdef REDCONF_ENDIAN_SWAP
|
||||
*pulInode = RedRev32(*pulInode);
|
||||
#endif
|
||||
}
|
||||
|
||||
ulIdx += ulBlockIdx;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if(ulFreeIdx == DIR_INDEX_INVALID)
|
||||
{
|
||||
ulFreeIdx = ulIdx + ulBlockIdx;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* The directory entry is free, but we already found a free one, so there's
|
||||
nothing to do here.
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
if(ulBlockIdx < ulBlockLastIdx)
|
||||
{
|
||||
/* If we broke out of the for loop, we found a matching
|
||||
dirent and can stop the search.
|
||||
*/
|
||||
break;
|
||||
}
|
||||
|
||||
ulIdx += ulBlockLastIdx;
|
||||
}
|
||||
else if(ret == -RED_ENODATA)
|
||||
{
|
||||
if(ulFreeIdx == DIR_INDEX_INVALID)
|
||||
{
|
||||
ulFreeIdx = ulIdx;
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
ulIdx += DIRENTS_PER_BLOCK;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Unexpected error, let the loop terminate, no action
|
||||
here.
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
if(ret == 0)
|
||||
{
|
||||
/* If we made it all the way to the end of the directory
|
||||
without stopping, then the given name does not exist in the
|
||||
directory.
|
||||
*/
|
||||
if(ulIdx == ulDirentCount)
|
||||
{
|
||||
/* If the directory had no sparse dirents, then the first
|
||||
free dirent is beyond the end of the directory. If the
|
||||
directory is already the maximum size, then there is no
|
||||
free dirent.
|
||||
*/
|
||||
if((ulFreeIdx == DIR_INDEX_INVALID) && (ulDirentCount < DIRENTS_MAX))
|
||||
{
|
||||
ulFreeIdx = ulDirentCount;
|
||||
}
|
||||
|
||||
ulIdx = ulFreeIdx;
|
||||
|
||||
ret = -RED_ENOENT;
|
||||
}
|
||||
|
||||
if(pulEntryIdx != NULL)
|
||||
{
|
||||
*pulEntryIdx = ulIdx;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
#if (REDCONF_API_POSIX_READDIR == 1) || (REDCONF_CHECKER == 1)
|
||||
/** @brief Read the next entry from a directory, given a starting index.
|
||||
|
||||
@param pPInode A pointer to the cached inode structure of the directory to
|
||||
read from.
|
||||
@param pulIdx On entry, the directory index to start reading from. On
|
||||
successful return, populated with the directory index to use
|
||||
for subsequent reads. On -RED_ENOENT return, populated with
|
||||
the directory index immediately following the last valid
|
||||
one.
|
||||
@param pszName On successful return, populated with the name of the next
|
||||
directory entry. Buffer must be at least
|
||||
REDCONF_NAME_MAX + 1 in size, to store the maximum name
|
||||
length plus a null terminator.
|
||||
@param pulInode On successful return, populated with the inode number
|
||||
pointed at by the next directory entry.
|
||||
|
||||
@return A negated ::REDSTATUS code indicating the operation result.
|
||||
|
||||
@retval 0 Operation was successful.
|
||||
@retval -RED_EIO A disk I/O error occurred.
|
||||
@retval -RED_ENOENT There are no more entries in the directory.
|
||||
@retval -RED_ENOTDIR @p pPInode is not a directory.
|
||||
@retval -RED_EINVAL @p pPInode is not a mounted cached inode structure;
|
||||
or @p pszName is `NULL`; or @p pulIdx is `NULL`; or
|
||||
@p pulInode is `NULL`.
|
||||
*/
|
||||
REDSTATUS RedDirEntryRead(
|
||||
CINODE *pPInode,
|
||||
uint32_t *pulIdx,
|
||||
char *pszName,
|
||||
uint32_t *pulInode)
|
||||
{
|
||||
REDSTATUS ret = 0;
|
||||
|
||||
if(!CINODE_IS_MOUNTED(pPInode) || (pulIdx == NULL) || (pszName == NULL) || (pulInode == NULL))
|
||||
{
|
||||
ret = -RED_EINVAL;
|
||||
}
|
||||
else if(!pPInode->fDirectory)
|
||||
{
|
||||
ret = -RED_ENOTDIR;
|
||||
}
|
||||
else
|
||||
{
|
||||
uint32_t ulIdx = *pulIdx;
|
||||
uint32_t ulDirentCount = DirOffsetToEntryIndex(pPInode->pInodeBuf->ullSize);
|
||||
|
||||
/* Starting either at the beginning of the directory or where we left
|
||||
off, loop over the directory blocks, searching each block for a
|
||||
non-sparse dirent to return as the next entry in the directory.
|
||||
*/
|
||||
while((ret == 0) && (ulIdx < ulDirentCount))
|
||||
{
|
||||
uint32_t ulBlockOffset = ulIdx / DIRENTS_PER_BLOCK;
|
||||
|
||||
ret = RedInodeDataSeekAndRead(pPInode, ulBlockOffset);
|
||||
|
||||
if(ret == 0)
|
||||
{
|
||||
const DIRENT *pDirents = CAST_CONST_DIRENT_PTR(pPInode->pbData);
|
||||
uint32_t ulBlockLastIdx = REDMIN(DIRENTS_PER_BLOCK, ulDirentCount - (ulBlockOffset * DIRENTS_PER_BLOCK));
|
||||
uint32_t ulBlockIdx;
|
||||
|
||||
for(ulBlockIdx = ulIdx % DIRENTS_PER_BLOCK; ulBlockIdx < ulBlockLastIdx; ulBlockIdx++)
|
||||
{
|
||||
if(pDirents[ulBlockIdx].ulInode != INODE_INVALID)
|
||||
{
|
||||
*pulIdx = ulIdx + 1U;
|
||||
RedStrNCpy(pszName, pDirents[ulBlockIdx].acName, REDCONF_NAME_MAX);
|
||||
pszName[REDCONF_NAME_MAX] = '\0';
|
||||
|
||||
*pulInode = pDirents[ulBlockIdx].ulInode;
|
||||
|
||||
#ifdef REDCONF_ENDIAN_SWAP
|
||||
*pulInode = RedRev32(*pulInode);
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
|
||||
ulIdx++;
|
||||
}
|
||||
|
||||
if(ulBlockIdx < ulBlockLastIdx)
|
||||
{
|
||||
REDASSERT(ulIdx <= ulDirentCount);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if(ret == -RED_ENODATA)
|
||||
{
|
||||
ulIdx += DIRENTS_PER_BLOCK - (ulIdx % DIRENTS_PER_BLOCK);
|
||||
ret = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Unexpected error, loop will terminate; nothing else to do.
|
||||
*/
|
||||
}
|
||||
|
||||
REDASSERT(ulIdx <= ulDirentCount);
|
||||
}
|
||||
|
||||
if((ret == 0) && (ulIdx >= ulDirentCount))
|
||||
{
|
||||
*pulIdx = ulDirentCount;
|
||||
ret = -RED_ENOENT;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#if (REDCONF_READ_ONLY == 0) && (REDCONF_API_POSIX_RENAME == 1)
|
||||
/** Rename a directory entry.
|
||||
|
||||
@param pSrcPInode The inode of the directory containing @p pszSrcName.
|
||||
@param pszSrcName The name of the directory entry to be renamed.
|
||||
@param pSrcInode On successful return, populated with the inode of the
|
||||
source entry.
|
||||
@param pDstPInode The inode of the directory in which @p pszDstName will
|
||||
be created or replaced.
|
||||
@param pszDstName The name of the directory entry to be created or
|
||||
replaced.
|
||||
@param pDstInode On successful return, if the destination previously
|
||||
existed, populated with the inode previously pointed to
|
||||
by the destination. This may be the same as the source
|
||||
inode. If the destination did not exist, populated with
|
||||
INODE_INVALID.
|
||||
|
||||
@return A negated ::REDSTATUS code indicating the operation result.
|
||||
|
||||
@retval 0 Operation was successful.
|
||||
@retval -RED_EEXIST #REDCONF_RENAME_ATOMIC is false and the
|
||||
destination name exists.
|
||||
@retval -RED_EINVAL @p pSrcPInode is not a mounted dirty cached
|
||||
inode structure; or @p pSrcInode is `NULL`; or
|
||||
@p pszSrcName is not a valid name; or
|
||||
@p pDstPInode is not a mounted dirty cached
|
||||
inode structure; or @p pDstInode is `NULL`; or
|
||||
@p pszDstName is not a valid name.
|
||||
@retval -RED_EIO A disk I/O error occurred.
|
||||
@retval -RED_EISDIR The destination name exists and is a directory,
|
||||
and the source name is a non-directory.
|
||||
@retval -RED_ENAMETOOLONG Either @p pszSrcName or @p pszDstName is longer
|
||||
than #REDCONF_NAME_MAX.
|
||||
@retval -RED_ENOENT The source name is not an existing entry; or
|
||||
either @p pszSrcName or @p pszDstName point to
|
||||
an empty string.
|
||||
@retval -RED_ENOTDIR @p pSrcPInode is not a directory; or
|
||||
@p pDstPInode is not a directory; or the source
|
||||
name is a directory and the destination name is
|
||||
a file.
|
||||
@retval -RED_ENOTEMPTY The destination name is a directory which is not
|
||||
empty.
|
||||
@retval -RED_ENOSPC The file system does not have enough space to
|
||||
extend the @p ulDstPInode directory.
|
||||
@retval -RED_EROFS The directory to be removed resides on a
|
||||
read-only file system.
|
||||
*/
|
||||
REDSTATUS RedDirEntryRename(
|
||||
CINODE *pSrcPInode,
|
||||
const char *pszSrcName,
|
||||
CINODE *pSrcInode,
|
||||
CINODE *pDstPInode,
|
||||
const char *pszDstName,
|
||||
CINODE *pDstInode)
|
||||
{
|
||||
REDSTATUS ret;
|
||||
|
||||
if( !CINODE_IS_DIRTY(pSrcPInode)
|
||||
|| (pszSrcName == NULL)
|
||||
|| (pSrcInode == NULL)
|
||||
|| !CINODE_IS_DIRTY(pDstPInode)
|
||||
|| (pszDstName == NULL)
|
||||
|| (pDstInode == NULL))
|
||||
{
|
||||
ret = -RED_EINVAL;
|
||||
}
|
||||
else if(!pSrcPInode->fDirectory || !pDstPInode->fDirectory)
|
||||
{
|
||||
ret = -RED_ENOTDIR;
|
||||
}
|
||||
else
|
||||
{
|
||||
uint32_t ulDstIdx = 0U; /* Init'd to quiet warnings. */
|
||||
uint32_t ulSrcIdx;
|
||||
|
||||
/* Look up the source and destination names.
|
||||
*/
|
||||
ret = RedDirEntryLookup(pSrcPInode, pszSrcName, &ulSrcIdx, &pSrcInode->ulInode);
|
||||
|
||||
if(ret == 0)
|
||||
{
|
||||
ret = RedDirEntryLookup(pDstPInode, pszDstName, &ulDstIdx, &pDstInode->ulInode);
|
||||
|
||||
if(ret == -RED_ENOENT)
|
||||
{
|
||||
if(ulDstIdx == DIR_INDEX_INVALID)
|
||||
{
|
||||
ret = -RED_ENOSPC;
|
||||
}
|
||||
else
|
||||
{
|
||||
#if REDCONF_RENAME_ATOMIC == 1
|
||||
pDstInode->ulInode = INODE_INVALID;
|
||||
#endif
|
||||
ret = 0;
|
||||
}
|
||||
}
|
||||
#if REDCONF_RENAME_ATOMIC == 0
|
||||
else if(ret == 0)
|
||||
{
|
||||
ret = -RED_EEXIST;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Nothing to do here, just propagate the error.
|
||||
*/
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#if REDCONF_RENAME_ATOMIC == 1
|
||||
/* If both names point to the same inode, POSIX says to do nothing to
|
||||
either name.
|
||||
*/
|
||||
if((ret == 0) && (pSrcInode->ulInode != pDstInode->ulInode))
|
||||
#else
|
||||
if(ret == 0)
|
||||
#endif
|
||||
{
|
||||
ret = RedInodeMount(pSrcInode, FTYPE_EITHER, true);
|
||||
|
||||
#if REDCONF_RENAME_ATOMIC == 1
|
||||
if((ret == 0) && (pDstInode->ulInode != INODE_INVALID))
|
||||
{
|
||||
/* Source and destination must be the same type (file/dir).
|
||||
*/
|
||||
ret = RedInodeMount(pDstInode, pSrcInode->fDirectory ? FTYPE_DIR : FTYPE_FILE, true);
|
||||
|
||||
/* If renaming directories, the destination must be empty.
|
||||
*/
|
||||
if((ret == 0) && pDstInode->fDirectory && (pDstInode->pInodeBuf->ullSize > 0U))
|
||||
{
|
||||
ret = -RED_ENOTEMPTY;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* If we are renaming a directory, make sure the rename isn't
|
||||
cyclic (e.g., renaming "foo" into "foo/bar").
|
||||
*/
|
||||
if((ret == 0) && pSrcInode->fDirectory)
|
||||
{
|
||||
ret = DirCyclicRenameCheck(pSrcInode->ulInode, pDstPInode);
|
||||
}
|
||||
|
||||
if(ret == 0)
|
||||
{
|
||||
ret = DirEntryWrite(pDstPInode, ulDstIdx, pSrcInode->ulInode, pszDstName, RedNameLen(pszDstName));
|
||||
}
|
||||
|
||||
if(ret == 0)
|
||||
{
|
||||
ret = RedDirEntryDelete(pSrcPInode, ulSrcIdx);
|
||||
|
||||
if(ret == -RED_ENOSPC)
|
||||
{
|
||||
REDSTATUS ret2;
|
||||
|
||||
/* If there was not enough space to branch the parent
|
||||
directory inode and data block containin the source
|
||||
entry, revert destination directory entry to its
|
||||
previous state.
|
||||
*/
|
||||
#if REDCONF_RENAME_ATOMIC == 1
|
||||
if(pDstInode->ulInode != INODE_INVALID)
|
||||
{
|
||||
ret2 = DirEntryWrite(pDstPInode, ulDstIdx, pDstInode->ulInode, pszDstName, RedNameLen(pszDstName));
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
ret2 = RedDirEntryDelete(pDstPInode, ulDstIdx);
|
||||
}
|
||||
|
||||
if(ret2 != 0)
|
||||
{
|
||||
ret = ret2;
|
||||
CRITICAL_ERROR();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(ret == 0)
|
||||
{
|
||||
pSrcInode->pInodeBuf->ulPInode = pDstPInode->ulInode;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/** @brief Check for a cyclic rename.
|
||||
|
||||
A cyclic rename is renaming a directory into a subdirectory of itself. For
|
||||
example, renaming "a" into "a/b/c/d" is cyclic. These renames must not be
|
||||
allowed since they would corrupt the directory tree.
|
||||
|
||||
@param ulSrcInode The inode number of the directory being renamed.
|
||||
@param pDstPInode A pointer to the cached inode structure of the directory
|
||||
into which the source is being renamed.
|
||||
|
||||
@return A negated ::REDSTATUS code indicating the operation result.
|
||||
|
||||
@retval 0 Operation was successful.
|
||||
@retval -RED_EIO A disk I/O error occurred.
|
||||
@retval -RED_EINVAL The rename is cyclic; or invalid parameters.
|
||||
@retval -RED_ENOTDIR @p pDstPInode is not a directory.
|
||||
*/
|
||||
static REDSTATUS DirCyclicRenameCheck(
|
||||
uint32_t ulSrcInode,
|
||||
const CINODE *pDstPInode)
|
||||
{
|
||||
REDSTATUS ret = 0;
|
||||
|
||||
if(!INODE_IS_VALID(ulSrcInode) || !CINODE_IS_MOUNTED(pDstPInode))
|
||||
{
|
||||
REDERROR();
|
||||
ret = -RED_EINVAL;
|
||||
}
|
||||
else if(ulSrcInode == pDstPInode->ulInode)
|
||||
{
|
||||
ret = -RED_EINVAL;
|
||||
}
|
||||
else if(!pDstPInode->fDirectory)
|
||||
{
|
||||
ret = -RED_ENOTDIR;
|
||||
}
|
||||
else
|
||||
{
|
||||
CINODE NextParent;
|
||||
/* Used to prevent infinite loop in case of corrupted directory
|
||||
structure.
|
||||
*/
|
||||
uint32_t ulIteration = 0U;
|
||||
|
||||
NextParent.ulInode = pDstPInode->pInodeBuf->ulPInode;
|
||||
|
||||
while( (NextParent.ulInode != ulSrcInode)
|
||||
&& (NextParent.ulInode != INODE_ROOTDIR)
|
||||
&& (NextParent.ulInode != INODE_INVALID)
|
||||
&& (ulIteration < gpRedVolConf->ulInodeCount))
|
||||
{
|
||||
ret = RedInodeMount(&NextParent, FTYPE_DIR, false);
|
||||
if(ret != 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
NextParent.ulInode = NextParent.pInodeBuf->ulPInode;
|
||||
|
||||
RedInodePut(&NextParent, 0U);
|
||||
|
||||
ulIteration++;
|
||||
}
|
||||
|
||||
if((ret == 0) && (ulIteration == gpRedVolConf->ulInodeCount))
|
||||
{
|
||||
CRITICAL_ERROR();
|
||||
ret = -RED_EFUBAR;
|
||||
}
|
||||
|
||||
if((ret == 0) && (ulSrcInode == NextParent.ulInode))
|
||||
{
|
||||
ret = -RED_EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
#endif /* (REDCONF_READ_ONLY == 0) && (REDCONF_API_POSIX_RENAME == 1) */
|
||||
|
||||
|
||||
#if REDCONF_READ_ONLY == 0
|
||||
/** @brief Update the contents of a directory entry.
|
||||
|
||||
@param pPInode A pointer to the cached inode structure of the directory
|
||||
whose entry is being written.
|
||||
@param ulIdx The index of the directory entry to write.
|
||||
@param ulInode The inode number the directory entry is to point at.
|
||||
@param pszName The name of the directory entry.
|
||||
@param ulNameLen The length of @p pszName.
|
||||
|
||||
@return A negated ::REDSTATUS code indicating the operation result.
|
||||
|
||||
@retval 0 Operation was successful.
|
||||
@retval -RED_EIO A disk I/O error occurred.
|
||||
@retval -RED_ENOSPC There is not enough space on the volume to write the
|
||||
directory entry.
|
||||
@retval -RED_ENOTDIR @p pPInode is not a directory.
|
||||
@retval -RED_EINVAL Invalid parameters.
|
||||
*/
|
||||
static REDSTATUS DirEntryWrite(
|
||||
CINODE *pPInode,
|
||||
uint32_t ulIdx,
|
||||
uint32_t ulInode,
|
||||
const char *pszName,
|
||||
uint32_t ulNameLen)
|
||||
{
|
||||
REDSTATUS ret;
|
||||
|
||||
if( !CINODE_IS_DIRTY(pPInode)
|
||||
|| (ulIdx >= DIRENTS_MAX)
|
||||
|| (!INODE_IS_VALID(ulInode) && (ulInode != INODE_INVALID))
|
||||
|| (pszName == NULL)
|
||||
|| (ulNameLen > REDCONF_NAME_MAX)
|
||||
|| ((ulNameLen == 0U) != (ulInode == INODE_INVALID)))
|
||||
{
|
||||
REDERROR();
|
||||
ret = -RED_EINVAL;
|
||||
}
|
||||
else if(!pPInode->fDirectory)
|
||||
{
|
||||
ret = -RED_ENOTDIR;
|
||||
}
|
||||
else
|
||||
{
|
||||
uint64_t ullOffset = DirEntryIndexToOffset(ulIdx);
|
||||
uint32_t ulLen = DIRENT_SIZE;
|
||||
static DIRENT de;
|
||||
|
||||
RedMemSet(&de, 0U, sizeof(de));
|
||||
|
||||
de.ulInode = ulInode;
|
||||
|
||||
#ifdef REDCONF_ENDIAN_SWAP
|
||||
de.ulInode = RedRev32(de.ulInode);
|
||||
#endif
|
||||
|
||||
RedStrNCpy(de.acName, pszName, ulNameLen);
|
||||
|
||||
ret = RedInodeDataWrite(pPInode, ullOffset, &ulLen, &de);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/** @brief Convert a directory entry index to a byte offset.
|
||||
|
||||
@param ulIdx Directory entry index.
|
||||
|
||||
@return Byte offset in the directory corresponding with ulIdx.
|
||||
*/
|
||||
static uint64_t DirEntryIndexToOffset(
|
||||
uint32_t ulIdx)
|
||||
{
|
||||
uint32_t ulBlock = ulIdx / DIRENTS_PER_BLOCK;
|
||||
uint32_t ulOffsetInBlock = ulIdx % DIRENTS_PER_BLOCK;
|
||||
uint64_t ullOffset;
|
||||
|
||||
REDASSERT(ulIdx < DIRENTS_MAX);
|
||||
|
||||
ullOffset = (uint64_t)ulBlock << BLOCK_SIZE_P2;
|
||||
ullOffset += (uint64_t)ulOffsetInBlock * DIRENT_SIZE;
|
||||
|
||||
return ullOffset;
|
||||
}
|
||||
#endif /* REDCONF_READ_ONLY == 0 */
|
||||
|
||||
|
||||
/** @brief Convert a byte offset to a directory entry index.
|
||||
|
||||
@param ullOffset Byte offset in the directory.
|
||||
|
||||
@return Directory entry index corresponding with @p ullOffset.
|
||||
*/
|
||||
static uint32_t DirOffsetToEntryIndex(
|
||||
uint64_t ullOffset)
|
||||
{
|
||||
uint32_t ulIdx;
|
||||
|
||||
REDASSERT(ullOffset < INODE_SIZE_MAX);
|
||||
REDASSERT(((uint32_t)(ullOffset & (REDCONF_BLOCK_SIZE - 1U)) % DIRENT_SIZE) == 0U);
|
||||
|
||||
/* Avoid doing any 64-bit divides.
|
||||
*/
|
||||
ulIdx = (uint32_t)(ullOffset >> BLOCK_SIZE_P2) * DIRENTS_PER_BLOCK;
|
||||
ulIdx += (uint32_t)(ullOffset & (REDCONF_BLOCK_SIZE - 1U)) / DIRENT_SIZE;
|
||||
|
||||
return ulIdx;
|
||||
}
|
||||
|
||||
|
||||
#endif /* REDCONF_API_POSIX == 1 */
|
||||
|
@@ -0,0 +1,235 @@
|
||||
/* ----> DO NOT REMOVE THE FOLLOWING NOTICE <----
|
||||
|
||||
Copyright (c) 2014-2015 Datalight, Inc.
|
||||
All Rights Reserved Worldwide.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; use version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but "AS-IS," WITHOUT ANY WARRANTY; without even the implied warranty
|
||||
of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
/* Businesses and individuals that for commercial or other reasons cannot
|
||||
comply with the terms of the GPLv2 license may obtain a commercial license
|
||||
before incorporating Reliance Edge into proprietary software for
|
||||
distribution in any form. Visit http://www.datalight.com/reliance-edge for
|
||||
more information.
|
||||
*/
|
||||
/** @file
|
||||
@brief Implements the Reliance Edge file system formatter.
|
||||
*/
|
||||
#include <redfs.h>
|
||||
#include <redcoreapi.h>
|
||||
#include <redcore.h>
|
||||
|
||||
#if FORMAT_SUPPORTED
|
||||
|
||||
|
||||
/** @brief Format a file system volume.
|
||||
|
||||
@return A negated ::REDSTATUS code indicating the operation result.
|
||||
|
||||
@retval 0 Operation was successful.
|
||||
@retval -RED_EBUSY Volume is mounted.
|
||||
@retval -RED_EIO A disk I/O error occurred.
|
||||
*/
|
||||
REDSTATUS RedVolFormat(void)
|
||||
{
|
||||
REDSTATUS ret;
|
||||
|
||||
if(gpRedVolume->fMounted)
|
||||
{
|
||||
ret = -RED_EBUSY;
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = RedOsBDevOpen(gbRedVolNum, BDEV_O_RDWR);
|
||||
}
|
||||
|
||||
if(ret == 0)
|
||||
{
|
||||
MASTERBLOCK *pMB;
|
||||
REDSTATUS ret2;
|
||||
|
||||
/* Overwrite the master block with zeroes, so that if formatting is
|
||||
interrupted, the volume will not be mountable.
|
||||
*/
|
||||
ret = RedBufferGet(BLOCK_NUM_MASTER, BFLAG_NEW | BFLAG_DIRTY, CAST_VOID_PTR_PTR(&pMB));
|
||||
|
||||
if(ret == 0)
|
||||
{
|
||||
ret = RedBufferFlush(BLOCK_NUM_MASTER, 1U);
|
||||
|
||||
RedBufferDiscard(pMB);
|
||||
}
|
||||
|
||||
if(ret == 0)
|
||||
{
|
||||
ret = RedIoFlush(gbRedVolNum);
|
||||
}
|
||||
|
||||
#if REDCONF_IMAP_EXTERNAL == 1
|
||||
if((ret == 0) && !gpRedCoreVol->fImapInline)
|
||||
{
|
||||
uint32_t ulImapBlock;
|
||||
uint32_t ulImapBlockLimit = gpRedCoreVol->ulImapStartBN + (gpRedCoreVol->ulImapNodeCount * 2U);
|
||||
uint16_t uImapFlags = (uint16_t)((uint32_t)BFLAG_META_IMAP | BFLAG_NEW | BFLAG_DIRTY);
|
||||
|
||||
/* Technically it is only necessary to create one copy of each imap
|
||||
node (the copy the metaroot points at), but creating them both
|
||||
avoids headaches during disk image analysis from stale imaps
|
||||
left over from previous formats.
|
||||
*/
|
||||
for(ulImapBlock = gpRedCoreVol->ulImapStartBN; ulImapBlock < ulImapBlockLimit; ulImapBlock++)
|
||||
{
|
||||
IMAPNODE *pImap;
|
||||
|
||||
ret = RedBufferGet(ulImapBlock, uImapFlags, CAST_VOID_PTR_PTR(&pImap));
|
||||
if(ret != 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
RedBufferPut(pImap);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Write the first metaroot.
|
||||
*/
|
||||
if(ret == 0)
|
||||
{
|
||||
RedMemSet(gpRedMR, 0U, sizeof(*gpRedMR));
|
||||
|
||||
gpRedMR->ulFreeBlocks = gpRedVolume->ulBlocksAllocable;
|
||||
#if REDCONF_API_POSIX == 1
|
||||
gpRedMR->ulFreeInodes = gpRedVolConf->ulInodeCount;
|
||||
#endif
|
||||
gpRedMR->ulAllocNextBlock = gpRedCoreVol->ulFirstAllocableBN;
|
||||
|
||||
/* The branched flag is typically set automatically when bits in
|
||||
the imap change. It is set here explicitly because the imap has
|
||||
only been initialized, not changed.
|
||||
*/
|
||||
gpRedCoreVol->fBranched = true;
|
||||
|
||||
ret = RedVolTransact();
|
||||
}
|
||||
|
||||
#if REDCONF_API_POSIX == 1
|
||||
/* Create the root directory.
|
||||
*/
|
||||
if(ret == 0)
|
||||
{
|
||||
CINODE rootdir;
|
||||
|
||||
rootdir.ulInode = INODE_ROOTDIR;
|
||||
ret = RedInodeCreate(&rootdir, INODE_INVALID, RED_S_IFDIR);
|
||||
|
||||
if(ret == 0)
|
||||
{
|
||||
RedInodePut(&rootdir, 0U);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if REDCONF_API_FSE == 1
|
||||
/* The FSE API does not support creating or deletes files, so all the
|
||||
inodes are created during setup.
|
||||
*/
|
||||
if(ret == 0)
|
||||
{
|
||||
uint32_t ulInodeIdx;
|
||||
|
||||
for(ulInodeIdx = 0U; ulInodeIdx < gpRedVolConf->ulInodeCount; ulInodeIdx++)
|
||||
{
|
||||
CINODE ino;
|
||||
|
||||
ino.ulInode = INODE_FIRST_FREE + ulInodeIdx;
|
||||
ret = RedInodeCreate(&ino, INODE_INVALID, RED_S_IFREG);
|
||||
|
||||
if(ret == 0)
|
||||
{
|
||||
RedInodePut(&ino, 0U);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Write the second metaroot.
|
||||
*/
|
||||
if(ret == 0)
|
||||
{
|
||||
ret = RedVolTransact();
|
||||
}
|
||||
|
||||
/* Populate and write out the master block.
|
||||
*/
|
||||
if(ret == 0)
|
||||
{
|
||||
ret = RedBufferGet(BLOCK_NUM_MASTER, (uint16_t)((uint32_t)BFLAG_META_MASTER | BFLAG_NEW | BFLAG_DIRTY), CAST_VOID_PTR_PTR(&pMB));
|
||||
}
|
||||
|
||||
if(ret == 0)
|
||||
{
|
||||
pMB->ulVersion = RED_DISK_LAYOUT_VERSION;
|
||||
RedStrNCpy(pMB->acBuildNum, RED_BUILD_NUMBER, sizeof(pMB->acBuildNum));
|
||||
pMB->ulFormatTime = RedOsClockGetTime();
|
||||
pMB->ulInodeCount = gpRedVolConf->ulInodeCount;
|
||||
pMB->ulBlockCount = gpRedVolume->ulBlockCount;
|
||||
pMB->uMaxNameLen = REDCONF_NAME_MAX;
|
||||
pMB->uDirectPointers = REDCONF_DIRECT_POINTERS;
|
||||
pMB->uIndirectPointers = REDCONF_INDIRECT_POINTERS;
|
||||
pMB->bBlockSizeP2 = BLOCK_SIZE_P2;
|
||||
|
||||
#if REDCONF_API_POSIX == 1
|
||||
pMB->bFlags |= MBFLAG_API_POSIX;
|
||||
#endif
|
||||
#if REDCONF_INODE_TIMESTAMPS == 1
|
||||
pMB->bFlags |= MBFLAG_INODE_TIMESTAMPS;
|
||||
#endif
|
||||
#if REDCONF_INODE_BLOCKS == 1
|
||||
pMB->bFlags |= MBFLAG_INODE_BLOCKS;
|
||||
#endif
|
||||
#if (REDCONF_API_POSIX == 1) && (REDCONF_API_POSIX_LINK == 1)
|
||||
pMB->bFlags |= MBFLAG_INODE_NLINK;
|
||||
#endif
|
||||
|
||||
ret = RedBufferFlush(BLOCK_NUM_MASTER, 1U);
|
||||
|
||||
RedBufferPut(pMB);
|
||||
}
|
||||
|
||||
if(ret == 0)
|
||||
{
|
||||
ret = RedIoFlush(gbRedVolNum);
|
||||
}
|
||||
|
||||
ret2 = RedOsBDevClose(gbRedVolNum);
|
||||
if(ret == 0)
|
||||
{
|
||||
ret = ret2;
|
||||
}
|
||||
}
|
||||
|
||||
/* Discard the buffers so a subsequent format will not run into blocks it
|
||||
does not expect.
|
||||
*/
|
||||
if(ret == 0)
|
||||
{
|
||||
ret = RedBufferDiscardRange(0U, gpRedVolume->ulBlockCount);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
#endif /* FORMAT_SUPPORTED */
|
||||
|
@@ -0,0 +1,349 @@
|
||||
/* ----> DO NOT REMOVE THE FOLLOWING NOTICE <----
|
||||
|
||||
Copyright (c) 2014-2015 Datalight, Inc.
|
||||
All Rights Reserved Worldwide.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; use version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but "AS-IS," WITHOUT ANY WARRANTY; without even the implied warranty
|
||||
of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
/* Businesses and individuals that for commercial or other reasons cannot
|
||||
comply with the terms of the GPLv2 license may obtain a commercial license
|
||||
before incorporating Reliance Edge into proprietary software for
|
||||
distribution in any form. Visit http://www.datalight.com/reliance-edge for
|
||||
more information.
|
||||
*/
|
||||
/** @file
|
||||
@brief Implements allocation routines.
|
||||
|
||||
This module implements routines for working with the imap, a bitmap which
|
||||
tracks which blocks are allocated or free. Some of the functionality is
|
||||
delegated to imapinline.c and imapextern.c.
|
||||
*/
|
||||
#include <redfs.h>
|
||||
#include <redcore.h>
|
||||
|
||||
|
||||
/** @brief Get the allocation bit of a block from either metaroot.
|
||||
|
||||
Will pass the call down either to the inline imap or to the external imap
|
||||
implementation, whichever is appropriate for the current volume.
|
||||
|
||||
@param bMR The metaroot index: either 0 or 1.
|
||||
@param ulBlock The block number to query.
|
||||
@param pfAllocated On successful return, populated with the allocation bit
|
||||
of the block.
|
||||
|
||||
@return A negated ::REDSTATUS code indicating the operation result.
|
||||
|
||||
@retval 0 Operation was successful.
|
||||
@retval -RED_EINVAL @p bMR is out of range; or @p ulBlock is out of range;
|
||||
or @p pfAllocated is `NULL`.
|
||||
@retval -RED_EIO A disk I/O error occurred.
|
||||
*/
|
||||
REDSTATUS RedImapBlockGet(
|
||||
uint8_t bMR,
|
||||
uint32_t ulBlock,
|
||||
bool *pfAllocated)
|
||||
{
|
||||
REDSTATUS ret;
|
||||
|
||||
if( (bMR > 1U)
|
||||
|| (ulBlock < gpRedCoreVol->ulInodeTableStartBN)
|
||||
|| (ulBlock >= gpRedVolume->ulBlockCount)
|
||||
|| (pfAllocated == NULL))
|
||||
{
|
||||
REDERROR();
|
||||
ret = -RED_EINVAL;
|
||||
}
|
||||
else
|
||||
{
|
||||
#if (REDCONF_IMAP_INLINE == 1) && (REDCONF_IMAP_EXTERNAL == 1)
|
||||
if(gpRedCoreVol->fImapInline)
|
||||
{
|
||||
ret = RedImapIBlockGet(bMR, ulBlock, pfAllocated);
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = RedImapEBlockGet(bMR, ulBlock, pfAllocated);
|
||||
}
|
||||
#elif REDCONF_IMAP_INLINE == 1
|
||||
ret = RedImapIBlockGet(bMR, ulBlock, pfAllocated);
|
||||
#else
|
||||
ret = RedImapEBlockGet(bMR, ulBlock, pfAllocated);
|
||||
#endif
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
#if REDCONF_READ_ONLY == 0
|
||||
/** @brief Set the allocation bit of a block in the working metaroot.
|
||||
|
||||
Will pass the call down either to the inline imap or to the external imap
|
||||
implementation, whichever is appropriate for the current volume.
|
||||
|
||||
@param ulBlock The block number to allocate or free.
|
||||
@param fAllocated Whether to allocate the block (true) or free it (false).
|
||||
|
||||
@return A negated ::REDSTATUS code indicating the operation result.
|
||||
|
||||
@retval 0 Operation was successful.
|
||||
@retval -RED_EINVAL @p ulBlock is out of range; or @p ulBlock is allocable
|
||||
and @p fAllocated is 1.
|
||||
@retval -RED_EIO A disk I/O error occurred.
|
||||
*/
|
||||
REDSTATUS RedImapBlockSet(
|
||||
uint32_t ulBlock,
|
||||
bool fAllocated)
|
||||
{
|
||||
REDSTATUS ret;
|
||||
|
||||
if( (ulBlock < gpRedCoreVol->ulInodeTableStartBN)
|
||||
|| (ulBlock >= gpRedVolume->ulBlockCount))
|
||||
{
|
||||
REDERROR();
|
||||
ret = -RED_EINVAL;
|
||||
}
|
||||
else if( (ulBlock >= gpRedCoreVol->ulFirstAllocableBN)
|
||||
&& ( (fAllocated && (gpRedMR->ulFreeBlocks == 0U))
|
||||
|| ((!fAllocated) && (gpRedMR->ulFreeBlocks >= gpRedVolume->ulBlocksAllocable))))
|
||||
{
|
||||
/* Attempting either to free more blocks than are allocable, or
|
||||
allocate a block when there are none available. This could indicate
|
||||
metadata corruption.
|
||||
*/
|
||||
CRITICAL_ERROR();
|
||||
ret = -RED_EFUBAR;
|
||||
}
|
||||
else
|
||||
{
|
||||
#if (REDCONF_IMAP_INLINE == 1) && (REDCONF_IMAP_EXTERNAL == 1)
|
||||
if(gpRedCoreVol->fImapInline)
|
||||
{
|
||||
ret = RedImapIBlockSet(ulBlock, fAllocated);
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = RedImapEBlockSet(ulBlock, fAllocated);
|
||||
}
|
||||
#elif REDCONF_IMAP_INLINE == 1
|
||||
ret = RedImapIBlockSet(ulBlock, fAllocated);
|
||||
#else
|
||||
ret = RedImapEBlockSet(ulBlock, fAllocated);
|
||||
#endif
|
||||
|
||||
/* Any change to the allocation state of a block indicates that the
|
||||
volume is now branched.
|
||||
*/
|
||||
gpRedCoreVol->fBranched = true;
|
||||
}
|
||||
|
||||
/* If a block was marked as no longer in use, discard it from the buffers.
|
||||
*/
|
||||
if((ret == 0) && (!fAllocated))
|
||||
{
|
||||
ret = RedBufferDiscardRange(ulBlock, 1U);
|
||||
CRITICAL_ASSERT(ret == 0);
|
||||
}
|
||||
|
||||
/* Adjust the free/almost free block count if the block was allocable.
|
||||
Discard the block if required.
|
||||
*/
|
||||
if((ret == 0) && (ulBlock >= gpRedCoreVol->ulFirstAllocableBN))
|
||||
{
|
||||
if(fAllocated)
|
||||
{
|
||||
gpRedMR->ulFreeBlocks--;
|
||||
}
|
||||
else
|
||||
{
|
||||
bool fWasAllocated;
|
||||
|
||||
/* Whether the block became free or almost free depends on its
|
||||
previous allocation state. If it was used, then it is now
|
||||
almost free. Otherwise, it was new and is now free.
|
||||
*/
|
||||
ret = RedImapBlockGet(1U - gpRedCoreVol->bCurMR, ulBlock, &fWasAllocated);
|
||||
CRITICAL_ASSERT(ret == 0);
|
||||
|
||||
if(ret == 0)
|
||||
{
|
||||
if(fWasAllocated)
|
||||
{
|
||||
gpRedCoreVol->ulAlmostFreeBlocks++;
|
||||
}
|
||||
else
|
||||
{
|
||||
gpRedMR->ulFreeBlocks++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/** @brief Allocate one block.
|
||||
|
||||
@param pulBlock On successful return, populated with the allocated block
|
||||
number.
|
||||
|
||||
@return A negated ::REDSTATUS code indicating the operation result.
|
||||
|
||||
@retval 0 Operation was successful.
|
||||
@retval -RED_EINVAL @p pulBlock is `NULL`.
|
||||
@retval -RED_EIO A disk I/O error occurred.
|
||||
@retval -RED_ENOSPC Insufficient free space to perform the allocation.
|
||||
*/
|
||||
REDSTATUS RedImapAllocBlock(
|
||||
uint32_t *pulBlock)
|
||||
{
|
||||
REDSTATUS ret;
|
||||
|
||||
if(pulBlock == NULL)
|
||||
{
|
||||
REDERROR();
|
||||
ret = -RED_EINVAL;
|
||||
}
|
||||
else if(gpRedMR->ulFreeBlocks == 0U)
|
||||
{
|
||||
ret = -RED_ENOSPC;
|
||||
}
|
||||
else
|
||||
{
|
||||
uint32_t ulStopBlock = gpRedMR->ulAllocNextBlock;
|
||||
bool fAllocated = false;
|
||||
|
||||
do
|
||||
{
|
||||
ALLOCSTATE state;
|
||||
|
||||
ret = RedImapBlockState(gpRedMR->ulAllocNextBlock, &state);
|
||||
CRITICAL_ASSERT(ret == 0);
|
||||
|
||||
if(ret == 0)
|
||||
{
|
||||
if(state == ALLOCSTATE_FREE)
|
||||
{
|
||||
ret = RedImapBlockSet(gpRedMR->ulAllocNextBlock, true);
|
||||
CRITICAL_ASSERT(ret == 0);
|
||||
|
||||
*pulBlock = gpRedMR->ulAllocNextBlock;
|
||||
fAllocated = true;
|
||||
}
|
||||
|
||||
/* Increment the next block number, wrapping it when the end of
|
||||
the volume is reached.
|
||||
*/
|
||||
gpRedMR->ulAllocNextBlock++;
|
||||
if(gpRedMR->ulAllocNextBlock == gpRedVolume->ulBlockCount)
|
||||
{
|
||||
gpRedMR->ulAllocNextBlock = gpRedCoreVol->ulFirstAllocableBN;
|
||||
}
|
||||
}
|
||||
}
|
||||
while((ret == 0) && !fAllocated && (gpRedMR->ulAllocNextBlock != ulStopBlock));
|
||||
|
||||
if((ret == 0) && !fAllocated)
|
||||
{
|
||||
/* The free block count was already determined to be non-zero, no
|
||||
error occurred while looking for free blocks, but no free blocks
|
||||
were found. This indicates metadata corruption.
|
||||
*/
|
||||
CRITICAL_ERROR();
|
||||
ret = -RED_EFUBAR;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
#endif /* REDCONF_READ_ONLY == 0 */
|
||||
|
||||
|
||||
/** @brief Get the allocation state of a block.
|
||||
|
||||
Takes into account the allocation bits from both metaroots, and returns one
|
||||
of four possible allocation state values:
|
||||
|
||||
- ::ALLOCSTATE_FREE Free and may be allocated; writeable.
|
||||
- ::ALLOCSTATE_USED In-use and transacted; not writeable.
|
||||
- ::ALLOCSTATE_NEW In-use but not transacted; writeable.
|
||||
- ::ALLOCSTATE_AFREE Will become free after a transaction; not writeable.
|
||||
|
||||
@param ulBlock The block number to query.
|
||||
@param pState On successful return, populated with the state of the block.
|
||||
|
||||
@return A negated ::REDSTATUS code indicating the operation result.
|
||||
|
||||
@retval 0 Operation was successful.
|
||||
@retval -RED_EINVAL @p ulBlock is out of range; or @p pState is `NULL`.
|
||||
@retval -RED_EIO A disk I/O error occurred.
|
||||
*/
|
||||
REDSTATUS RedImapBlockState(
|
||||
uint32_t ulBlock,
|
||||
ALLOCSTATE *pState)
|
||||
{
|
||||
REDSTATUS ret;
|
||||
|
||||
if( (ulBlock < gpRedCoreVol->ulInodeTableStartBN)
|
||||
|| (ulBlock >= gpRedVolume->ulBlockCount)
|
||||
|| (pState == NULL))
|
||||
{
|
||||
REDERROR();
|
||||
ret = -RED_EINVAL;
|
||||
}
|
||||
else
|
||||
{
|
||||
bool fBitCurrent;
|
||||
|
||||
ret = RedImapBlockGet(gpRedCoreVol->bCurMR, ulBlock, &fBitCurrent);
|
||||
|
||||
if(ret == 0)
|
||||
{
|
||||
bool fBitOld;
|
||||
|
||||
ret = RedImapBlockGet(1U - gpRedCoreVol->bCurMR, ulBlock, &fBitOld);
|
||||
|
||||
if(ret == 0)
|
||||
{
|
||||
if(fBitCurrent)
|
||||
{
|
||||
if(fBitOld)
|
||||
{
|
||||
*pState = ALLOCSTATE_USED;
|
||||
}
|
||||
else
|
||||
{
|
||||
*pState = ALLOCSTATE_NEW;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(fBitOld)
|
||||
{
|
||||
*pState = ALLOCSTATE_AFREE;
|
||||
}
|
||||
else
|
||||
{
|
||||
*pState = ALLOCSTATE_FREE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@@ -0,0 +1,316 @@
|
||||
/* ----> DO NOT REMOVE THE FOLLOWING NOTICE <----
|
||||
|
||||
Copyright (c) 2014-2015 Datalight, Inc.
|
||||
All Rights Reserved Worldwide.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; use version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but "AS-IS," WITHOUT ANY WARRANTY; without even the implied warranty
|
||||
of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
/* Businesses and individuals that for commercial or other reasons cannot
|
||||
comply with the terms of the GPLv2 license may obtain a commercial license
|
||||
before incorporating Reliance Edge into proprietary software for
|
||||
distribution in any form. Visit http://www.datalight.com/reliance-edge for
|
||||
more information.
|
||||
*/
|
||||
/** @file
|
||||
@brief Implements routines for the external imap.
|
||||
|
||||
The external imap is used on volumes that are too big for the imap bitmap
|
||||
to be stored entirely in the metaroot, so instead the bitmap is stored in
|
||||
imap nodes on disk, and the metaroot bitmap is used to toggle between imap
|
||||
nodes.
|
||||
*/
|
||||
#include <redfs.h>
|
||||
|
||||
#if REDCONF_IMAP_EXTERNAL == 1
|
||||
|
||||
#include <redcore.h>
|
||||
|
||||
|
||||
#if REDCONF_READ_ONLY == 0
|
||||
static REDSTATUS ImapNodeBranch(uint32_t ulImapNode, IMAPNODE **ppImap);
|
||||
static bool ImapNodeIsBranched(uint32_t ulImapNode);
|
||||
#endif
|
||||
|
||||
|
||||
/** @brief Get the allocation bit of a block from the imap as it exists in
|
||||
either metaroot.
|
||||
|
||||
@param bMR The metaroot index: either 0 or 1.
|
||||
@param ulBlock The block number to query.
|
||||
@param pfAllocated On successful exit, populated with the allocation bit
|
||||
of the block.
|
||||
|
||||
@return A negated ::REDSTATUS code indicating the operation result.
|
||||
|
||||
@retval 0 Operation was successful.
|
||||
@retval -RED_EINVAL @p bMR is out of range; or @p ulBlock is out of range;
|
||||
or @p pfAllocated is `NULL`.
|
||||
@retval -RED_EIO A disk I/O error occurred.
|
||||
*/
|
||||
REDSTATUS RedImapEBlockGet(
|
||||
uint8_t bMR,
|
||||
uint32_t ulBlock,
|
||||
bool *pfAllocated)
|
||||
{
|
||||
REDSTATUS ret;
|
||||
|
||||
if( gpRedCoreVol->fImapInline
|
||||
|| (bMR > 1U)
|
||||
|| (ulBlock < gpRedCoreVol->ulInodeTableStartBN)
|
||||
|| (ulBlock >= gpRedVolume->ulBlockCount)
|
||||
|| (pfAllocated == NULL))
|
||||
{
|
||||
REDERROR();
|
||||
ret = -RED_EINVAL;
|
||||
}
|
||||
else
|
||||
{
|
||||
uint32_t ulOffset = ulBlock - gpRedCoreVol->ulInodeTableStartBN;
|
||||
uint32_t ulImapNode = ulOffset / IMAPNODE_ENTRIES;
|
||||
uint8_t bMRToRead = bMR;
|
||||
IMAPNODE *pImap;
|
||||
|
||||
#if REDCONF_READ_ONLY == 0
|
||||
/* If the imap node is not branched, then both copies of the imap are
|
||||
identical. If the old metaroot copy is requested, use the current
|
||||
copy instead, since it is more likely to be buffered.
|
||||
*/
|
||||
if(bMR == (1U - gpRedCoreVol->bCurMR))
|
||||
{
|
||||
if(!ImapNodeIsBranched(ulImapNode))
|
||||
{
|
||||
bMRToRead = 1U - bMR;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
ret = RedBufferGet(RedImapNodeBlock(bMRToRead, ulImapNode), BFLAG_META_IMAP, CAST_VOID_PTR_PTR(&pImap));
|
||||
|
||||
if(ret == 0)
|
||||
{
|
||||
*pfAllocated = RedBitGet(pImap->abEntries, ulOffset % IMAPNODE_ENTRIES);
|
||||
|
||||
RedBufferPut(pImap);
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
#if REDCONF_READ_ONLY == 0
|
||||
/** @brief Set the allocation bit of a block in the working-state imap.
|
||||
|
||||
@param ulBlock The block number to allocate or free.
|
||||
@param fAllocated Whether to allocate the block (true) or free it (false).
|
||||
|
||||
@return A negated ::REDSTATUS code indicating the operation result.
|
||||
|
||||
@retval 0 Operation was successful.
|
||||
@retval -RED_EINVAL @p ulBlock is out of range.
|
||||
@retval -RED_EIO A disk I/O error occurred.
|
||||
*/
|
||||
REDSTATUS RedImapEBlockSet(
|
||||
uint32_t ulBlock,
|
||||
bool fAllocated)
|
||||
{
|
||||
REDSTATUS ret;
|
||||
|
||||
if( gpRedCoreVol->fImapInline
|
||||
|| (ulBlock < gpRedCoreVol->ulInodeTableStartBN)
|
||||
|| (ulBlock >= gpRedVolume->ulBlockCount))
|
||||
{
|
||||
REDERROR();
|
||||
ret = -RED_EINVAL;
|
||||
}
|
||||
else
|
||||
{
|
||||
uint32_t ulOffset = ulBlock - gpRedCoreVol->ulInodeTableStartBN;
|
||||
uint32_t ulImapNode = ulOffset / IMAPNODE_ENTRIES;
|
||||
IMAPNODE *pImap;
|
||||
|
||||
ret = ImapNodeBranch(ulImapNode, &pImap);
|
||||
|
||||
if(ret == 0)
|
||||
{
|
||||
uint32_t ulImapEntry = ulOffset % IMAPNODE_ENTRIES;
|
||||
|
||||
if(RedBitGet(pImap->abEntries, ulImapEntry) == fAllocated)
|
||||
{
|
||||
/* The driver shouldn't ever set a bit in the imap to its
|
||||
current value. That shouldn't ever be needed, and it
|
||||
indicates that the driver is doing unnecessary I/O, or
|
||||
that the imap is corrupt.
|
||||
*/
|
||||
CRITICAL_ERROR();
|
||||
ret = -RED_EFUBAR;
|
||||
}
|
||||
else if(fAllocated)
|
||||
{
|
||||
RedBitSet(pImap->abEntries, ulImapEntry);
|
||||
}
|
||||
else
|
||||
{
|
||||
RedBitClear(pImap->abEntries, ulImapEntry);
|
||||
}
|
||||
|
||||
RedBufferPut(pImap);
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/** @brief Branch an imap node and get a buffer for it.
|
||||
|
||||
If the imap node is already branched, it can be overwritten in its current
|
||||
location, and this function just gets it buffered dirty. If the node is not
|
||||
already branched, the metaroot must be updated to toggle the imap node to
|
||||
its alternate location, thereby preserving the committed state copy of the
|
||||
imap node.
|
||||
|
||||
@param ulImapNode The imap node to branch and buffer.
|
||||
@param ppImap On successful return, populated with the imap node
|
||||
buffer, which will be marked dirty.
|
||||
|
||||
@return A negated ::REDSTATUS code indicating the operation result.
|
||||
|
||||
@retval 0 Operation was successful.
|
||||
@retval -RED_EINVAL @p ulImapNode is out of range; or @p ppImap is `NULL`.
|
||||
@retval -RED_EIO A disk I/O error occurred.
|
||||
*/
|
||||
static REDSTATUS ImapNodeBranch(
|
||||
uint32_t ulImapNode,
|
||||
IMAPNODE **ppImap)
|
||||
{
|
||||
REDSTATUS ret;
|
||||
|
||||
if((ulImapNode >= gpRedCoreVol->ulImapNodeCount) || (ppImap == NULL))
|
||||
{
|
||||
REDERROR();
|
||||
ret = -RED_EINVAL;
|
||||
}
|
||||
else if(ImapNodeIsBranched(ulImapNode))
|
||||
{
|
||||
/* Imap node is already branched, so just get it buffered dirty.
|
||||
*/
|
||||
ret = RedBufferGet(RedImapNodeBlock(gpRedCoreVol->bCurMR, ulImapNode), BFLAG_META_IMAP | BFLAG_DIRTY, CAST_VOID_PTR_PTR(ppImap));
|
||||
}
|
||||
else
|
||||
{
|
||||
uint32_t ulBlockCurrent;
|
||||
uint32_t ulBlockOld;
|
||||
|
||||
/* The metaroot currently points to the committed state imap node.
|
||||
Toggle the metaroot to point at the alternate, writeable location.
|
||||
*/
|
||||
if(RedBitGet(gpRedMR->abEntries, ulImapNode))
|
||||
{
|
||||
RedBitClear(gpRedMR->abEntries, ulImapNode);
|
||||
}
|
||||
else
|
||||
{
|
||||
RedBitSet(gpRedMR->abEntries, ulImapNode);
|
||||
}
|
||||
|
||||
ulBlockCurrent = RedImapNodeBlock(gpRedCoreVol->bCurMR, ulImapNode);
|
||||
ulBlockOld = RedImapNodeBlock(1U - gpRedCoreVol->bCurMR, ulImapNode);
|
||||
|
||||
ret = RedBufferDiscardRange(ulBlockCurrent, 1U);
|
||||
|
||||
/* Buffer the committed copy then reassign the block number to the
|
||||
writeable location. This also dirties the buffer.
|
||||
*/
|
||||
if(ret == 0)
|
||||
{
|
||||
ret = RedBufferGet(ulBlockOld, BFLAG_META_IMAP, CAST_VOID_PTR_PTR(ppImap));
|
||||
|
||||
if(ret == 0)
|
||||
{
|
||||
RedBufferBranch(*ppImap, ulBlockCurrent);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/** @brief Determine whether an imap node is branched.
|
||||
|
||||
If the imap node is branched, it can be overwritten in its current location.
|
||||
|
||||
@param ulImapNode The imap node to examine.
|
||||
|
||||
@return Whether the imap node is branched.
|
||||
*/
|
||||
static bool ImapNodeIsBranched(
|
||||
uint32_t ulImapNode)
|
||||
{
|
||||
bool fNodeBitSetInMetaroot0 = RedBitGet(gpRedCoreVol->aMR[0U].abEntries, ulImapNode);
|
||||
bool fNodeBitSetInMetaroot1 = RedBitGet(gpRedCoreVol->aMR[1U].abEntries, ulImapNode);
|
||||
|
||||
/* If the imap node is not branched, both metaroots will point to the same
|
||||
copy of the node.
|
||||
*/
|
||||
return fNodeBitSetInMetaroot0 != fNodeBitSetInMetaroot1;
|
||||
}
|
||||
#endif /* REDCONF_READ_ONLY == 0 */
|
||||
|
||||
|
||||
/** @brief Calculate the block number of the imap node location indicated by the
|
||||
given metaroot.
|
||||
|
||||
An imap node has two locations on disk. A bit in the metaroot bitmap
|
||||
indicates which location is the valid one, according to that metaroot. This
|
||||
function returns the block number of the imap node which is valid in the
|
||||
given metaroot.
|
||||
|
||||
@param bMR Which metaroot to examine.
|
||||
@param ulImapNode The imap node for which to calculate the block number.
|
||||
|
||||
@return Block number of the imap node, as indicated by the given metaroot.
|
||||
*/
|
||||
uint32_t RedImapNodeBlock(
|
||||
uint8_t bMR,
|
||||
uint32_t ulImapNode)
|
||||
{
|
||||
uint32_t ulBlock;
|
||||
|
||||
REDASSERT(ulImapNode < gpRedCoreVol->ulImapNodeCount);
|
||||
|
||||
ulBlock = gpRedCoreVol->ulImapStartBN + (ulImapNode * 2U);
|
||||
|
||||
if(bMR > 1U)
|
||||
{
|
||||
REDERROR();
|
||||
}
|
||||
else if(RedBitGet(gpRedCoreVol->aMR[bMR].abEntries, ulImapNode))
|
||||
{
|
||||
/* Bit is set, so point ulBlock at the second copy of the node.
|
||||
*/
|
||||
ulBlock++;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* ulBlock already points at the first copy of the node.
|
||||
*/
|
||||
}
|
||||
|
||||
return ulBlock;
|
||||
}
|
||||
|
||||
#endif /* REDCONF_IMAP_EXTERNAL == 1 */
|
||||
|
@@ -0,0 +1,133 @@
|
||||
/* ----> DO NOT REMOVE THE FOLLOWING NOTICE <----
|
||||
|
||||
Copyright (c) 2014-2015 Datalight, Inc.
|
||||
All Rights Reserved Worldwide.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; use version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but "AS-IS," WITHOUT ANY WARRANTY; without even the implied warranty
|
||||
of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
/* Businesses and individuals that for commercial or other reasons cannot
|
||||
comply with the terms of the GPLv2 license may obtain a commercial license
|
||||
before incorporating Reliance Edge into proprietary software for
|
||||
distribution in any form. Visit http://www.datalight.com/reliance-edge for
|
||||
more information.
|
||||
*/
|
||||
/** @file
|
||||
@brief Implements routines for the inline imap.
|
||||
|
||||
The inline imap is used on volumes that are small enough for the imap bitmap
|
||||
to be entirely contained within the metaroot.
|
||||
*/
|
||||
#include <redfs.h>
|
||||
|
||||
#if REDCONF_IMAP_INLINE == 1
|
||||
|
||||
#include <redcore.h>
|
||||
|
||||
|
||||
/** @brief Get the allocation bit of a block from either metaroot.
|
||||
|
||||
@param bMR The metaroot index: either 0 or 1.
|
||||
@param ulBlock The block number to query.
|
||||
@param pfAllocated On successful return, populated with the allocation bit
|
||||
of the block.
|
||||
|
||||
@return A negated ::REDSTATUS code indicating the operation result.
|
||||
|
||||
@retval 0 Operation was successful.
|
||||
@retval -RED_EINVAL @p bMR is out of range; or @p ulBlock is out of range;
|
||||
@p pfAllocated is `NULL`; or the current volume does not
|
||||
use the inline imap.
|
||||
*/
|
||||
REDSTATUS RedImapIBlockGet(
|
||||
uint8_t bMR,
|
||||
uint32_t ulBlock,
|
||||
bool *pfAllocated)
|
||||
{
|
||||
REDSTATUS ret;
|
||||
|
||||
if( (!gpRedCoreVol->fImapInline)
|
||||
|| (bMR > 1U)
|
||||
|| (ulBlock < gpRedCoreVol->ulInodeTableStartBN)
|
||||
|| (ulBlock >= gpRedVolume->ulBlockCount)
|
||||
|| (pfAllocated == NULL))
|
||||
{
|
||||
REDERROR();
|
||||
ret = -RED_EINVAL;
|
||||
}
|
||||
else
|
||||
{
|
||||
*pfAllocated = RedBitGet(gpRedCoreVol->aMR[bMR].abEntries, ulBlock - gpRedCoreVol->ulInodeTableStartBN);
|
||||
ret = 0;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
#if REDCONF_READ_ONLY == 0
|
||||
/** @brief Set the allocation bit of a block in the working metaroot.
|
||||
|
||||
@param ulBlock The block number to allocate or free.
|
||||
@param fAllocated Whether to allocate the block (true) or free it (false).
|
||||
|
||||
@return A negated ::REDSTATUS code indicating the operation result.
|
||||
|
||||
@retval 0 Operation was successful.
|
||||
@retval -RED_EINVAL @p ulBlock is out of range; or the current volume does
|
||||
not use the inline imap.
|
||||
*/
|
||||
REDSTATUS RedImapIBlockSet(
|
||||
uint32_t ulBlock,
|
||||
bool fAllocated)
|
||||
{
|
||||
REDSTATUS ret;
|
||||
|
||||
if( (!gpRedCoreVol->fImapInline)
|
||||
|| (ulBlock < gpRedCoreVol->ulInodeTableStartBN)
|
||||
|| (ulBlock >= gpRedVolume->ulBlockCount))
|
||||
{
|
||||
REDERROR();
|
||||
ret = -RED_EINVAL;
|
||||
}
|
||||
else
|
||||
{
|
||||
uint32_t ulOffset = ulBlock - gpRedCoreVol->ulInodeTableStartBN;
|
||||
|
||||
if(RedBitGet(gpRedMR->abEntries, ulOffset) == fAllocated)
|
||||
{
|
||||
/* The driver shouldn't ever set a bit in the imap to its current
|
||||
value. This is more of a problem with the external imap, but it
|
||||
is checked here for consistency.
|
||||
*/
|
||||
CRITICAL_ERROR();
|
||||
ret = -RED_EFUBAR;
|
||||
}
|
||||
else if(fAllocated)
|
||||
{
|
||||
RedBitSet(gpRedMR->abEntries, ulOffset);
|
||||
ret = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
RedBitClear(gpRedMR->abEntries, ulOffset);
|
||||
ret = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* REDCONF_IMAP_INLINE == 1 */
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,540 @@
|
||||
/* ----> DO NOT REMOVE THE FOLLOWING NOTICE <----
|
||||
|
||||
Copyright (c) 2014-2015 Datalight, Inc.
|
||||
All Rights Reserved Worldwide.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; use version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but "AS-IS," WITHOUT ANY WARRANTY; without even the implied warranty
|
||||
of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
/* Businesses and individuals that for commercial or other reasons cannot
|
||||
comply with the terms of the GPLv2 license may obtain a commercial license
|
||||
before incorporating Reliance Edge into proprietary software for
|
||||
distribution in any form. Visit http://www.datalight.com/reliance-edge for
|
||||
more information.
|
||||
*/
|
||||
/** @file
|
||||
@brief Implements core volume operations.
|
||||
*/
|
||||
#include <redfs.h>
|
||||
#include <redcore.h>
|
||||
|
||||
|
||||
static bool MetarootIsValid(METAROOT *pMR, bool *pfSectorCRCIsValid);
|
||||
#ifdef REDCONF_ENDIAN_SWAP
|
||||
static void MetaRootEndianSwap(METAROOT *pMetaRoot);
|
||||
#endif
|
||||
|
||||
|
||||
/** @brief Mount a file system volume.
|
||||
|
||||
@return A negated ::REDSTATUS code indicating the operation result.
|
||||
|
||||
@retval 0 Operation was successful.
|
||||
@retval -RED_EIO Volume not formatted, improperly formatted, or corrupt.
|
||||
*/
|
||||
REDSTATUS RedVolMount(void)
|
||||
{
|
||||
REDSTATUS ret;
|
||||
|
||||
#if REDCONF_READ_ONLY == 0
|
||||
ret = RedOsBDevOpen(gbRedVolNum, BDEV_O_RDWR);
|
||||
#else
|
||||
ret = RedOsBDevOpen(gbRedVolNum, BDEV_O_RDONLY);
|
||||
#endif
|
||||
|
||||
if(ret == 0)
|
||||
{
|
||||
ret = RedVolMountMaster();
|
||||
|
||||
if(ret == 0)
|
||||
{
|
||||
ret = RedVolMountMetaroot();
|
||||
}
|
||||
|
||||
if(ret != 0)
|
||||
{
|
||||
/* If we fail to mount, invalidate the buffers to prevent any
|
||||
confusion that could be caused by stale or corrupt metadata.
|
||||
*/
|
||||
(void)RedBufferDiscardRange(0U, gpRedVolume->ulBlockCount);
|
||||
(void)RedOsBDevClose(gbRedVolNum);
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/** @brief Mount the master block.
|
||||
|
||||
@return A negated ::REDSTATUS code indicating the operation result.
|
||||
|
||||
@retval 0 Operation was successful.
|
||||
@retval -RED_EIO Master block missing, corrupt, or inconsistent with the
|
||||
compile-time driver settings.
|
||||
*/
|
||||
REDSTATUS RedVolMountMaster(void)
|
||||
{
|
||||
REDSTATUS ret;
|
||||
MASTERBLOCK *pMB;
|
||||
|
||||
/* Read the master block, to ensure that the disk was formatted with
|
||||
Reliance Edge.
|
||||
*/
|
||||
ret = RedBufferGet(BLOCK_NUM_MASTER, BFLAG_META_MASTER, CAST_VOID_PTR_PTR(&pMB));
|
||||
|
||||
if(ret == 0)
|
||||
{
|
||||
/* Verify that the driver was compiled with the same settings that
|
||||
the disk was formatted with. If not, the user has made a
|
||||
mistake: either the driver settings are wrong, or the disk needs
|
||||
to be reformatted.
|
||||
*/
|
||||
if( (pMB->ulVersion != RED_DISK_LAYOUT_VERSION)
|
||||
|| (pMB->ulInodeCount != gpRedVolConf->ulInodeCount)
|
||||
|| (pMB->ulBlockCount != gpRedVolume->ulBlockCount)
|
||||
|| (pMB->uMaxNameLen != REDCONF_NAME_MAX)
|
||||
|| (pMB->uDirectPointers != REDCONF_DIRECT_POINTERS)
|
||||
|| (pMB->uIndirectPointers != REDCONF_INDIRECT_POINTERS)
|
||||
|| (pMB->bBlockSizeP2 != BLOCK_SIZE_P2)
|
||||
|| (((pMB->bFlags & MBFLAG_API_POSIX) != 0U) != (REDCONF_API_POSIX == 1))
|
||||
|| (((pMB->bFlags & MBFLAG_INODE_TIMESTAMPS) != 0U) != (REDCONF_INODE_TIMESTAMPS == 1))
|
||||
|| (((pMB->bFlags & MBFLAG_INODE_BLOCKS) != 0U) != (REDCONF_INODE_BLOCKS == 1)))
|
||||
{
|
||||
ret = -RED_EIO;
|
||||
}
|
||||
#if REDCONF_API_POSIX == 1
|
||||
else if(((pMB->bFlags & MBFLAG_INODE_NLINK) != 0U) != (REDCONF_API_POSIX_LINK == 1))
|
||||
{
|
||||
ret = -RED_EIO;
|
||||
}
|
||||
#else
|
||||
else if((pMB->bFlags & MBFLAG_INODE_NLINK) != 0U)
|
||||
{
|
||||
ret = -RED_EIO;
|
||||
}
|
||||
#endif
|
||||
else
|
||||
{
|
||||
/* Master block configuration is valid.
|
||||
|
||||
Save the sequence number of the master block in the volume,
|
||||
since we need it later (see RedVolMountMetaroot()) and we do
|
||||
not want to re-buffer the master block.
|
||||
*/
|
||||
gpRedVolume->ullSequence = pMB->hdr.ullSequence;
|
||||
}
|
||||
|
||||
RedBufferPut(pMB);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/** @brief Mount the latest metaroot.
|
||||
|
||||
This function also populates the volume contexts.
|
||||
|
||||
@return A negated ::REDSTATUS code indicating the operation result.
|
||||
|
||||
@retval 0 Operation was successful.
|
||||
@retval -RED_EIO Both metaroots are missing or corrupt.
|
||||
*/
|
||||
REDSTATUS RedVolMountMetaroot(void)
|
||||
{
|
||||
REDSTATUS ret;
|
||||
|
||||
ret = RedIoRead(gbRedVolNum, BLOCK_NUM_FIRST_METAROOT, 1U, &gpRedCoreVol->aMR[0U]);
|
||||
|
||||
if(ret == 0)
|
||||
{
|
||||
ret = RedIoRead(gbRedVolNum, BLOCK_NUM_FIRST_METAROOT + 1U, 1U, &gpRedCoreVol->aMR[1U]);
|
||||
}
|
||||
|
||||
/* Determine which metaroot is the most recent copy that was written
|
||||
completely.
|
||||
*/
|
||||
if(ret == 0)
|
||||
{
|
||||
uint8_t bMR = UINT8_MAX;
|
||||
bool fSectorCRCIsValid;
|
||||
|
||||
if(MetarootIsValid(&gpRedCoreVol->aMR[0U], &fSectorCRCIsValid))
|
||||
{
|
||||
bMR = 0U;
|
||||
|
||||
#ifdef REDCONF_ENDIAN_SWAP
|
||||
MetaRootEndianSwap(&gpRedCoreVol->aMR[0U]);
|
||||
#endif
|
||||
}
|
||||
else if(gpRedVolConf->fAtomicSectorWrite && !fSectorCRCIsValid)
|
||||
{
|
||||
ret = -RED_EIO;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Metaroot is not valid, so it is ignored and there's nothing
|
||||
to do here.
|
||||
*/
|
||||
}
|
||||
|
||||
if(ret == 0)
|
||||
{
|
||||
if(MetarootIsValid(&gpRedCoreVol->aMR[1U], &fSectorCRCIsValid))
|
||||
{
|
||||
#ifdef REDCONF_ENDIAN_SWAP
|
||||
MetaRootEndianSwap(&gpRedCoreVol->aMR[1U]);
|
||||
#endif
|
||||
|
||||
if((bMR != 0U) || (gpRedCoreVol->aMR[1U].hdr.ullSequence > gpRedCoreVol->aMR[0U].hdr.ullSequence))
|
||||
{
|
||||
bMR = 1U;
|
||||
}
|
||||
}
|
||||
else if(gpRedVolConf->fAtomicSectorWrite && !fSectorCRCIsValid)
|
||||
{
|
||||
ret = -RED_EIO;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Metaroot is not valid, so it is ignored and there's nothing
|
||||
to do here.
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
if(ret == 0)
|
||||
{
|
||||
if(bMR == UINT8_MAX)
|
||||
{
|
||||
/* Neither metaroot was valid.
|
||||
*/
|
||||
ret = -RED_EIO;
|
||||
}
|
||||
else
|
||||
{
|
||||
gpRedCoreVol->bCurMR = bMR;
|
||||
gpRedMR = &gpRedCoreVol->aMR[bMR];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(ret == 0)
|
||||
{
|
||||
/* Normally the metaroot contains the highest sequence number, but the
|
||||
master block is the last block written during format, so on a
|
||||
freshly formatted volume the master block sequence number (stored in
|
||||
gpRedVolume->ullSequence) will be higher than that in the metaroot.
|
||||
*/
|
||||
if(gpRedMR->hdr.ullSequence > gpRedVolume->ullSequence)
|
||||
{
|
||||
gpRedVolume->ullSequence = gpRedMR->hdr.ullSequence;
|
||||
}
|
||||
|
||||
/* gpRedVolume->ullSequence stores the *next* sequence number; to avoid
|
||||
giving the next node written to disk the same sequence number as the
|
||||
metaroot, increment it here.
|
||||
*/
|
||||
ret = RedVolSeqNumIncrement();
|
||||
}
|
||||
|
||||
if(ret == 0)
|
||||
{
|
||||
gpRedVolume->fMounted = true;
|
||||
#if REDCONF_READ_ONLY == 0
|
||||
gpRedVolume->fReadOnly = false;
|
||||
#endif
|
||||
|
||||
#if RESERVED_BLOCKS > 0U
|
||||
gpRedCoreVol->fUseReservedBlocks = false;
|
||||
#endif
|
||||
gpRedCoreVol->ulAlmostFreeBlocks = 0U;
|
||||
|
||||
gpRedCoreVol->aMR[1U - gpRedCoreVol->bCurMR] = *gpRedMR;
|
||||
gpRedCoreVol->bCurMR = 1U - gpRedCoreVol->bCurMR;
|
||||
gpRedMR = &gpRedCoreVol->aMR[gpRedCoreVol->bCurMR];
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/** @brief Determine whether the metaroot is valid.
|
||||
|
||||
@param pMR The metaroot buffer.
|
||||
@param pfSectorCRCIsValid Populated with whether the first sector of the
|
||||
metaroot buffer is valid.
|
||||
|
||||
@return Whether the metaroot is valid.
|
||||
|
||||
@retval true The metaroot buffer is valid.
|
||||
@retval false The metaroot buffer is invalid.
|
||||
*/
|
||||
static bool MetarootIsValid(
|
||||
METAROOT *pMR,
|
||||
bool *pfSectorCRCIsValid)
|
||||
{
|
||||
bool fRet = false;
|
||||
|
||||
if(pfSectorCRCIsValid == NULL)
|
||||
{
|
||||
REDERROR();
|
||||
}
|
||||
else if(pMR == NULL)
|
||||
{
|
||||
REDERROR();
|
||||
*pfSectorCRCIsValid = false;
|
||||
}
|
||||
#ifdef REDCONF_ENDIAN_SWAP
|
||||
else if(RedRev32(pMR->hdr.ulSignature) != META_SIG_METAROOT)
|
||||
#else
|
||||
else if(pMR->hdr.ulSignature != META_SIG_METAROOT)
|
||||
#endif
|
||||
{
|
||||
*pfSectorCRCIsValid = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
const uint8_t *pbMR = CAST_VOID_PTR_TO_CONST_UINT8_PTR(pMR);
|
||||
uint32_t ulSectorCRC = pMR->ulSectorCRC;
|
||||
uint32_t ulCRC;
|
||||
|
||||
#ifdef REDCONF_ENDIAN_SWAP
|
||||
ulSectorCRC = RedRev32(ulSectorCRC);
|
||||
#endif
|
||||
|
||||
/* The sector CRC was zero when the CRC was computed during the
|
||||
transaction, so it must be zero here.
|
||||
*/
|
||||
pMR->ulSectorCRC = 0U;
|
||||
|
||||
ulCRC = RedCrc32Update(0U, &pbMR[8U], gpRedVolConf->ulSectorSize - 8U);
|
||||
|
||||
fRet = ulCRC == ulSectorCRC;
|
||||
*pfSectorCRCIsValid = fRet;
|
||||
|
||||
if(fRet)
|
||||
{
|
||||
if(gpRedVolConf->ulSectorSize < REDCONF_BLOCK_SIZE)
|
||||
{
|
||||
ulCRC = RedCrc32Update(ulCRC, &pbMR[gpRedVolConf->ulSectorSize], REDCONF_BLOCK_SIZE - gpRedVolConf->ulSectorSize);
|
||||
}
|
||||
|
||||
#ifdef REDCONF_ENDIAN_SWAP
|
||||
ulCRC = RedRev32(ulCRC);
|
||||
#endif
|
||||
|
||||
fRet = ulCRC == pMR->hdr.ulCRC;
|
||||
}
|
||||
}
|
||||
|
||||
return fRet;
|
||||
}
|
||||
|
||||
|
||||
#if REDCONF_READ_ONLY == 0
|
||||
/** @brief Commit a transaction point.
|
||||
|
||||
@return A negated ::REDSTATUS code indicating the operation result.
|
||||
|
||||
@retval 0 Operation was successful.
|
||||
@retval -RED_EIO A disk I/O error occurred.
|
||||
*/
|
||||
REDSTATUS RedVolTransact(void)
|
||||
{
|
||||
REDSTATUS ret = 0;
|
||||
|
||||
REDASSERT(!gpRedVolume->fReadOnly); /* Should be checked by caller. */
|
||||
|
||||
if(gpRedCoreVol->fBranched)
|
||||
{
|
||||
gpRedMR->ulFreeBlocks += gpRedCoreVol->ulAlmostFreeBlocks;
|
||||
gpRedCoreVol->ulAlmostFreeBlocks = 0U;
|
||||
|
||||
ret = RedBufferFlush(0U, gpRedVolume->ulBlockCount);
|
||||
|
||||
if(ret == 0)
|
||||
{
|
||||
gpRedMR->hdr.ulSignature = META_SIG_METAROOT;
|
||||
gpRedMR->hdr.ullSequence = gpRedVolume->ullSequence;
|
||||
|
||||
ret = RedVolSeqNumIncrement();
|
||||
}
|
||||
|
||||
if(ret == 0)
|
||||
{
|
||||
const uint8_t *pbMR = CAST_VOID_PTR_TO_CONST_UINT8_PTR(gpRedMR);
|
||||
uint32_t ulSectorCRC;
|
||||
|
||||
#ifdef REDCONF_ENDIAN_SWAP
|
||||
MetaRootEndianSwap(gpRedMR);
|
||||
#endif
|
||||
|
||||
gpRedMR->ulSectorCRC = 0U;
|
||||
|
||||
ulSectorCRC = RedCrc32Update(0U, &pbMR[8U], gpRedVolConf->ulSectorSize - 8U);
|
||||
|
||||
if(gpRedVolConf->ulSectorSize < REDCONF_BLOCK_SIZE)
|
||||
{
|
||||
gpRedMR->hdr.ulCRC = RedCrc32Update(ulSectorCRC, &pbMR[gpRedVolConf->ulSectorSize], REDCONF_BLOCK_SIZE - gpRedVolConf->ulSectorSize);
|
||||
}
|
||||
else
|
||||
{
|
||||
gpRedMR->hdr.ulCRC = ulSectorCRC;
|
||||
}
|
||||
|
||||
gpRedMR->ulSectorCRC = ulSectorCRC;
|
||||
|
||||
#ifdef REDCONF_ENDIAN_SWAP
|
||||
gpRedMR->hdr.ulCRC = RedRev32(gpRedMR->hdr.ulCRC);
|
||||
gpRedMR->ulSectorCRC = RedRev32(gpRedMR->ulSectorCRC);
|
||||
#endif
|
||||
|
||||
/* Flush the block device before writing the metaroot, so that all
|
||||
previously written blocks are guaranteed to be on the media before
|
||||
the metaroot is written. Otherwise, if the block device reorders
|
||||
the writes, the metaroot could reach the media before metadata it
|
||||
points at, creating a window for disk corruption if power is lost.
|
||||
*/
|
||||
ret = RedIoFlush(gbRedVolNum);
|
||||
}
|
||||
|
||||
if(ret == 0)
|
||||
{
|
||||
ret = RedIoWrite(gbRedVolNum, BLOCK_NUM_FIRST_METAROOT + gpRedCoreVol->bCurMR, 1U, gpRedMR);
|
||||
|
||||
#ifdef REDCONF_ENDIAN_SWAP
|
||||
MetaRootEndianSwap(gpRedMR);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Flush the block device to force the metaroot write to the media. This
|
||||
guarantees the transaction point is really complete before we return.
|
||||
*/
|
||||
if(ret == 0)
|
||||
{
|
||||
ret = RedIoFlush(gbRedVolNum);
|
||||
}
|
||||
|
||||
/* Toggle to the other metaroot buffer. The working state and committed
|
||||
state metaroot buffers exchange places.
|
||||
*/
|
||||
if(ret == 0)
|
||||
{
|
||||
uint8_t bNextMR = 1U - gpRedCoreVol->bCurMR;
|
||||
|
||||
gpRedCoreVol->aMR[bNextMR] = *gpRedMR;
|
||||
gpRedCoreVol->bCurMR = bNextMR;
|
||||
|
||||
gpRedMR = &gpRedCoreVol->aMR[gpRedCoreVol->bCurMR];
|
||||
|
||||
gpRedCoreVol->fBranched = false;
|
||||
}
|
||||
|
||||
CRITICAL_ASSERT(ret == 0);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef REDCONF_ENDIAN_SWAP
|
||||
static void MetaRootEndianSwap(
|
||||
METAROOT *pMetaRoot)
|
||||
{
|
||||
if(pMetaRoot == NULL)
|
||||
{
|
||||
REDERROR();
|
||||
}
|
||||
else
|
||||
{
|
||||
pMetaRoot->ulSectorCRC = RedRev32(pMetaRoot->ulSectorCRC);
|
||||
pMetaRoot->ulFreeBlocks = RedRev32(pMetaRoot->ulFreeBlocks);
|
||||
#if REDCONF_API_POSIX == 1
|
||||
pMetaRoot->ulFreeInodes = RedRev32(pMetaRoot->ulFreeInodes);
|
||||
#endif
|
||||
pMetaRoot->ulAllocNextBlock = RedRev32(pMetaRoot->ulAllocNextBlock);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/** @brief Process a critical file system error.
|
||||
|
||||
@param pszFileName The file in which the error occurred.
|
||||
@param ulLineNum The line number at which the error occurred.
|
||||
*/
|
||||
void RedVolCriticalError(
|
||||
const char *pszFileName,
|
||||
uint32_t ulLineNum)
|
||||
{
|
||||
#if REDCONF_OUTPUT == 1
|
||||
#if REDCONF_READ_ONLY == 0
|
||||
if(!gpRedVolume->fReadOnly)
|
||||
{
|
||||
RedOsOutputString("Critical file system error in Reliance Edge, setting volume to READONLY\n");
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
RedOsOutputString("Critical file system error in Reliance Edge (volume already READONLY)\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
#if REDCONF_READ_ONLY == 0
|
||||
gpRedVolume->fReadOnly = true;
|
||||
#endif
|
||||
|
||||
#if REDCONF_ASSERTS == 1
|
||||
RedOsAssertFail(pszFileName, ulLineNum);
|
||||
#else
|
||||
(void)pszFileName;
|
||||
(void)ulLineNum;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/** @brief Increment the sequence number.
|
||||
|
||||
@return A negated ::REDSTATUS code indicating the operation result.
|
||||
|
||||
@retval 0 Operation was successful.
|
||||
@retval -RED_EINVAL Cannot increment sequence number: maximum value reached.
|
||||
This should not ever happen.
|
||||
*/
|
||||
REDSTATUS RedVolSeqNumIncrement(void)
|
||||
{
|
||||
REDSTATUS ret;
|
||||
|
||||
if(gpRedVolume->ullSequence == UINT64_MAX)
|
||||
{
|
||||
/* In practice this should never, ever happen; to get here, there would
|
||||
need to be UINT64_MAX disk writes, which would take eons: longer
|
||||
than the lifetime of any product or storage media. If this assert
|
||||
fires and the current year is still written with four digits,
|
||||
suspect memory corruption.
|
||||
*/
|
||||
CRITICAL_ERROR();
|
||||
ret = -RED_EFUBAR;
|
||||
}
|
||||
else
|
||||
{
|
||||
gpRedVolume->ullSequence++;
|
||||
ret = 0;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@@ -0,0 +1,257 @@
|
||||
/* ----> DO NOT REMOVE THE FOLLOWING NOTICE <----
|
||||
|
||||
Copyright (c) 2014-2015 Datalight, Inc.
|
||||
All Rights Reserved Worldwide.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; use version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but "AS-IS," WITHOUT ANY WARRANTY; without even the implied warranty
|
||||
of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
/* Businesses and individuals that for commercial or other reasons cannot
|
||||
comply with the terms of the GPLv2 license may obtain a commercial license
|
||||
before incorporating Reliance Edge into proprietary software for
|
||||
distribution in any form. Visit http://www.datalight.com/reliance-edge for
|
||||
more information.
|
||||
*/
|
||||
/** @file
|
||||
*/
|
||||
#ifndef REDCORE_H
|
||||
#define REDCORE_H
|
||||
|
||||
|
||||
#include <redstat.h>
|
||||
#include <redvolume.h>
|
||||
#include "rednodes.h"
|
||||
#include "redcoremacs.h"
|
||||
#include "redcorevol.h"
|
||||
|
||||
|
||||
#define META_SIG_MASTER (0x5453414DU) /* 'MAST' */
|
||||
#define META_SIG_METAROOT (0x4154454DU) /* 'META' */
|
||||
#define META_SIG_IMAP (0x50414D49U) /* 'IMAP' */
|
||||
#define META_SIG_INODE (0x444F4E49U) /* 'INOD' */
|
||||
#define META_SIG_DINDIR (0x494C4244U) /* 'DBLI' */
|
||||
#define META_SIG_INDIR (0x49444E49U) /* 'INDI' */
|
||||
|
||||
|
||||
REDSTATUS RedIoRead(uint8_t bVolNum, uint32_t ulBlockStart, uint32_t ulBlockCount, void *pBuffer);
|
||||
#if REDCONF_READ_ONLY == 0
|
||||
REDSTATUS RedIoWrite(uint8_t bVolNum, uint32_t ulBlockStart, uint32_t ulBlockCount, const void *pBuffer);
|
||||
REDSTATUS RedIoFlush(uint8_t bVolNum);
|
||||
#endif
|
||||
|
||||
|
||||
/** Indicates a block buffer is dirty (its contents are different than the
|
||||
contents of the corresponding block on disk); or, when passed into
|
||||
RedBufferGet(), indicates that the buffer should be marked dirty.
|
||||
*/
|
||||
#define BFLAG_DIRTY ((uint16_t) 0x0001U)
|
||||
|
||||
/** Tells RedBufferGet() that the buffer is for a newly allocated block, and its
|
||||
contents should be zeroed instead of being read from disk. Always used in
|
||||
combination with BFLAG_DIRTY.
|
||||
*/
|
||||
#define BFLAG_NEW ((uint16_t) 0x0002U)
|
||||
|
||||
/** Indicates that a block buffer is a master block (MASTERBLOCK) metadata node.
|
||||
*/
|
||||
#define BFLAG_META_MASTER ((uint16_t)(0x0004U | BFLAG_META))
|
||||
|
||||
/** Indicates that a block buffer is an imap (IMAPNODE) metadata node.
|
||||
*/
|
||||
#define BFLAG_META_IMAP ((uint16_t)(0x0008U | BFLAG_META))
|
||||
|
||||
/** Indicates that a block buffer is an inode (INODE) metadata node.
|
||||
*/
|
||||
#define BFLAG_META_INODE ((uint16_t)(0x0010U | BFLAG_META))
|
||||
|
||||
/** Indicates that a block buffer is an indirect (INDIR) metadata node.
|
||||
*/
|
||||
#define BFLAG_META_INDIR ((uint16_t)(0x0020U | BFLAG_META))
|
||||
|
||||
/** Indicates that a block buffer is a double indirect (DINDIR) metadata node.
|
||||
*/
|
||||
#define BFLAG_META_DINDIR ((uint16_t)(0x0040U | BFLAG_META))
|
||||
|
||||
/** Indicates that a block buffer is a metadata node. Callers of RedBufferGet()
|
||||
should not use this flag; instead, use one of the BFLAG_META_* flags.
|
||||
*/
|
||||
#define BFLAG_META ((uint16_t) 0x8000U)
|
||||
|
||||
|
||||
void RedBufferInit(void);
|
||||
REDSTATUS RedBufferGet(uint32_t ulBlock, uint16_t uFlags, void **ppBuffer);
|
||||
void RedBufferPut(const void *pBuffer);
|
||||
#if REDCONF_READ_ONLY == 0
|
||||
REDSTATUS RedBufferFlush(uint32_t ulBlockStart, uint32_t ulBlockCount);
|
||||
void RedBufferDirty(const void *pBuffer);
|
||||
void RedBufferBranch(const void *pBuffer, uint32_t ulBlockNew);
|
||||
#if (REDCONF_API_POSIX == 1) || FORMAT_SUPPORTED
|
||||
void RedBufferDiscard(const void *pBuffer);
|
||||
#endif
|
||||
#endif
|
||||
REDSTATUS RedBufferDiscardRange(uint32_t ulBlockStart, uint32_t ulBlockCount);
|
||||
|
||||
|
||||
/** @brief Allocation state of a block.
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
ALLOCSTATE_FREE, /**< Free and may be allocated; writeable. */
|
||||
ALLOCSTATE_USED, /**< In-use and transacted; not writeable. */
|
||||
ALLOCSTATE_NEW, /**< In-use but not transacted; writeable. */
|
||||
ALLOCSTATE_AFREE /**< Will become free after a transaction; not writeable. */
|
||||
} ALLOCSTATE;
|
||||
|
||||
REDSTATUS RedImapBlockGet(uint8_t bMR, uint32_t ulBlock, bool *pfAllocated);
|
||||
#if REDCONF_READ_ONLY == 0
|
||||
REDSTATUS RedImapBlockSet(uint32_t ulBlock, bool fAllocated);
|
||||
REDSTATUS RedImapAllocBlock(uint32_t *pulBlock);
|
||||
#endif
|
||||
REDSTATUS RedImapBlockState(uint32_t ulBlock, ALLOCSTATE *pState);
|
||||
|
||||
#if REDCONF_IMAP_INLINE == 1
|
||||
REDSTATUS RedImapIBlockGet(uint8_t bMR, uint32_t ulBlock, bool *pfAllocated);
|
||||
REDSTATUS RedImapIBlockSet(uint32_t ulBlock, bool fAllocated);
|
||||
#endif
|
||||
|
||||
#if REDCONF_IMAP_EXTERNAL == 1
|
||||
REDSTATUS RedImapEBlockGet(uint8_t bMR, uint32_t ulBlock, bool *pfAllocated);
|
||||
REDSTATUS RedImapEBlockSet(uint32_t ulBlock, bool fAllocated);
|
||||
uint32_t RedImapNodeBlock(uint8_t bMR, uint32_t ulImapNode);
|
||||
#endif
|
||||
|
||||
|
||||
/** @brief Cached inode structure.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
uint32_t ulInode; /**< The inode number of the cached inode. */
|
||||
#if REDCONF_API_POSIX == 1
|
||||
bool fDirectory; /**< True if the inode is a directory. */
|
||||
#endif
|
||||
#if REDCONF_READ_ONLY == 0
|
||||
bool fBranched; /**< True if the inode is branched (writeable). */
|
||||
bool fDirty; /**< True if the inode buffer is dirty. */
|
||||
#endif
|
||||
bool fCoordInited; /**< True after the first seek. */
|
||||
|
||||
INODE *pInodeBuf; /**< Pointer to the inode buffer. */
|
||||
#if DINDIR_POINTERS > 0U
|
||||
DINDIR *pDindir; /**< Pointer to the double indirect node buffer. */
|
||||
#endif
|
||||
#if REDCONF_DIRECT_POINTERS < INODE_ENTRIES
|
||||
INDIR *pIndir; /**< Pointer to the indirect node buffer. */
|
||||
#endif
|
||||
uint8_t *pbData; /**< Pointer to the data block buffer. */
|
||||
|
||||
/* All the members below this point are part of the seek coordinates; see
|
||||
RedInodeDataSeek().
|
||||
*/
|
||||
uint32_t ulLogicalBlock; /**< Logical block offset into the inode. */
|
||||
#if DINDIR_POINTERS > 0U
|
||||
uint32_t ulDindirBlock; /**< Physical block number of the double indirect node. */
|
||||
#endif
|
||||
#if REDCONF_DIRECT_POINTERS < INODE_ENTRIES
|
||||
uint32_t ulIndirBlock; /**< Physical block number of the indirect node. */
|
||||
#endif
|
||||
uint32_t ulDataBlock; /**< Physical block number of the file data block. */
|
||||
|
||||
uint16_t uInodeEntry; /**< Which inode entry to traverse to reach ulLogicalBlock. */
|
||||
#if DINDIR_POINTERS > 0U
|
||||
uint16_t uDindirEntry; /**< Which double indirect entry to traverse to reach ulLogicalBlock. */
|
||||
#endif
|
||||
#if REDCONF_DIRECT_POINTERS < INODE_ENTRIES
|
||||
uint16_t uIndirEntry; /**< Which indirect entry to traverse to reach ulLogicalBlock. */
|
||||
#endif
|
||||
} CINODE;
|
||||
|
||||
#define CINODE_IS_MOUNTED(pInode) (((pInode) != NULL) && INODE_IS_VALID((pInode)->ulInode) && ((pInode)->pInodeBuf != NULL))
|
||||
#define CINODE_IS_DIRTY(pInode) (CINODE_IS_MOUNTED(pInode) && (pInode)->fDirty)
|
||||
|
||||
|
||||
#define IPUT_UPDATE_ATIME (0x01U)
|
||||
#define IPUT_UPDATE_MTIME (0x02U)
|
||||
#define IPUT_UPDATE_CTIME (0x04U)
|
||||
#define IPUT_UPDATE_MASK (IPUT_UPDATE_ATIME|IPUT_UPDATE_MTIME|IPUT_UPDATE_CTIME)
|
||||
|
||||
|
||||
REDSTATUS RedInodeMount(CINODE *pInode, FTYPE type, bool fBranch);
|
||||
#if REDCONF_READ_ONLY == 0
|
||||
REDSTATUS RedInodeBranch(CINODE *pInode);
|
||||
#endif
|
||||
#if (REDCONF_READ_ONLY == 0) && ((REDCONF_API_POSIX == 1) || FORMAT_SUPPORTED)
|
||||
REDSTATUS RedInodeCreate(CINODE *pInode, uint32_t ulPInode, uint16_t uMode);
|
||||
#endif
|
||||
#if DELETE_SUPPORTED
|
||||
REDSTATUS RedInodeDelete(CINODE *pInode);
|
||||
REDSTATUS RedInodeLinkDec(CINODE *pInode);
|
||||
#endif
|
||||
#if (REDCONF_READ_ONLY == 0) && (REDCONF_API_POSIX == 1)
|
||||
REDSTATUS RedInodeFree(CINODE *pInode);
|
||||
#endif
|
||||
void RedInodePut(CINODE *pInode, uint8_t bTimeFields);
|
||||
void RedInodePutCoord(CINODE *pInode);
|
||||
#if DINDIR_POINTERS > 0U
|
||||
void RedInodePutDindir(CINODE *pInode);
|
||||
#endif
|
||||
#if REDCONF_DIRECT_POINTERS < INODE_ENTRIES
|
||||
void RedInodePutIndir(CINODE *pInode);
|
||||
#endif
|
||||
void RedInodePutData(CINODE *pInode);
|
||||
#if ((REDCONF_READ_ONLY == 0) && ((REDCONF_API_POSIX == 1) || FORMAT_SUPPORTED)) || (REDCONF_CHECKER == 1)
|
||||
REDSTATUS RedInodeIsFree(uint32_t ulInode, bool *pfFree);
|
||||
#endif
|
||||
REDSTATUS RedInodeBitGet(uint8_t bMR, uint32_t ulInode, uint8_t bWhich, bool *pfAllocated);
|
||||
|
||||
REDSTATUS RedInodeDataRead(CINODE *pInode, uint64_t ullStart, uint32_t *pulLen, void *pBuffer);
|
||||
#if REDCONF_READ_ONLY == 0
|
||||
REDSTATUS RedInodeDataWrite(CINODE *pInode, uint64_t ullStart, uint32_t *pulLen, const void *pBuffer);
|
||||
#if DELETE_SUPPORTED || TRUNCATE_SUPPORTED
|
||||
REDSTATUS RedInodeDataTruncate(CINODE *pInode, uint64_t ullSize);
|
||||
#endif
|
||||
#endif
|
||||
REDSTATUS RedInodeDataSeekAndRead(CINODE *pInode, uint32_t ulBlock);
|
||||
REDSTATUS RedInodeDataSeek(CINODE *pInode, uint32_t ulBlock);
|
||||
|
||||
#if REDCONF_API_POSIX == 1
|
||||
#if REDCONF_READ_ONLY == 0
|
||||
REDSTATUS RedDirEntryCreate(CINODE *pPInode, const char *pszName, uint32_t ulInode);
|
||||
#endif
|
||||
#if DELETE_SUPPORTED
|
||||
REDSTATUS RedDirEntryDelete(CINODE *pPInode, uint32_t ulDeleteIdx);
|
||||
#endif
|
||||
REDSTATUS RedDirEntryLookup(CINODE *pPInode, const char *pszName, uint32_t *pulEntryIdx, uint32_t *pulInode);
|
||||
#if (REDCONF_API_POSIX_READDIR == 1) || (REDCONF_CHECKER == 1)
|
||||
REDSTATUS RedDirEntryRead(CINODE *pPInode, uint32_t *pulIdx, char *pszName, uint32_t *pulInode);
|
||||
#endif
|
||||
#if (REDCONF_READ_ONLY == 0) && (REDCONF_API_POSIX_RENAME == 1)
|
||||
REDSTATUS RedDirEntryRename(CINODE *pSrcPInode, const char *pszSrcName, CINODE *pSrcInode, CINODE *pDstPInode, const char *pszDstName, CINODE *pDstInode);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
REDSTATUS RedVolMount(void);
|
||||
REDSTATUS RedVolMountMaster(void);
|
||||
REDSTATUS RedVolMountMetaroot(void);
|
||||
#if REDCONF_READ_ONLY == 0
|
||||
REDSTATUS RedVolTransact(void);
|
||||
#endif
|
||||
void RedVolCriticalError(const char *pszFileName, uint32_t ulLineNum);
|
||||
REDSTATUS RedVolSeqNumIncrement(void);
|
||||
|
||||
#if FORMAT_SUPPORTED
|
||||
REDSTATUS RedVolFormat(void);
|
||||
#endif
|
||||
|
||||
|
||||
#endif
|
||||
|
@@ -0,0 +1,92 @@
|
||||
/* ----> DO NOT REMOVE THE FOLLOWING NOTICE <----
|
||||
|
||||
Copyright (c) 2014-2015 Datalight, Inc.
|
||||
All Rights Reserved Worldwide.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; use version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but "AS-IS," WITHOUT ANY WARRANTY; without even the implied warranty
|
||||
of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
/* Businesses and individuals that for commercial or other reasons cannot
|
||||
comply with the terms of the GPLv2 license may obtain a commercial license
|
||||
before incorporating Reliance Edge into proprietary software for
|
||||
distribution in any form. Visit http://www.datalight.com/reliance-edge for
|
||||
more information.
|
||||
*/
|
||||
/** @file
|
||||
*/
|
||||
#ifndef REDCOREMACS_H
|
||||
#define REDCOREMACS_H
|
||||
|
||||
|
||||
#define BLOCK_NUM_MASTER (0UL) /* Block number of the master block. */
|
||||
#define BLOCK_NUM_FIRST_METAROOT (1UL) /* Block number of the first metaroot. */
|
||||
|
||||
#define BLOCK_SPARSE (0U)
|
||||
|
||||
#define DINDIR_POINTERS ((INODE_ENTRIES - REDCONF_DIRECT_POINTERS) - REDCONF_INDIRECT_POINTERS)
|
||||
#define DINDIR_DATA_BLOCKS (INDIR_ENTRIES * INDIR_ENTRIES)
|
||||
|
||||
#define INODE_INDIR_BLOCKS (REDCONF_INDIRECT_POINTERS * INDIR_ENTRIES)
|
||||
#define INODE_DINDIR_BLOCKS (DINDIR_POINTERS * DINDIR_DATA_BLOCKS)
|
||||
#define INODE_DATA_BLOCKS (REDCONF_DIRECT_POINTERS + INODE_INDIR_BLOCKS + INODE_DINDIR_BLOCKS)
|
||||
#define INODE_SIZE_MAX (UINT64_SUFFIX(1) * REDCONF_BLOCK_SIZE * INODE_DATA_BLOCKS)
|
||||
|
||||
|
||||
/* First inode number that can be allocated.
|
||||
*/
|
||||
#if REDCONF_API_POSIX == 1
|
||||
#define INODE_FIRST_FREE (INODE_FIRST_VALID + 1U)
|
||||
#else
|
||||
#define INODE_FIRST_FREE (INODE_FIRST_VALID)
|
||||
#endif
|
||||
|
||||
/** @brief Determine if an inode number is valid.
|
||||
*/
|
||||
#define INODE_IS_VALID(INODENUM) (((INODENUM) >= INODE_FIRST_VALID) && ((INODENUM) < (INODE_FIRST_VALID + gpRedVolConf->ulInodeCount)))
|
||||
|
||||
|
||||
/* The number of blocks reserved to allow a truncate or delete operation to
|
||||
complete when the disk is otherwise full.
|
||||
|
||||
The more expensive of the two operations is delete, which has to actually
|
||||
write to a file data block to remove the directory entry.
|
||||
*/
|
||||
#if REDCONF_READ_ONLY == 1
|
||||
#define RESERVED_BLOCKS 0U
|
||||
#elif (REDCONF_API_POSIX == 1) && ((REDCONF_API_POSIX_UNLINK == 1) || (REDCONF_API_POSIX_RMDIR == 1))
|
||||
#if DINDIR_POINTERS > 0U
|
||||
#define RESERVED_BLOCKS 3U
|
||||
#elif REDCONF_INDIRECT_POINTERS > 0U
|
||||
#define RESERVED_BLOCKS 2U
|
||||
#else
|
||||
#define RESERVED_BLOCKS 1U
|
||||
#endif
|
||||
#elif ((REDCONF_API_POSIX == 1) && (REDCONF_API_POSIX_FTRUNCATE == 1)) || ((REDCONF_API_FSE == 1) && (REDCONF_API_FSE_TRUNCATE == 1))
|
||||
#if DINDIR_POINTERS > 0U
|
||||
#define RESERVED_BLOCKS 2U
|
||||
#elif REDCONF_INDIRECT_POINTERS > 0U
|
||||
#define RESERVED_BLOCKS 1U
|
||||
#else
|
||||
#define RESERVED_BLOCKS 0U
|
||||
#endif
|
||||
#else
|
||||
#define RESERVED_BLOCKS 0U
|
||||
#endif
|
||||
|
||||
|
||||
#define CRITICAL_ASSERT(EXP) ((EXP) ? (void)0 : CRITICAL_ERROR())
|
||||
#define CRITICAL_ERROR() RedVolCriticalError(__FILE__, __LINE__)
|
||||
|
||||
|
||||
#endif
|
||||
|
@@ -0,0 +1,95 @@
|
||||
/* ----> DO NOT REMOVE THE FOLLOWING NOTICE <----
|
||||
|
||||
Copyright (c) 2014-2015 Datalight, Inc.
|
||||
All Rights Reserved Worldwide.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; use version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but "AS-IS," WITHOUT ANY WARRANTY; without even the implied warranty
|
||||
of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
/* Businesses and individuals that for commercial or other reasons cannot
|
||||
comply with the terms of the GPLv2 license may obtain a commercial license
|
||||
before incorporating Reliance Edge into proprietary software for
|
||||
distribution in any form. Visit http://www.datalight.com/reliance-edge for
|
||||
more information.
|
||||
*/
|
||||
/** @file
|
||||
*/
|
||||
#ifndef REDCOREVOL_H
|
||||
#define REDCOREVOL_H
|
||||
|
||||
|
||||
/** @brief Per-volume run-time data specific to the core.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
/** Whether this volume uses the inline imap (true) or external imap
|
||||
(false). Computed at initialization time based on the block count.
|
||||
*/
|
||||
bool fImapInline;
|
||||
|
||||
#if REDCONF_IMAP_EXTERNAL == 1
|
||||
/** First block number of the on-disk imap. Valid only when fImapInline
|
||||
is false.
|
||||
*/
|
||||
uint32_t ulImapStartBN;
|
||||
|
||||
/** The number of double-allocated imap nodes that make up the imap.
|
||||
*/
|
||||
uint32_t ulImapNodeCount;
|
||||
#endif
|
||||
|
||||
/** Block number where the inode table starts.
|
||||
*/
|
||||
uint32_t ulInodeTableStartBN;
|
||||
|
||||
/** First block number that can be allocated.
|
||||
*/
|
||||
uint32_t ulFirstAllocableBN;
|
||||
|
||||
/** The two metaroot structures, committed and working state.
|
||||
*/
|
||||
METAROOT aMR[2U];
|
||||
|
||||
/** The index of the current metaroot; must be 0 or 1.
|
||||
*/
|
||||
uint8_t bCurMR;
|
||||
|
||||
/** Whether the volume has been branched or not.
|
||||
*/
|
||||
bool fBranched;
|
||||
|
||||
/** The number of blocks which will become free after the next transaction.
|
||||
*/
|
||||
uint32_t ulAlmostFreeBlocks;
|
||||
|
||||
#if RESERVED_BLOCKS > 0U
|
||||
/** Whether to use the blocks reserved for operations that create free
|
||||
space.
|
||||
*/
|
||||
bool fUseReservedBlocks;
|
||||
#endif
|
||||
} COREVOLUME;
|
||||
|
||||
/* Pointer to the core volume currently being accessed; populated during
|
||||
RedCoreVolSetCurrent().
|
||||
*/
|
||||
extern COREVOLUME * CONST_IF_ONE_VOLUME gpRedCoreVol;
|
||||
|
||||
/* Pointer to the metaroot currently being accessed; populated during
|
||||
RedCoreVolSetCurrent() and RedCoreVolTransact().
|
||||
*/
|
||||
extern METAROOT *gpRedMR;
|
||||
|
||||
|
||||
#endif
|
||||
|
@@ -0,0 +1,195 @@
|
||||
/* ----> DO NOT REMOVE THE FOLLOWING NOTICE <----
|
||||
|
||||
Copyright (c) 2014-2015 Datalight, Inc.
|
||||
All Rights Reserved Worldwide.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; use version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but "AS-IS," WITHOUT ANY WARRANTY; without even the implied warranty
|
||||
of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
/* Businesses and individuals that for commercial or other reasons cannot
|
||||
comply with the terms of the GPLv2 license may obtain a commercial license
|
||||
before incorporating Reliance Edge into proprietary software for
|
||||
distribution in any form. Visit http://www.datalight.com/reliance-edge for
|
||||
more information.
|
||||
*/
|
||||
/** @file
|
||||
*/
|
||||
#ifndef REDNODES_H
|
||||
#define REDNODES_H
|
||||
|
||||
|
||||
#define NODEHEADER_SIZE (16U)
|
||||
#define NODEHEADER_OFFSET_SIG (0U)
|
||||
#define NODEHEADER_OFFSET_CRC (4U)
|
||||
#define NODEHEADER_OFFSET_SEQ (8U)
|
||||
|
||||
/** @brief Common header for all metadata nodes.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
uint32_t ulSignature; /**< Value which uniquely identifies the metadata node type. */
|
||||
uint32_t ulCRC; /**< CRC-32 checksum of the node contents, starting after the CRC. */
|
||||
uint64_t ullSequence; /**< Current sequence number at the time the node was written to disk. */
|
||||
} NODEHEADER;
|
||||
|
||||
|
||||
/** Flag set in the master block when REDCONF_API_POSIX == 1. */
|
||||
#define MBFLAG_API_POSIX (0x01U)
|
||||
|
||||
/** Flag set in the master block when REDCONF_INODE_TIMESTAMPS == 1. */
|
||||
#define MBFLAG_INODE_TIMESTAMPS (0x02U)
|
||||
|
||||
/** Flag set in the master block when REDCONF_INODE_BLOCKS == 1. */
|
||||
#define MBFLAG_INODE_BLOCKS (0x04U)
|
||||
|
||||
/** Flag set in the master block when (REDCONF_API_POSIX == 1) && (REDCONF_API_POSIX_LINK == 1). */
|
||||
#define MBFLAG_INODE_NLINK (0x08U)
|
||||
|
||||
|
||||
/** @brief Node which identifies the volume and stores static volume information.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
NODEHEADER hdr; /**< Common node header. */
|
||||
|
||||
uint32_t ulVersion; /**< On-disk layout version number. */
|
||||
char acBuildNum[8U]; /**< Build number of the product (not null terminated). */
|
||||
uint32_t ulFormatTime; /**< Date and time the volume was formatted. */
|
||||
uint32_t ulInodeCount; /**< Compile-time configured number of inodes. */
|
||||
uint32_t ulBlockCount; /**< Compile-time configured number of logical blocks. */
|
||||
uint16_t uMaxNameLen; /**< Compile-time configured maximum file name length. */
|
||||
uint16_t uDirectPointers; /**< Compile-time configured number of direct pointers per inode. */
|
||||
uint16_t uIndirectPointers; /**< Compile-time configured number of indirect pointers per inode. */
|
||||
uint8_t bBlockSizeP2; /**< Compile-time configured block size, expressed as a power of two. */
|
||||
uint8_t bFlags; /**< Compile-time booleans which affect on-disk structures. */
|
||||
} MASTERBLOCK;
|
||||
|
||||
|
||||
#if REDCONF_API_POSIX == 1
|
||||
#define METAROOT_HEADER_SIZE (NODEHEADER_SIZE + 16U) /* Size in bytes of the metaroot header fields. */
|
||||
#else
|
||||
#define METAROOT_HEADER_SIZE (NODEHEADER_SIZE + 12U) /* Size in bytes of the metaroot header fields. */
|
||||
#endif
|
||||
#define METAROOT_ENTRY_BYTES (REDCONF_BLOCK_SIZE - METAROOT_HEADER_SIZE) /* Number of bytes remaining in the metaroot block for entries. */
|
||||
#define METAROOT_ENTRIES (METAROOT_ENTRY_BYTES * 8U)
|
||||
|
||||
/** @brief Metadata root node; each volume has two.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
NODEHEADER hdr; /**< Common node header. */
|
||||
|
||||
uint32_t ulSectorCRC; /**< CRC-32 checksum of the first sector. */
|
||||
uint32_t ulFreeBlocks; /**< Number of allocable blocks that are free. */
|
||||
#if REDCONF_API_POSIX == 1
|
||||
uint32_t ulFreeInodes; /**< Number of inode slots that are free. */
|
||||
#endif
|
||||
uint32_t ulAllocNextBlock; /**< Forward allocation pointer. */
|
||||
|
||||
/** Imap bitmap. With inline imaps, this is the imap bitmap that indicates
|
||||
which inode blocks are used and which allocable blocks are used.
|
||||
Otherwise, this bitmap toggles nodes in the external imap between one
|
||||
of two possible block locations.
|
||||
*/
|
||||
uint8_t abEntries[METAROOT_ENTRY_BYTES];
|
||||
} METAROOT;
|
||||
|
||||
|
||||
#if REDCONF_IMAP_EXTERNAL == 1
|
||||
#define IMAPNODE_HEADER_SIZE (NODEHEADER_SIZE) /* Size in bytes of the imap node header fields. */
|
||||
#define IMAPNODE_ENTRY_BYTES (REDCONF_BLOCK_SIZE - IMAPNODE_HEADER_SIZE) /* Number of bytes remaining in the imap node for entries. */
|
||||
#define IMAPNODE_ENTRIES (IMAPNODE_ENTRY_BYTES * 8U)
|
||||
|
||||
/** @brief One node of the external imap.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
NODEHEADER hdr; /**< Common node header. */
|
||||
|
||||
/** Bitmap which indicates which inode blocks are used and which allocable
|
||||
blocks are used.
|
||||
*/
|
||||
uint8_t abEntries[IMAPNODE_ENTRY_BYTES];
|
||||
} IMAPNODE;
|
||||
#endif
|
||||
|
||||
|
||||
#define INODE_HEADER_SIZE (NODEHEADER_SIZE + 8U + ((REDCONF_INODE_BLOCKS == 1) ? 4U : 0U) + \
|
||||
((REDCONF_INODE_TIMESTAMPS == 1) ? 12U : 0U) + 4U + ((REDCONF_API_POSIX == 1) ? 4U : 0U))
|
||||
#define INODE_ENTRIES ((REDCONF_BLOCK_SIZE - INODE_HEADER_SIZE) / 4U)
|
||||
|
||||
#if (REDCONF_DIRECT_POINTERS < 0) || (REDCONF_DIRECT_POINTERS > (INODE_ENTRIES - REDCONF_INDIRECT_POINTERS))
|
||||
#error "Configuration error: invalid value of REDCONF_DIRECT_POINTERS"
|
||||
#endif
|
||||
#if (REDCONF_INDIRECT_POINTERS < 0) || (REDCONF_INDIRECT_POINTERS > (INODE_ENTRIES - REDCONF_DIRECT_POINTERS))
|
||||
#error "Configuration error: invalid value of REDCONF_INDIRECT_POINTERS"
|
||||
#endif
|
||||
|
||||
/** @brief Stores metadata for a file or directory.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
NODEHEADER hdr; /**< Common node header. */
|
||||
|
||||
uint64_t ullSize; /**< Size of the inode, in bytes. */
|
||||
#if REDCONF_INODE_BLOCKS == 1
|
||||
uint32_t ulBlocks; /**< Total number file data blocks allocated to the inode. */
|
||||
#endif
|
||||
#if REDCONF_INODE_TIMESTAMPS == 1
|
||||
uint32_t ulATime; /**< Time of last access (seconds since January 1, 1970). */
|
||||
uint32_t ulMTime; /**< Time of last modification (seconds since January 1, 1970). */
|
||||
uint32_t ulCTime; /**< Time of last status change (seconds since January 1, 1970). */
|
||||
#endif
|
||||
uint16_t uMode; /**< Inode type (file or directory) and permissions (reserved). */
|
||||
#if (REDCONF_API_POSIX == 1) && (REDCONF_API_POSIX_LINK == 1)
|
||||
uint16_t uNLink; /**< Link count, number of names pointing to the inode. */
|
||||
#else
|
||||
uint8_t abPadding[2]; /**< Padding to 32-bit align the next member. */
|
||||
#endif
|
||||
#if REDCONF_API_POSIX == 1
|
||||
uint32_t ulPInode; /**< Parent inode number. Only guaranteed to be accurate for directories. */
|
||||
#endif
|
||||
|
||||
/** Block numbers for lower levels of the file metadata structure. Some
|
||||
fraction of these entries are for direct pointers (file data block
|
||||
numbers), some for indirect pointers, some for double-indirect
|
||||
pointers; the number allocated to each is static but user-configurable.
|
||||
For all types, an array slot is zero if the range is sparse or beyond
|
||||
the end of file.
|
||||
*/
|
||||
uint32_t aulEntries[INODE_ENTRIES];
|
||||
} INODE;
|
||||
|
||||
|
||||
#define INDIR_HEADER_SIZE (NODEHEADER_SIZE + 4U)
|
||||
#define INDIR_ENTRIES ((REDCONF_BLOCK_SIZE - INDIR_HEADER_SIZE) / 4U)
|
||||
|
||||
/** @brief Node for storing block pointers.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
NODEHEADER hdr; /**< Common node header. */
|
||||
|
||||
uint32_t ulInode; /**< Inode which owns this indirect or double indirect. */
|
||||
|
||||
/** For indirect nodes, stores block numbers of file data. For double
|
||||
indirect nodes, stores block numbers of indirect nodes. An array
|
||||
slot is zero if the corresponding block or indirect range is beyond
|
||||
the end of file or entirely sparse.
|
||||
*/
|
||||
uint32_t aulEntries[INDIR_ENTRIES];
|
||||
} INDIR, DINDIR;
|
||||
|
||||
|
||||
#endif
|
||||
|
@@ -0,0 +1,389 @@
|
||||
Datalight Coding Style
|
||||
======================
|
||||
|
||||
This is a description of the Datalight Coding Style intended for third parties
|
||||
who want to contribute code to Reliance Edge. This document is derived from the
|
||||
DDSS Coding Guidelines, but only contains a subset of the content which is most
|
||||
likely to be relevant to third party contributors.
|
||||
|
||||
Reliance Edge complies with the MISRA-C:2012 coding guidelines, which includes
|
||||
many rules that affect coding style. Unfortunately the MISRA-C:2012 document is
|
||||
not freely available, and is much too long to be effectively summarized, but if
|
||||
you are familiar with the rules, adhere to them. A few important rules of
|
||||
thumb: avoid the goto and continue keywords; avoid using more than one break
|
||||
in a loop; and avoid having more than one return from a function (single point
|
||||
of exit); default cases in every switch statement; avoid recursion; and make
|
||||
generous use of parentheses. Outside of the file system driver, in tests and
|
||||
host tools, the MISRA-C rules are relaxed.
|
||||
|
||||
Beyond MISRA-C, Datalight has a standard coding style. Most aspects of this
|
||||
style are matters of preference, but when contributing code to Datalight an
|
||||
effort should be made to use this style for the sake of consistency.
|
||||
|
||||
Below is an example function, which illustrates several key points of Datalight
|
||||
Coding Style:
|
||||
|
||||
/** @brief One-sentence description of what this function does.
|
||||
|
||||
Additional description.
|
||||
|
||||
@param ulFirstParameter Description of the parameter.
|
||||
@param pszPointer Description of the parameter.
|
||||
|
||||
@return Describe the return value.
|
||||
|
||||
@retval true Optional description of specific return value.
|
||||
@retval false Optional description of specific return value.
|
||||
*/
|
||||
bool ExampleFunction(
|
||||
uint32_t ulFirstParameter,
|
||||
char *pszPointer)
|
||||
{
|
||||
bool fStatus = true;
|
||||
|
||||
/* This is a single-line comment.
|
||||
*/
|
||||
if(ulFirstParameter > 0U)
|
||||
{
|
||||
/* This is a multi-line comment. Filler text: Lorem ipsum dolor sit
|
||||
amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt
|
||||
ut labore et dolore magna aliqua.
|
||||
*/
|
||||
FunctionCall();
|
||||
|
||||
while(fStatus)
|
||||
{
|
||||
fStatus = AnotherFunction(ulFirstParameter, pszPointer);
|
||||
}
|
||||
}
|
||||
|
||||
return fStatus;
|
||||
}
|
||||
|
||||
Tab Stop Conventions
|
||||
--------------------
|
||||
|
||||
In all C code (.c/.h), use a tab width of four spaces, and use soft tabs (in
|
||||
other words, tabs are expanded to spaces). In Makefiles, use hard tabs and a
|
||||
tab width of 8.
|
||||
|
||||
Naming
|
||||
------
|
||||
|
||||
Datalight uses CamelCase for functions and variables. Type names are generally
|
||||
UPPERCASE, except for standard types like uint32_t. Preprocessor macros are
|
||||
UPPERCASE, with words separated by underscores (for example, INODE_INVALID).
|
||||
|
||||
Doxygen Documentation
|
||||
---------------------
|
||||
|
||||
Doxygen is used to document functions (including static functions), along with
|
||||
types, structures, files, etc. For Doxygen tags, use '@' instead of a backslash
|
||||
(thus "@param" not "\param").
|
||||
|
||||
Function Declarations
|
||||
---------------------
|
||||
|
||||
Multi-line function declarations are preferred, as they tend to be more
|
||||
readable. Use the following form:
|
||||
|
||||
static bool ExampleFunctionDeclaration(
|
||||
uint32_t ulFirstParameter,
|
||||
char *pszPointer,
|
||||
uint8_t **ppbBuffer)
|
||||
{
|
||||
uint16_t uLocalVar; /* descriptive comment */
|
||||
uint8_t *pbBuffer = NULL; /* descriptive comment */
|
||||
|
||||
Function body...
|
||||
}
|
||||
|
||||
The following guidelines should be used:
|
||||
|
||||
- Align both the data-type and the variable names, for parameters and locals, at
|
||||
the same level if practical.
|
||||
- For pointer types, the '*' belongs to the variable name---it's not part of the
|
||||
data-type, so keep it with the variable name.
|
||||
- If useful, single line comments may be used to describe local variables (not
|
||||
a requirement).
|
||||
- For functions with no parameters, the "void" declaration does not need to be
|
||||
on a separate line.
|
||||
- Generally each variable should be declared on a separate line. This promotes
|
||||
readability, and facilitates having a comment for each variable.
|
||||
|
||||
Function declarations should be spaced apart by two blank lines between the
|
||||
closing brace which ends a function and the Doxygen comment which starts the
|
||||
next.
|
||||
|
||||
Curly Braces
|
||||
------------
|
||||
|
||||
Datalight lines up all curly braces vertically. As per MISRA-C, curly braces
|
||||
are never omitted, even if the braces contain only a single statement.
|
||||
|
||||
For consistency, even structure declarations and initializations should use the
|
||||
same style, with the curly braces lined up vertically. One exception is for
|
||||
structure initializations where both the opening and closing curly braces can
|
||||
fit on the same line. If so, do it.
|
||||
|
||||
Code Comments
|
||||
-------------
|
||||
|
||||
Datalight uses the standard C style /* comments */. C++ style comments (//) are
|
||||
never used. The Datalight standard comment style is shown below. This style
|
||||
applies to all general comments within the code.
|
||||
|
||||
/* This is a single-line comment.
|
||||
*/
|
||||
if(ulFirstParameter > 0U)
|
||||
{
|
||||
/* This is a multi-line comment. Filler text: Lorem ipsum dolor sit amet,
|
||||
consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore
|
||||
et dolore magna aliqua.
|
||||
*/
|
||||
while(fStatus)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
Note the characteristics:
|
||||
|
||||
- The /* and */ align with the natural 4 character indentation.
|
||||
- The comment text is exactly indented another 4 characters.
|
||||
- The comment text starts on the same line as the opening /*.
|
||||
- The terminating */ is on its own line.
|
||||
- There is usually a single blank line preceding the comment, however if the
|
||||
preceding line is an opening curly brace, then an extra blank line is not
|
||||
necessary.
|
||||
- There is usually no blank line after the comment, but rather the closing */
|
||||
"attaches" the comment to the code about which the comment refers.
|
||||
- These comments should always fit with the standard 80 character margin.
|
||||
|
||||
Comments where the /* and */ are on the same line may be used in a few places:
|
||||
|
||||
- For variable or parameter descriptions, where the comment fits on the same
|
||||
line as the declaration.
|
||||
- For structure member declarations, where the comment fits on the same line as
|
||||
the declaration.
|
||||
- For macros or preprocessor logic, where the comment fits on the same line.
|
||||
|
||||
It is OK for such comments to exceed the 80 character margin by a small amount,
|
||||
if necessary, as this sometimes promotes code readability.
|
||||
|
||||
Indentation Style
|
||||
-----------------
|
||||
|
||||
The general paradigm used in Datalight code is that curly braces line up
|
||||
vertically, and everything in between them is indented. This should include all
|
||||
comments, labels, and preprocessor symbols. The only things which are aligned
|
||||
at the left-most columns are:
|
||||
|
||||
- Symbols, variables, declarations, and preprocessor logic which are at the
|
||||
module-scope (outside of a function)
|
||||
- Comments which are outside of a function
|
||||
- Function declarations
|
||||
- Function open and closing curly braces
|
||||
|
||||
Typically comments are always lined up directly with the code to which they
|
||||
apply.
|
||||
|
||||
Labels (when used; gotos are disallowed in driver code) are lined up two
|
||||
characters to the left of the code they reside in, to make them stand out, while
|
||||
as the same time, still remaining subservient to the level of curly braces in
|
||||
which they reside. For example:
|
||||
|
||||
bool ExampleLabelUsage(void)
|
||||
{
|
||||
MutexLock();
|
||||
|
||||
Lots of complicated code...
|
||||
|
||||
Unlock:
|
||||
|
||||
MutexUnlock();
|
||||
|
||||
return fSuccess;
|
||||
}
|
||||
|
||||
Preprocessor logic, such as controlling features which are conditionally
|
||||
compiled in or out, should not disrupt the flow of the code, but rather should
|
||||
be indented in similar fashion to the code it controls, but positioned two
|
||||
characters to the left. For example, consider the following code snippet. The
|
||||
preprocessor conditions are both indented relative to the outer curly braces,
|
||||
but do not disrupt the normal code flow.
|
||||
|
||||
int32_t red_statvfs(
|
||||
const char *pszVolume,
|
||||
REDSTATFS *pStatvfs)
|
||||
{
|
||||
REDSTATUS ret;
|
||||
|
||||
ret = PosixEnter();
|
||||
if(ret == 0)
|
||||
{
|
||||
uint8_t bVolNum;
|
||||
|
||||
ret = RedPathSplit(pszVolume, &bVolNum, NULL);
|
||||
|
||||
#if REDCONF_VOLUME_COUNT > 1U
|
||||
if(ret == 0)
|
||||
{
|
||||
ret = RedCoreVolSetCurrent(bVolNum);
|
||||
}
|
||||
#endif
|
||||
|
||||
if(ret == 0)
|
||||
{
|
||||
ret = RedCoreVolStat(pStatvfs);
|
||||
}
|
||||
|
||||
PosixLeave();
|
||||
}
|
||||
|
||||
return PosixReturn(ret);
|
||||
}
|
||||
|
||||
Note that, like anything else between curly brackets, the contents of a switch
|
||||
statement are indented:
|
||||
|
||||
switch(ulSignature)
|
||||
{
|
||||
case META_SIG_MASTER:
|
||||
fValid = (uFlags == BFLAG_META_MASTER);
|
||||
break;
|
||||
case META_SIG_IMAP:
|
||||
fValid = (uFlags == BFLAG_META_IMAP);
|
||||
break;
|
||||
case META_SIG_INODE:
|
||||
fValid = (uFlags == BFLAG_META_INODE);
|
||||
break;
|
||||
case META_SIG_DINDIR:
|
||||
fValid = (uFlags == BFLAG_META_DINDIR);
|
||||
break;
|
||||
case META_SIG_INDIR:
|
||||
fValid = (uFlags == BFLAG_META_INDIR);
|
||||
break;
|
||||
default:
|
||||
fValid = false;
|
||||
break;
|
||||
}
|
||||
|
||||
Maximum Line Length
|
||||
-------------------
|
||||
|
||||
The maximum line length for code need not be rigidly limited to the traditional
|
||||
80 characters. Nevertheless the line lengths should be kept reasonable.
|
||||
Anything longer than 100 to 120 characters should probably be broken up. The
|
||||
most important consideration is readability---fitting on the screen is important
|
||||
for readability, but equally important is facilitating an easy understanding of
|
||||
the logical code flow.
|
||||
|
||||
There are a few exceptions on both sides of the issue. Generally comments
|
||||
should be limited to 80 characters always. Some lines of code may exceed the
|
||||
120 character length by a large margin, if it makes the code more understandable
|
||||
and maintainable. This is especially true when dealing with code that generates
|
||||
output which needs to be lined up.
|
||||
|
||||
Regardless of everything else, no lines should exceed 250 characters because
|
||||
some editors cannot handle anything larger.
|
||||
|
||||
Maximum Display Output Line Length
|
||||
----------------------------------
|
||||
|
||||
Any code which displays TTY style output, whether on a screen or a terminal,
|
||||
should be constructed so the output is readable and wraps properly on an 80
|
||||
character wide display. This primarily applies to the "standard" output from
|
||||
various tests and tools as well as syntax output for those tests and tools;
|
||||
debug output can violate this rule.
|
||||
|
||||
Preprocessor Notation
|
||||
---------------------
|
||||
|
||||
Don't use preprocessor notation where the # is separated from the keyword by one
|
||||
or more white spaces. For example, don't do:
|
||||
|
||||
#ifndef SYMBOL1
|
||||
# define SYMBOL1
|
||||
#endif
|
||||
|
||||
Instead, do:
|
||||
|
||||
#ifndef SYMBOL1
|
||||
#define SYMBOL1
|
||||
#endif
|
||||
|
||||
Hexadecimal Notation
|
||||
--------------------
|
||||
|
||||
Use uppercase for any alphabetic hexadecimal digits, and lower case for the
|
||||
notational element. For example:
|
||||
|
||||
#define HEXNUM 0x123abd /* Bad */
|
||||
#define HEXNUM 0X123ABD /* Bad */
|
||||
#define HEXNUM 0x123ABD /* Good */
|
||||
|
||||
Hungarian Notation
|
||||
------------------
|
||||
|
||||
Datalight uses Hungarian notation. The following type prefixes are used:
|
||||
|
||||
Type Prefix | Meaning
|
||||
----------- | -------
|
||||
c | char
|
||||
uc | unsigned char
|
||||
i | int
|
||||
n | unsigned int or size_t
|
||||
b | uint8_t
|
||||
u | uint16_t
|
||||
ul | uint32_t
|
||||
ull | uint64_t
|
||||
sz | array of char that will be null-terminated
|
||||
f | bool
|
||||
h | A handle
|
||||
fn | A function (always used with the "p" modifier)
|
||||
|
||||
There is no official Hungarian for int8_t, int16_t, int32_t, or int64_t,
|
||||
although some code uses unofficial variants (like "ll" for int64_t).
|
||||
|
||||
The following modifiers may be used in combination with the type prefixes
|
||||
defined above, or in combination with other types:
|
||||
|
||||
Modifier | Meaning
|
||||
-------- | -------
|
||||
a | An array
|
||||
p | A pointer
|
||||
g | A global variable
|
||||
|
||||
Notes:
|
||||
|
||||
- There is no standard Hungarian for structure declarations, however the use of
|
||||
the "a" and "p" modifiers is completely appropriate (and expected).
|
||||
- For those data types which do not have any standard defined Hungarian prefix,
|
||||
using none is preferable to misusing another prefix which would lead to
|
||||
confusion.
|
||||
- The "p" pointer modifier must be used such that a variable which is a pointer
|
||||
to a pointer uses multiple "p" prefixes. A general rule-of-thumb is that the
|
||||
variable name should have the same number of "p" prefixes as the declaration
|
||||
has asterisks. This allows pointer expressions to be easily decoded using
|
||||
cancellation.
|
||||
|
||||
Variable Scope
|
||||
--------------
|
||||
|
||||
Declare a variable in the narrowest scope in which it is meaningful.
|
||||
Unnecessarily declaring all variables at the beginning of a function, where they
|
||||
may be physically far from where they are actually used, makes the code harder
|
||||
to maintain.
|
||||
|
||||
When multiple blocks of code share a variable, but not its value, declare the
|
||||
variable separately for each code block.
|
||||
|
||||
For example, if two separate blocks contain loops indexed by a variable ulIndex
|
||||
declare it separately in each block rather than declaring it once in a wider
|
||||
scope and using it in both places.
|
||||
|
||||
Using distinct declarations in the two blocks allows the compiler to check for
|
||||
failure to initialize the variable in the second block. If there is a single
|
||||
declaration, the (now meaningless) value left over from the first block can be
|
||||
used erroneously in the second block.
|
||||
|
@@ -0,0 +1,135 @@
|
||||
# Reliance Edge Release Notes
|
||||
|
||||
This file contains a list of updates made to Reliance Edge over the course of
|
||||
recent releases and a list of known issues.
|
||||
|
||||
## Release History and Changes
|
||||
|
||||
### Reliance Edge v2.0, January 2017
|
||||
|
||||
- Added support for Linux as a host environment
|
||||
- All "host" projects may now be built in either Windows or Linux using the
|
||||
`make` command. The formatter and image builder are built, and the checker
|
||||
and image copier are also built in the commercial kit.
|
||||
- An additional host tool has been added for Linux only: `redfuse`. It is a
|
||||
File System in User Space (FUSE) implementation, allowing a Reliance Edge
|
||||
volume to be mounted directly on Linux for easy access. It is built from
|
||||
the host project folder using the command `make redfuse`.
|
||||
- The OS-specific API test (commercial kit only) is now ported to run on Linux
|
||||
for the purpose of verifying the FUSE implementation.
|
||||
- Fixed a bug that could leave a directory in an invalid state after removing
|
||||
files. For example, an affected directory might report a non-zero length even
|
||||
after all files had been deleted.
|
||||
- Fixed a bug that would leave the driver in a bad state if a mount operation
|
||||
failed due to missing or corrupt metaroot blocks.
|
||||
|
||||
### Reliance Edge v1.1 (Beta), November 2016
|
||||
|
||||
- Added support for a discard (trim) interface in the commercial kit. While
|
||||
discards are not integral to the behavior of the filesystem, they allow
|
||||
certain types of Flash drivers and media to perform at optimal speed and
|
||||
efficiency. The commercial version of Reliance Edge now allows the user to
|
||||
implement this interface for compatible storage media.
|
||||
- This change added new fields to the configuration files redconf.h and
|
||||
redconf.c. The configuration utility has been updated to version 1.1 and
|
||||
existing configuration files must be updated using the updated utility.
|
||||
- The configuration utility now has keyboard shortcuts for opening and saving
|
||||
the configuration.
|
||||
- The configuration utility now adds version macros to easily identify when an
|
||||
outdated configuration file is used with Reliance Edge or vice versa.
|
||||
|
||||
### Reliance Edge v1.0.4, July 2016
|
||||
|
||||
- Added ARM mbed and ARM mbed OS support in the commercial kit, with an example
|
||||
projects for ARM mbed OS on the NXP FRDM-K64F board.
|
||||
- Some minor deficiencies in the POSIX-like API test suite have been addressed.
|
||||
|
||||
### Reliance Edge v1.0.3, June 2016
|
||||
|
||||
- Added support for static memory allocation configuration in FreeRTOS
|
||||
version 9. No common code changes.
|
||||
|
||||
### Reliance Edge v1.0.2, February 2016
|
||||
|
||||
#### Common Code Changes
|
||||
- A new per-volume configuration option has been added: users can specify a
|
||||
number of times to retry a block device read, write or flush operation before
|
||||
returning a failure. The configuration tool has been updated to version 1.0.2
|
||||
with this change.
|
||||
- This added a new field to the volume configuration in redconf.c: existing
|
||||
redconf.c files from v1.0.1 and earlier must be updated to work with v1.0.2.
|
||||
Open redconf.h and redconf.c with the configuration tool, enable
|
||||
"Retry block device I/O on failure" for any volumes if desired, and save the
|
||||
redconf files.
|
||||
|
||||
#### FreeRTOS Port Changes
|
||||
- Added support for the STM32 HAL SD card driver in the FreeRTOS block device
|
||||
interface. Two boards are supported out-of-the-box: the STM324xG-EVAL and the
|
||||
STM32F746NG-Discovery. A sample project is included for the STM324xG-EVAL.
|
||||
|
||||
#### MQX Port Changes
|
||||
- Fixed a bug which prevented Reliance Edge from compiling if the File System
|
||||
Essentials API was selected in the configuration.
|
||||
- Fixed a bug which would have returned an uninitialized value from
|
||||
`RedOsBDevFlush()` for block devices that support flushing.
|
||||
|
||||
### Reliance Edge v1.0.1, October 2015
|
||||
|
||||
- Added MQX RTOS support in the commercial kit, with example projects for
|
||||
the Kinetis Design Studio.
|
||||
- Bug fix in the F_DRIVER implementation of the FreeRTOS block device service.
|
||||
|
||||
### Reliance Edge v1.0, July 2015
|
||||
|
||||
#### Common Code Changes
|
||||
|
||||
- First release of commercial kit and MISRA C:2012 Design Assurance Package.
|
||||
The commercial kit includes many new tools and tests which were not previously
|
||||
available.
|
||||
- Overhauled parsing of command-line parameters to be consistent for all tools
|
||||
and tests. Command-line tools now use Unix-style short and long options (such
|
||||
as `-H` and `--help`) instead of DOS-style switches (such as `/?`).
|
||||
- Renamed all os/\*/include/ostypes.h headers to os/\*/include/redostypes.h, so
|
||||
that all headers use the product prefix. If you created a port using v0.9,
|
||||
this header needs to be renamed and its header guard (#ifndef OSTYPES_H etc.)
|
||||
should also be updated.
|
||||
- Add a new header for OS-specific MISRA C:2012 deviation macros, located at
|
||||
os/\*/include/redosdeviations.h. If you created a port using v0.9, copy the
|
||||
template from os/stub/include/redosdeviations.h into the include directory.
|
||||
- Eliminated support for sector sizes less than 256. If using a smaller sector
|
||||
size (say for a RAM disk), this must now be emulated in the implementation of
|
||||
the block device OS service.
|
||||
- Added RedFseFormat() as an optional FSE API, allowing FSE applications to
|
||||
format the volume at run-time.
|
||||
- This added a new macro to redconf.h: existing redconf.h files from v0.9 must
|
||||
be updated to work with v1.0. Open redconf.h with the configuration tool,
|
||||
ignore the warning about the missing macro, and save it.
|
||||
- Internal restructuring has renamed the macros for the string and memory
|
||||
functions used in redconf.h. An existing redconf.h file from v0.9 will need
|
||||
to be updated; for a file containing the old names, the new config tool will
|
||||
default to using the (slow) Reliance Edge string/memory functions; to use the
|
||||
C library or custom versions, this will need to be selected in the
|
||||
configuration utility.
|
||||
- Fix a bug which would result in an error when attempting to create a name with
|
||||
one or more trailing path separators (such as `red_mkdir("/foo/bar/")`).
|
||||
- Fix a bug where an open handle for an inode on one volume would prevent the
|
||||
same inode number from being deleted on a different volume.
|
||||
|
||||
#### FreeRTOS Port Changes
|
||||
|
||||
- The implementation of the timestamp OS service no longer requires that
|
||||
`configUSE_TIMERS` be set to `1`.
|
||||
|
||||
### Reliance Edge v0.9 (Beta), April 2015
|
||||
|
||||
First public release.
|
||||
|
||||
## Known Issues
|
||||
|
||||
### Visual Studio 2005
|
||||
|
||||
The Reliance Edge Win32 port (used for the host tools and the Win32 test
|
||||
project) cannot be compiled by Visual Studio 2005. This is not going to be
|
||||
fixed since VS2005 is an old toolset. Newer versions of Visual Studio, starting
|
||||
with Visual Studio 2008, work just fine.
|
||||
|
@@ -0,0 +1,156 @@
|
||||
|
||||
|
||||
RELIANCE EDGE RELEASE NOTES
|
||||
|
||||
|
||||
This file contains a list of updates made to Reliance Edge over the
|
||||
course of recent releases and a list of known issues.
|
||||
|
||||
|
||||
Release History and Changes
|
||||
|
||||
Reliance Edge v2.0, January 2017
|
||||
|
||||
- Added support for Linux as a host environment
|
||||
- All "host" projects may now be built in either Windows or Linux
|
||||
using the make command. The formatter and image builder are built,
|
||||
and the checker and image copier are also built in the
|
||||
commercial kit.
|
||||
- An additional host tool has been added for Linux only: redfuse. It
|
||||
is a File System in User Space (FUSE) implementation, allowing a
|
||||
Reliance Edge volume to be mounted directly on Linux for
|
||||
easy access. It is built from the host project folder using the
|
||||
command make redfuse.
|
||||
- The OS-specific API test (commercial kit only) is now ported to run
|
||||
on Linux for the purpose of verifying the FUSE implementation.
|
||||
- Fixed a bug that could leave a directory in an invalid state after
|
||||
removing files. For example, an affected directory might report a
|
||||
non-zero length even after all files had been deleted.
|
||||
- Fixed a bug that would leave the driver in a bad state if a mount
|
||||
operation failed due to missing or corrupt metaroot blocks.
|
||||
|
||||
Reliance Edge v1.1 (Beta), November 2016
|
||||
|
||||
- Added support for a discard (trim) interface in the commercial kit.
|
||||
While discards are not integral to the behavior of the filesystem,
|
||||
they allow certain types of Flash drivers and media to perform at
|
||||
optimal speed and efficiency. The commercial version of Reliance
|
||||
Edge now allows the user to implement this interface for compatible
|
||||
storage media.
|
||||
- This change added new fields to the configuration files redconf.h
|
||||
and redconf.c. The configuration utility has been updated to version
|
||||
1.1 and existing configuration files must be updated using the
|
||||
updated utility.
|
||||
- The configuration utility now has keyboard shortcuts for opening and
|
||||
saving the configuration.
|
||||
- The configuration utility now adds version macros to easily identify
|
||||
when an outdated configuration file is used with Reliance Edge or
|
||||
vice versa.
|
||||
|
||||
Reliance Edge v1.0.4, July 2016
|
||||
|
||||
- Added ARM mbed and ARM mbed OS support in the commercial kit, with
|
||||
an example projects for ARM mbed OS on the NXP FRDM-K64F board.
|
||||
- Some minor deficiencies in the POSIX-like API test suite have
|
||||
been addressed.
|
||||
|
||||
Reliance Edge v1.0.3, June 2016
|
||||
|
||||
- Added support for static memory allocation configuration in FreeRTOS
|
||||
version 9. No common code changes.
|
||||
|
||||
Reliance Edge v1.0.2, February 2016
|
||||
|
||||
Common Code Changes
|
||||
|
||||
- A new per-volume configuration option has been added: users can
|
||||
specify a number of times to retry a block device read, write or
|
||||
flush operation before returning a failure. The configuration tool
|
||||
has been updated to version 1.0.2 with this change.
|
||||
- This added a new field to the volume configuration in redconf.c:
|
||||
existing redconf.c files from v1.0.1 and earlier must be updated to
|
||||
work with v1.0.2. Open redconf.h and redconf.c with the
|
||||
configuration tool, enable "Retry block device I/O on failure" for
|
||||
any volumes if desired, and save the redconf files.
|
||||
|
||||
FreeRTOS Port Changes
|
||||
|
||||
- Added support for the STM32 HAL SD card driver in the FreeRTOS block
|
||||
device interface. Two boards are supported out-of-the-box: the
|
||||
STM324xG-EVAL and the STM32F746NG-Discovery. A sample project is
|
||||
included for the STM324xG-EVAL.
|
||||
|
||||
MQX Port Changes
|
||||
|
||||
- Fixed a bug which prevented Reliance Edge from compiling if the File
|
||||
System Essentials API was selected in the configuration.
|
||||
- Fixed a bug which would have returned an uninitialized value from
|
||||
RedOsBDevFlush() for block devices that support flushing.
|
||||
|
||||
Reliance Edge v1.0.1, October 2015
|
||||
|
||||
- Added MQX RTOS support in the commercial kit, with example projects
|
||||
for the Kinetis Design Studio.
|
||||
- Bug fix in the F_DRIVER implementation of the FreeRTOS block
|
||||
device service.
|
||||
|
||||
Reliance Edge v1.0, July 2015
|
||||
|
||||
Common Code Changes
|
||||
|
||||
- First release of commercial kit and MISRA C:2012 Design
|
||||
Assurance Package. The commercial kit includes many new tools and
|
||||
tests which were not previously available.
|
||||
- Overhauled parsing of command-line parameters to be consistent for
|
||||
all tools and tests. Command-line tools now use Unix-style short and
|
||||
long options (such as -H and --help) instead of DOS-style switches
|
||||
(such as /?).
|
||||
- Renamed all os/*/include/ostypes.h headers to
|
||||
os/*/include/redostypes.h, so that all headers use the
|
||||
product prefix. If you created a port using v0.9, this header needs
|
||||
to be renamed and its header guard (#ifndef OSTYPES_H etc.) should
|
||||
also be updated.
|
||||
- Add a new header for OS-specific MISRA C:2012 deviation macros,
|
||||
located at os/*/include/redosdeviations.h. If you created a port
|
||||
using v0.9, copy the template from os/stub/include/redosdeviations.h
|
||||
into the include directory.
|
||||
- Eliminated support for sector sizes less than 256. If using a
|
||||
smaller sector size (say for a RAM disk), this must now be emulated
|
||||
in the implementation of the block device OS service.
|
||||
- Added RedFseFormat() as an optional FSE API, allowing FSE
|
||||
applications to format the volume at run-time.
|
||||
- This added a new macro to redconf.h: existing redconf.h files from
|
||||
v0.9 must be updated to work with v1.0. Open redconf.h with the
|
||||
configuration tool, ignore the warning about the missing macro, and
|
||||
save it.
|
||||
- Internal restructuring has renamed the macros for the string and
|
||||
memory functions used in redconf.h. An existing redconf.h file from
|
||||
v0.9 will need to be updated; for a file containing the old names,
|
||||
the new config tool will default to using the (slow) Reliance Edge
|
||||
string/memory functions; to use the C library or custom versions,
|
||||
this will need to be selected in the configuration utility.
|
||||
- Fix a bug which would result in an error when attempting to create a
|
||||
name with one or more trailing path separators (such as
|
||||
red_mkdir("/foo/bar/")).
|
||||
- Fix a bug where an open handle for an inode on one volume would
|
||||
prevent the same inode number from being deleted on a
|
||||
different volume.
|
||||
|
||||
FreeRTOS Port Changes
|
||||
|
||||
- The implementation of the timestamp OS service no longer requires
|
||||
that configUSE_TIMERS be set to 1.
|
||||
|
||||
Reliance Edge v0.9 (Beta), April 2015
|
||||
|
||||
First public release.
|
||||
|
||||
|
||||
Known Issues
|
||||
|
||||
Visual Studio 2005
|
||||
|
||||
The Reliance Edge Win32 port (used for the host tools and the Win32 test
|
||||
project) cannot be compiled by Visual Studio 2005. This is not going to
|
||||
be fixed since VS2005 is an old toolset. Newer versions of Visual
|
||||
Studio, starting with Visual Studio 2008, work just fine.
|
690
FreeRTOSv10.2.1/FreeRTOS-Plus/Source/Reliance-Edge/fse/fse.c
Normal file
690
FreeRTOSv10.2.1/FreeRTOS-Plus/Source/Reliance-Edge/fse/fse.c
Normal file
@@ -0,0 +1,690 @@
|
||||
/* ----> DO NOT REMOVE THE FOLLOWING NOTICE <----
|
||||
|
||||
Copyright (c) 2014-2015 Datalight, Inc.
|
||||
All Rights Reserved Worldwide.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; use version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but "AS-IS," WITHOUT ANY WARRANTY; without even the implied warranty
|
||||
of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
/* Businesses and individuals that for commercial or other reasons cannot
|
||||
comply with the terms of the GPLv2 license may obtain a commercial license
|
||||
before incorporating Reliance Edge into proprietary software for
|
||||
distribution in any form. Visit http://www.datalight.com/reliance-edge for
|
||||
more information.
|
||||
*/
|
||||
/** @file
|
||||
@brief Implementation of the Reliance Edge FSE API.
|
||||
*/
|
||||
#include <redfs.h>
|
||||
|
||||
#if REDCONF_API_FSE == 1
|
||||
|
||||
/** @defgroup red_group_fse The File System Essentials Interface
|
||||
@{
|
||||
*/
|
||||
|
||||
#include <redvolume.h>
|
||||
#include <redcoreapi.h>
|
||||
#include <redfse.h>
|
||||
|
||||
|
||||
static REDSTATUS FseEnter(uint8_t bVolNum);
|
||||
static void FseLeave(void);
|
||||
|
||||
|
||||
static bool gfFseInited; /* Whether driver is initialized. */
|
||||
|
||||
|
||||
/** @brief Initialize the Reliance Edge file system driver.
|
||||
|
||||
Prepares the Reliance Edge file system driver to be used. Must be the first
|
||||
Reliance Edge function to be invoked: no volumes can be mounted until the
|
||||
driver has been initialized.
|
||||
|
||||
If this function is called when the Reliance Edge driver is already
|
||||
initialized, it does nothing and returns success.
|
||||
|
||||
This function is not thread safe: attempting to initialize from multiple
|
||||
threads could leave things in a bad state.
|
||||
|
||||
@return A negated ::REDSTATUS code indicating the operation result.
|
||||
|
||||
@retval 0 Operation was successful.
|
||||
*/
|
||||
REDSTATUS RedFseInit(void)
|
||||
{
|
||||
REDSTATUS ret;
|
||||
|
||||
if(gfFseInited)
|
||||
{
|
||||
ret = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = RedCoreInit();
|
||||
|
||||
if(ret == 0)
|
||||
{
|
||||
gfFseInited = true;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/** @brief Uninitialize the Reliance Edge file system driver.
|
||||
|
||||
Tears down the Reliance Edge file system driver. Cannot be used until all
|
||||
Reliance Edge volumes are unmounted. A subsequent call to RedFseInit()
|
||||
will initialize the driver again.
|
||||
|
||||
If this function is called when the Reliance Edge driver is already
|
||||
uninitialized, it does nothing and returns success.
|
||||
|
||||
This function is not thread safe: attempting to uninitialize from multiple
|
||||
threads could leave things in a bad state.
|
||||
|
||||
@return A negated ::REDSTATUS code indicating the operation result.
|
||||
|
||||
@retval 0 Operation was successful.
|
||||
@retval -RED_EBUSY At least one volume is still mounted.
|
||||
*/
|
||||
REDSTATUS RedFseUninit(void)
|
||||
{
|
||||
REDSTATUS ret = 0;
|
||||
|
||||
if(!gfFseInited)
|
||||
{
|
||||
ret = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
uint8_t bVolNum;
|
||||
|
||||
#if REDCONF_TASK_COUNT > 1U
|
||||
RedOsMutexAcquire();
|
||||
#endif
|
||||
|
||||
for(bVolNum = 0U; bVolNum < REDCONF_VOLUME_COUNT; bVolNum++)
|
||||
{
|
||||
if(gaRedVolume[bVolNum].fMounted)
|
||||
{
|
||||
ret = -RED_EBUSY;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(ret == 0)
|
||||
{
|
||||
gfFseInited = false;
|
||||
}
|
||||
|
||||
#if REDCONF_TASK_COUNT > 1U
|
||||
RedOsMutexRelease();
|
||||
#endif
|
||||
|
||||
if(ret == 0)
|
||||
{
|
||||
ret = RedCoreUninit();
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/** @brief Mount a file system volume.
|
||||
|
||||
Prepares the file system volume to be accessed. Mount will fail if the
|
||||
volume has never been formatted, or if the on-disk format is inconsistent
|
||||
with the compile-time configuration.
|
||||
|
||||
If the volume is already mounted, this function does nothing and returns
|
||||
success.
|
||||
|
||||
@param bVolNum The volume number of the volume to be mounted.
|
||||
|
||||
@return A negated ::REDSTATUS code indicating the operation result.
|
||||
|
||||
@retval 0 Operation was successful.
|
||||
@retval -RED_EINVAL @p bVolNum is an invalid volume number; or the driver is
|
||||
uninitialized.
|
||||
@retval -RED_EIO Volume not formatted, improperly formatted, or corrupt.
|
||||
*/
|
||||
REDSTATUS RedFseMount(
|
||||
uint8_t bVolNum)
|
||||
{
|
||||
REDSTATUS ret;
|
||||
|
||||
ret = FseEnter(bVolNum);
|
||||
|
||||
if(ret == 0)
|
||||
{
|
||||
if(!gpRedVolume->fMounted)
|
||||
{
|
||||
ret = RedCoreVolMount();
|
||||
}
|
||||
|
||||
FseLeave();
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/** @brief Unmount a file system volume.
|
||||
|
||||
This function discards the in-memory state for the file system and marks it
|
||||
as unmounted. Subsequent attempts to access the volume will fail until the
|
||||
volume is mounted again.
|
||||
|
||||
If unmount automatic transaction points are enabled, this function will
|
||||
commit a transaction point prior to unmounting. If unmount automatic
|
||||
transaction points are disabled, this function will unmount without
|
||||
transacting, effectively discarding the working state.
|
||||
|
||||
Before unmounting, this function will wait for any active file system
|
||||
thread to complete by acquiring the FS mutex. The volume will be marked as
|
||||
unmounted before the FS mutex is released, so subsequent FS threads will
|
||||
possibly block and then see an error when attempting to access a volume
|
||||
which is unmounting or unmounted.
|
||||
|
||||
If the volume is already unmounted, this function does nothing and returns
|
||||
success.
|
||||
|
||||
@param bVolNum The volume number of the volume to be unmounted.
|
||||
|
||||
@return A negated ::REDSTATUS code indicating the operation result.
|
||||
|
||||
@retval 0 Operation was successful.
|
||||
@retval -RED_EINVAL @p bVolNum is an invalid volume number; or the driver is
|
||||
uninitialized.
|
||||
@retval -RED_EIO I/O error during unmount automatic transaction point.
|
||||
*/
|
||||
REDSTATUS RedFseUnmount(
|
||||
uint8_t bVolNum)
|
||||
{
|
||||
REDSTATUS ret;
|
||||
|
||||
ret = FseEnter(bVolNum);
|
||||
|
||||
if(ret == 0)
|
||||
{
|
||||
if(gpRedVolume->fMounted)
|
||||
{
|
||||
ret = RedCoreVolUnmount();
|
||||
}
|
||||
|
||||
FseLeave();
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
#if (REDCONF_READ_ONLY == 0) && (REDCONF_API_FSE_FORMAT == 1)
|
||||
/** @brief Format a file system volume.
|
||||
|
||||
Uses the statically defined volume configuration. After calling this
|
||||
function, the volume needs to be mounted -- see RedFseMount().
|
||||
|
||||
An error is returned if the volume is mounted.
|
||||
|
||||
@param bVolNum The volume number of the volume to be formatted.
|
||||
|
||||
@return A negated ::REDSTATUS code indicating the operation result.
|
||||
|
||||
@retval 0 Operation was successful.
|
||||
@retval -RED_EBUSY The volume is mounted.
|
||||
@retval -RED_EINVAL @p bVolNum is an invalid volume number; or the driver is
|
||||
uninitialized.
|
||||
@retval -RED_EIO I/O error formatting the volume.
|
||||
*/
|
||||
REDSTATUS RedFseFormat(
|
||||
uint8_t bVolNum)
|
||||
{
|
||||
REDSTATUS ret;
|
||||
|
||||
ret = FseEnter(bVolNum);
|
||||
|
||||
if(ret == 0)
|
||||
{
|
||||
ret = RedCoreVolFormat();
|
||||
|
||||
FseLeave();
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/** @brief Read from a file.
|
||||
|
||||
Data which has not yet been written, but which is before the end-of-file
|
||||
(sparse data), shall read as zeroes. A short read -- where the number of
|
||||
bytes read is less than requested -- indicates that the requested read was
|
||||
partially or, if zero bytes were read, entirely beyond the end-of-file.
|
||||
|
||||
If @p ullFileOffset is at or beyond the maximum file size, it is treated
|
||||
like any other read entirely beyond the end-of-file: no data is read and
|
||||
zero is returned.
|
||||
|
||||
@param bVolNum The volume number of the file to read.
|
||||
@param ulFileNum The file number of the file to read.
|
||||
@param ullFileOffset The file offset to read from.
|
||||
@param ulLength The number of bytes to read.
|
||||
@param pBuffer The buffer to populate with the data read. Must be
|
||||
at least ulLength bytes in size.
|
||||
|
||||
@return The number of bytes read (nonnegative) or a negated ::REDSTATUS
|
||||
code indicating the operation result (negative).
|
||||
|
||||
@retval >=0 The number of bytes read from the file.
|
||||
@retval -RED_EBADF @p ulFileNum is not a valid file number.
|
||||
@retval -RED_EINVAL @p bVolNum is an invalid volume number or not mounted;
|
||||
or @p pBuffer is `NULL`; or @p ulLength exceeds
|
||||
INT32_MAX and cannot be returned properly.
|
||||
@retval -RED_EIO A disk I/O error occurred.
|
||||
*/
|
||||
int32_t RedFseRead(
|
||||
uint8_t bVolNum,
|
||||
uint32_t ulFileNum,
|
||||
uint64_t ullFileOffset,
|
||||
uint32_t ulLength,
|
||||
void *pBuffer)
|
||||
{
|
||||
int32_t ret;
|
||||
|
||||
if(ulLength > (uint32_t)INT32_MAX)
|
||||
{
|
||||
ret = -RED_EINVAL;
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = FseEnter(bVolNum);
|
||||
}
|
||||
|
||||
if(ret == 0)
|
||||
{
|
||||
uint32_t ulReadLen = ulLength;
|
||||
|
||||
ret = RedCoreFileRead(ulFileNum, ullFileOffset, &ulReadLen, pBuffer);
|
||||
|
||||
FseLeave();
|
||||
|
||||
if(ret == 0)
|
||||
{
|
||||
ret = (int32_t)ulReadLen;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
#if REDCONF_READ_ONLY == 0
|
||||
/** @brief Write to a file.
|
||||
|
||||
If the write extends beyond the end-of-file, the file size will be
|
||||
increased.
|
||||
|
||||
A short write -- where the number of bytes written is less than requested
|
||||
-- indicates either that the file system ran out of space but was still
|
||||
able to write some of the request; or that the request would have caused
|
||||
the file to exceed the maximum file size, but some of the data could be
|
||||
written prior to the file size limit.
|
||||
|
||||
If an error is returned (negative return), either none of the data was
|
||||
written or a critical error occurred (like an I/O error) and the file
|
||||
system volume will be read-only.
|
||||
|
||||
@param bVolNum The volume number of the file to write.
|
||||
@param ulFileNum The file number of the file to write.
|
||||
@param ullFileOffset The file offset to write at.
|
||||
@param ulLength The number of bytes to write.
|
||||
@param pBuffer The buffer containing the data to be written. Must
|
||||
be at least ulLength bytes in size.
|
||||
|
||||
@return The number of bytes written (nonnegative) or a negated ::REDSTATUS
|
||||
code indicating the operation result (negative).
|
||||
|
||||
@retval >0 The number of bytes written to the file.
|
||||
@retval -RED_EBADF @p ulFileNum is not a valid file number.
|
||||
@retval -RED_EFBIG No data can be written to the given file offset since
|
||||
the resulting file size would exceed the maximum file
|
||||
size.
|
||||
@retval -RED_EINVAL @p bVolNum is an invalid volume number or not mounted;
|
||||
or @p pBuffer is `NULL`; or @p ulLength exceeds
|
||||
INT32_MAX and cannot be returned properly.
|
||||
@retval -RED_EIO A disk I/O error occurred.
|
||||
@retval -RED_ENOSPC No data can be written because there is insufficient
|
||||
free space.
|
||||
@retval -RED_EROFS The file system volume is read-only.
|
||||
*/
|
||||
int32_t RedFseWrite(
|
||||
uint8_t bVolNum,
|
||||
uint32_t ulFileNum,
|
||||
uint64_t ullFileOffset,
|
||||
uint32_t ulLength,
|
||||
const void *pBuffer)
|
||||
{
|
||||
int32_t ret;
|
||||
|
||||
if(ulLength > (uint32_t)INT32_MAX)
|
||||
{
|
||||
ret = -RED_EINVAL;
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = FseEnter(bVolNum);
|
||||
}
|
||||
|
||||
if(ret == 0)
|
||||
{
|
||||
uint32_t ulWriteLen = ulLength;
|
||||
|
||||
ret = RedCoreFileWrite(ulFileNum, ullFileOffset, &ulWriteLen, pBuffer);
|
||||
|
||||
FseLeave();
|
||||
|
||||
if(ret == 0)
|
||||
{
|
||||
ret = (int32_t)ulWriteLen;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#if (REDCONF_READ_ONLY == 0) && (REDCONF_API_FSE_TRUNCATE == 1)
|
||||
/** @brief Truncate a file (set the file size).
|
||||
|
||||
Allows the file size to be increased, decreased, or to remain the same. If
|
||||
the file size is increased, the new area is sparse (will read as zeroes).
|
||||
If the file size is decreased, the data beyond the new end-of-file will
|
||||
return to free space once it is no longer part of the committed state
|
||||
(either immediately or after the next transaction point).
|
||||
|
||||
This function can fail when the disk is full if @p ullNewFileSize is
|
||||
non-zero. If decreasing the file size, this can be fixed by transacting and
|
||||
trying again: Reliance Edge guarantees that it is possible to perform a
|
||||
truncate of at least one file that decreases the file size after a
|
||||
transaction point. If disk full transactions are enabled, this will happen
|
||||
automatically.
|
||||
|
||||
@param bVolNum The volume number of the file to truncate.
|
||||
@param ulFileNum The file number of the file to truncate.
|
||||
@param ullNewFileSize The new file size, in bytes.
|
||||
|
||||
@return A negated ::REDSTATUS code indicating the operation result.
|
||||
|
||||
@retval 0 Operation was successful.
|
||||
@retval -RED_EBADF @p ulFileNum is not a valid file number.
|
||||
@retval -RED_EFBIG @p ullNewFileSize exceeds the maximum file size.
|
||||
@retval -RED_EINVAL @p bVolNum is an invalid volume number or not mounted.
|
||||
@retval -RED_EIO A disk I/O error occurred.
|
||||
@retval -RED_ENOSPC Insufficient free space to perform the truncate.
|
||||
@retval -RED_EROFS The file system volume is read-only.
|
||||
*/
|
||||
REDSTATUS RedFseTruncate(
|
||||
uint8_t bVolNum,
|
||||
uint32_t ulFileNum,
|
||||
uint64_t ullNewFileSize)
|
||||
{
|
||||
REDSTATUS ret;
|
||||
|
||||
ret = FseEnter(bVolNum);
|
||||
|
||||
if(ret == 0)
|
||||
{
|
||||
ret = RedCoreFileTruncate(ulFileNum, ullNewFileSize);
|
||||
|
||||
FseLeave();
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/** @brief Retrieve the size of a file.
|
||||
|
||||
@param bVolNum The volume number of the file whose size is being read.
|
||||
@param ulFileNum The file number of the file whose size is being read.
|
||||
|
||||
@return The size of the file (nonnegative) or a negated ::REDSTATUS code
|
||||
indicating the operation result (negative).
|
||||
|
||||
@retval >=0 The size of the file.
|
||||
@retval -RED_EBADF @p ulFileNum is not a valid file number.
|
||||
@retval -RED_EINVAL @p bVolNum is an invalid volume number or not mounted.
|
||||
@retval -RED_EIO A disk I/O error occurred.
|
||||
*/
|
||||
int64_t RedFseSizeGet(
|
||||
uint8_t bVolNum,
|
||||
uint32_t ulFileNum)
|
||||
{
|
||||
int64_t ret;
|
||||
|
||||
ret = FseEnter(bVolNum);
|
||||
|
||||
if(ret == 0)
|
||||
{
|
||||
uint64_t ullSize;
|
||||
|
||||
ret = RedCoreFileSizeGet(ulFileNum, &ullSize);
|
||||
|
||||
FseLeave();
|
||||
|
||||
if(ret == 0)
|
||||
{
|
||||
/* Unless there is an on-disk format change, the maximum file size
|
||||
is guaranteed to be less than INT64_MAX, and so it can be safely
|
||||
returned in an int64_t.
|
||||
*/
|
||||
REDASSERT(ullSize < (uint64_t)INT64_MAX);
|
||||
|
||||
ret = (int64_t)ullSize;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
#if (REDCONF_READ_ONLY == 0) && (REDCONF_API_FSE_TRANSMASKSET == 1)
|
||||
/** @brief Update the transaction mask.
|
||||
|
||||
The following events are available:
|
||||
|
||||
- #RED_TRANSACT_UMOUNT
|
||||
- #RED_TRANSACT_WRITE
|
||||
- #RED_TRANSACT_TRUNCATE
|
||||
- #RED_TRANSACT_VOLFULL
|
||||
|
||||
The #RED_TRANSACT_MANUAL macro (by itself) may be used to disable all
|
||||
automatic transaction events. The #RED_TRANSACT_MASK macro is a bitmask of
|
||||
all transaction flags, excluding those representing excluded functionality.
|
||||
|
||||
Attempting to enable events for excluded functionality will result in an
|
||||
error.
|
||||
|
||||
@param bVolNum The volume number of the volume whose transaction mask
|
||||
is being changed.
|
||||
@param ulEventMask A bitwise-OR'd mask of automatic transaction events to
|
||||
be set as the current transaction mode.
|
||||
|
||||
@return A negated ::REDSTATUS code indicating the operation result.
|
||||
|
||||
@retval 0 Operation was successful.
|
||||
@retval -RED_EINVAL @p bVolNum is an invalid volume number or not mounted;
|
||||
or @p ulEventMask contains invalid bits.
|
||||
@retval -RED_EROFS The file system volume is read-only.
|
||||
*/
|
||||
REDSTATUS RedFseTransMaskSet(
|
||||
uint8_t bVolNum,
|
||||
uint32_t ulEventMask)
|
||||
{
|
||||
REDSTATUS ret;
|
||||
|
||||
ret = FseEnter(bVolNum);
|
||||
|
||||
if(ret == 0)
|
||||
{
|
||||
ret = RedCoreTransMaskSet(ulEventMask);
|
||||
|
||||
FseLeave();
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#if REDCONF_API_FSE_TRANSMASKGET == 1
|
||||
/** @brief Read the transaction mask.
|
||||
|
||||
If the volume is read-only, the returned event mask is always zero.
|
||||
|
||||
@param bVolNum The volume number of the volume whose transaction mask
|
||||
is being retrieved.
|
||||
@param pulEventMask Populated with a bitwise-OR'd mask of automatic
|
||||
transaction events which represent the current
|
||||
transaction mode for the volume.
|
||||
|
||||
@return A negated ::REDSTATUS code indicating the operation result.
|
||||
|
||||
@retval 0 Operation was successful.
|
||||
@retval -RED_EINVAL @p bVolNum is an invalid volume number or not mounted;
|
||||
or @p pulEventMask is `NULL`.
|
||||
*/
|
||||
REDSTATUS RedFseTransMaskGet(
|
||||
uint8_t bVolNum,
|
||||
uint32_t *pulEventMask)
|
||||
{
|
||||
REDSTATUS ret;
|
||||
|
||||
ret = FseEnter(bVolNum);
|
||||
|
||||
if(ret == 0)
|
||||
{
|
||||
ret = RedCoreTransMaskGet(pulEventMask);
|
||||
|
||||
FseLeave();
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#if REDCONF_READ_ONLY == 0
|
||||
/** @brief Commit a transaction point.
|
||||
|
||||
Reliance Edge is a transactional file system. All modifications, of both
|
||||
metadata and filedata, are initially working state. A transaction point
|
||||
is a process whereby the working state atomically becomes the committed
|
||||
state, replacing the previous committed state. Whenever Reliance Edge is
|
||||
mounted, including after power loss, the state of the file system after
|
||||
mount is the most recent committed state. Nothing from the committed
|
||||
state is ever missing, and nothing from the working state is ever included.
|
||||
|
||||
@param bVolNum The volume number of the volume to transact.
|
||||
|
||||
@return A negated ::REDSTATUS code indicating the operation result.
|
||||
|
||||
@retval 0 Operation was successful.
|
||||
@retval -RED_EINVAL @p bVolNum is an invalid volume number or not mounted.
|
||||
@retval -RED_EIO A disk I/O error occurred.
|
||||
@retval -RED_EROFS The file system volume is read-only.
|
||||
*/
|
||||
REDSTATUS RedFseTransact(
|
||||
uint8_t bVolNum)
|
||||
{
|
||||
REDSTATUS ret;
|
||||
|
||||
ret = FseEnter(bVolNum);
|
||||
|
||||
if(ret == 0)
|
||||
{
|
||||
ret = RedCoreVolTransact();
|
||||
|
||||
FseLeave();
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
/** @} */
|
||||
|
||||
/** @brief Enter the file system driver.
|
||||
|
||||
@param bVolNum The volume to be accessed.
|
||||
|
||||
@return A negated ::REDSTATUS code indicating the operation result.
|
||||
|
||||
@retval 0 Operation was successful.
|
||||
@retval -RED_EINVAL The file system driver is uninitialized; or @p bVolNum
|
||||
is not a valid volume number.
|
||||
*/
|
||||
static REDSTATUS FseEnter(
|
||||
uint8_t bVolNum)
|
||||
{
|
||||
REDSTATUS ret;
|
||||
|
||||
if(gfFseInited)
|
||||
{
|
||||
#if REDCONF_TASK_COUNT > 1U
|
||||
RedOsMutexAcquire();
|
||||
#endif
|
||||
|
||||
/* This also serves to range-check the volume number (even in single
|
||||
volume configurations).
|
||||
*/
|
||||
ret = RedCoreVolSetCurrent(bVolNum);
|
||||
|
||||
#if REDCONF_TASK_COUNT > 1U
|
||||
if(ret != 0)
|
||||
{
|
||||
RedOsMutexRelease();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = -RED_EINVAL;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/** @brief Leave the file system driver.
|
||||
*/
|
||||
static void FseLeave(void)
|
||||
{
|
||||
REDASSERT(gfFseInited);
|
||||
|
||||
#if REDCONF_TASK_COUNT > 1U
|
||||
RedOsMutexRelease();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
#endif /* REDCONF_API_FSE == 1 */
|
||||
|
@@ -0,0 +1,112 @@
|
||||
/* ----> DO NOT REMOVE THE FOLLOWING NOTICE <----
|
||||
|
||||
Copyright (c) 2014-2015 Datalight, Inc.
|
||||
All Rights Reserved Worldwide.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; use version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but "AS-IS," WITHOUT ANY WARRANTY; without even the implied warranty
|
||||
of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
/* Businesses and individuals that for commercial or other reasons cannot
|
||||
comply with the terms of the GPLv2 license may obtain a commercial license
|
||||
before incorporating Reliance Edge into proprietary software for
|
||||
distribution in any form. Visit http://www.datalight.com/reliance-edge for
|
||||
more information.
|
||||
*/
|
||||
/** @file
|
||||
@brief Defines macros used to interact with the Reliance Edge API.
|
||||
*/
|
||||
#ifndef REDAPIMACS_H
|
||||
#define REDAPIMACS_H
|
||||
|
||||
|
||||
/** Clear all events: manual transactions only. */
|
||||
#define RED_TRANSACT_MANUAL 0x00000000U
|
||||
|
||||
/** Transact prior to unmounting in red_umount() or RedFseUnmount(). */
|
||||
#define RED_TRANSACT_UMOUNT 0x00000001U
|
||||
|
||||
/** Transact after a successful red_open() which created a file. */
|
||||
#define RED_TRANSACT_CREAT 0x00000002U
|
||||
|
||||
/** Transact after a successful red_unlink() or red_rmdir(). */
|
||||
#define RED_TRANSACT_UNLINK 0x00000004U
|
||||
|
||||
/** Transact after a successful red_mkdir(). */
|
||||
#define RED_TRANSACT_MKDIR 0x00000008U
|
||||
|
||||
/** Transact after a successful red_rename(). */
|
||||
#define RED_TRANSACT_RENAME 0x00000010U
|
||||
|
||||
/** Transact after a successful red_link(). */
|
||||
#define RED_TRANSACT_LINK 0x00000020U
|
||||
|
||||
/** Transact after a successful red_close(). */
|
||||
#define RED_TRANSACT_CLOSE 0x00000040U
|
||||
|
||||
/** Transact after a successful red_write() or RedFseWrite(). */
|
||||
#define RED_TRANSACT_WRITE 0x00000080U
|
||||
|
||||
/** Transact after a successful red_fsync(). */
|
||||
#define RED_TRANSACT_FSYNC 0x00000100U
|
||||
|
||||
/** Transact after a successful red_ftruncate(), RedFseTruncate(), or red_open() with RED_O_TRUNC that actually truncates. */
|
||||
#define RED_TRANSACT_TRUNCATE 0x00000200U
|
||||
|
||||
/** Transact to free space in disk full situations. */
|
||||
#define RED_TRANSACT_VOLFULL 0x00000400U
|
||||
|
||||
#if REDCONF_READ_ONLY == 1
|
||||
|
||||
/** Mask of all supported automatic transaction events. */
|
||||
#define RED_TRANSACT_MASK 0U
|
||||
|
||||
#elif REDCONF_API_POSIX == 1
|
||||
|
||||
/** @brief Mask of all supported automatic transaction events.
|
||||
*/
|
||||
#define RED_TRANSACT_MASK \
|
||||
( \
|
||||
RED_TRANSACT_UMOUNT | \
|
||||
RED_TRANSACT_CREAT | \
|
||||
((REDCONF_API_POSIX_UNLINK == 1) ? RED_TRANSACT_UNLINK : 0U) | \
|
||||
((REDCONF_API_POSIX_MKDIR == 1) ? RED_TRANSACT_MKDIR : 0U) | \
|
||||
((REDCONF_API_POSIX_RENAME == 1) ? RED_TRANSACT_RENAME : 0U) | \
|
||||
((REDCONF_API_POSIX_LINK == 1) ? RED_TRANSACT_LINK : 0U) | \
|
||||
RED_TRANSACT_CLOSE | \
|
||||
RED_TRANSACT_WRITE | \
|
||||
RED_TRANSACT_FSYNC | \
|
||||
((REDCONF_API_POSIX_FTRUNCATE == 1) ? RED_TRANSACT_TRUNCATE : 0U) | \
|
||||
RED_TRANSACT_VOLFULL \
|
||||
)
|
||||
|
||||
#else /* REDCONF_API_FSE == 1 */
|
||||
|
||||
/** @brief Mask of all supported automatic transaction events.
|
||||
*/
|
||||
#define RED_TRANSACT_MASK \
|
||||
( \
|
||||
RED_TRANSACT_UMOUNT | \
|
||||
RED_TRANSACT_WRITE | \
|
||||
((REDCONF_API_FSE_TRUNCATE == 1) ? RED_TRANSACT_TRUNCATE : 0U) | \
|
||||
RED_TRANSACT_VOLFULL \
|
||||
)
|
||||
|
||||
#endif /* REDCONF_READ_ONLY */
|
||||
|
||||
#if (REDCONF_TRANSACT_DEFAULT & RED_TRANSACT_MASK) != REDCONF_TRANSACT_DEFAULT
|
||||
#error "Configuration error: invalid value of REDCONF_TRANSACT_DEFAULT"
|
||||
#endif
|
||||
|
||||
|
||||
#endif
|
||||
|
@@ -0,0 +1,349 @@
|
||||
/* ----> DO NOT REMOVE THE FOLLOWING NOTICE <----
|
||||
|
||||
Copyright (c) 2014-2015 Datalight, Inc.
|
||||
All Rights Reserved Worldwide.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; use version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but "AS-IS," WITHOUT ANY WARRANTY; without even the implied warranty
|
||||
of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
/* Businesses and individuals that for commercial or other reasons cannot
|
||||
comply with the terms of the GPLv2 license may obtain a commercial license
|
||||
before incorporating Reliance Edge into proprietary software for
|
||||
distribution in any form. Visit http://www.datalight.com/reliance-edge for
|
||||
more information.
|
||||
*/
|
||||
/** @file
|
||||
@brief Compile-time validity checks for the REDCONF macros.
|
||||
*/
|
||||
#ifndef REDCONFIGCHK_H
|
||||
#define REDCONFIGCHK_H
|
||||
|
||||
#ifdef RED_CONFIG_MINCOMPAT_VER
|
||||
#if (RED_VERSION_VAL & 0xFFFFFF00U) < (RED_CONFIG_MINCOMPAT_VER & 0xFFFFFF00U)
|
||||
/* This indicates that your configuration files were generated by a
|
||||
version of the Reliance Edge Configuration Utility that is designed
|
||||
for a more recent version of Reliance Edge and is no longer compatible
|
||||
with this version. You can update to the most recent version of
|
||||
Reliance Edge or contact RelianceEdgeSupport@datalight.com to obtain
|
||||
the correct legacy version of the Configuration Utility.
|
||||
*/
|
||||
#error "Your configuration is not compatible with this version of Reliance Edge. Please download the latest version of Reliance Edge or recreate your configuration with an older version of the Configuration Utility."
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef REDCONF_READ_ONLY
|
||||
#error "Configuration error: REDCONF_READ_ONLY must be defined."
|
||||
#endif
|
||||
#ifndef REDCONF_API_POSIX
|
||||
#error "Configuration error: REDCONF_API_POSIX must be defined."
|
||||
#endif
|
||||
#ifndef REDCONF_API_FSE
|
||||
#error "Configuration error: REDCONF_API_FSE must be defined."
|
||||
#endif
|
||||
|
||||
#if REDCONF_API_POSIX == 1
|
||||
#ifndef REDCONF_API_POSIX_FORMAT
|
||||
#error "Configuration error: REDCONF_API_POSIX_FORMAT must be defined."
|
||||
#endif
|
||||
#ifndef REDCONF_API_POSIX_UNLINK
|
||||
#error "Configuration error: REDCONF_API_POSIX_UNLINK must be defined."
|
||||
#endif
|
||||
#ifndef REDCONF_API_POSIX_MKDIR
|
||||
#error "Configuration error: REDCONF_API_POSIX_MKDIR must be defined."
|
||||
#endif
|
||||
#ifndef REDCONF_API_POSIX_RMDIR
|
||||
#error "Configuration error: REDCONF_API_POSIX_RMDIR must be defined."
|
||||
#endif
|
||||
#ifndef REDCONF_API_POSIX_RENAME
|
||||
#error "Configuration error: REDCONF_API_POSIX_RENAME must be defined."
|
||||
#endif
|
||||
#ifndef REDCONF_API_POSIX_LINK
|
||||
#error "Configuration error: REDCONF_API_POSIX_LINK must be defined."
|
||||
#endif
|
||||
#ifndef REDCONF_API_POSIX_FTRUNCATE
|
||||
#error "Configuration error: REDCONF_API_POSIX_FTRUNCATE must be defined."
|
||||
#endif
|
||||
#ifndef REDCONF_API_POSIX_READDIR
|
||||
#error "Configuration error: REDCONF_API_POSIX_READDIR must be defined."
|
||||
#endif
|
||||
#ifndef REDCONF_NAME_MAX
|
||||
#error "Configuration error: REDCONF_NAME_MAX must be defined."
|
||||
#endif
|
||||
#ifndef REDCONF_PATH_SEPARATOR
|
||||
#error "Configuration error: REDCONF_PATH_SEPARATOR must be defined."
|
||||
#endif
|
||||
#ifndef REDCONF_RENAME_ATOMIC
|
||||
#error "Configuration error: REDCONF_RENAME_ATOMIC must be defined."
|
||||
#endif
|
||||
#ifndef REDCONF_HANDLE_COUNT
|
||||
#error "Configuration error: REDCONF_HANDLE_COUNT must be defined."
|
||||
#endif
|
||||
#endif
|
||||
#if REDCONF_API_FSE == 1
|
||||
#ifndef REDCONF_API_FSE_FORMAT
|
||||
#error "Configuration error: REDCONF_API_FSE_FORMAT must be defined."
|
||||
#endif
|
||||
#ifndef REDCONF_API_FSE_TRUNCATE
|
||||
#error "Configuration error: REDCONF_API_FSE_TRUNCATE must be defined."
|
||||
#endif
|
||||
#ifndef REDCONF_API_FSE_TRANSMASKSET
|
||||
#error "Configuration error: REDCONF_API_FSE_TRANSMASKSET must be defined."
|
||||
#endif
|
||||
#ifndef REDCONF_API_FSE_TRANSMASKGET
|
||||
#error "Configuration error: REDCONF_API_FSE_TRANSMASKGET must be defined."
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef REDCONF_TASK_COUNT
|
||||
#error "Configuration error: REDCONF_TASK_COUNT must be defined."
|
||||
#endif
|
||||
#ifndef REDCONF_ENDIAN_BIG
|
||||
#error "Configuration error: REDCONF_ENDIAN_BIG must be defined."
|
||||
#endif
|
||||
#ifndef REDCONF_ALIGNMENT_SIZE
|
||||
#error "Configuration error: REDCONF_ALIGNMENT_SIZE must be defined."
|
||||
#endif
|
||||
#ifndef REDCONF_CRC_ALGORITHM
|
||||
#error "Configuration error: REDCONF_CRC_ALGORITHM must be defined."
|
||||
#endif
|
||||
#ifndef REDCONF_INODE_TIMESTAMPS
|
||||
#error "Configuration error: REDCONF_INODE_TIMESTAMPS must be defined."
|
||||
#endif
|
||||
#ifndef REDCONF_ATIME
|
||||
#error "Configuration error: REDCONF_ATIME must be defined."
|
||||
#endif
|
||||
#ifndef REDCONF_DIRECT_POINTERS
|
||||
#error "Configuration error: REDCONF_DIRECT_POINTERS must be defined."
|
||||
#endif
|
||||
#ifndef REDCONF_INDIRECT_POINTERS
|
||||
#error "Configuration error: REDCONF_INDIRECT_POINTERS must be defined."
|
||||
#endif
|
||||
#ifndef REDCONF_INODE_BLOCKS
|
||||
#error "Configuration error: REDCONF_INODE_BLOCKS must be defined."
|
||||
#endif
|
||||
#ifndef REDCONF_IMAP_EXTERNAL
|
||||
#error "Configuration error: REDCONF_IMAP_EXTERNAL must be defined."
|
||||
#endif
|
||||
#ifndef REDCONF_IMAP_INLINE
|
||||
#error "Configuration error: REDCONF_IMAP_INLINE must be defined."
|
||||
#endif
|
||||
#ifndef REDCONF_OUTPUT
|
||||
#error "Configuration error: REDCONF_OUTPUT must be defined."
|
||||
#endif
|
||||
#ifndef REDCONF_ASSERTS
|
||||
#error "Configuration error: REDCONF_ASSERTS must be defined."
|
||||
#endif
|
||||
#ifndef REDCONF_TRANSACT_DEFAULT
|
||||
#error "Configuration error: REDCONF_TRANSACT_DEFAULT must be defined."
|
||||
#endif
|
||||
#ifndef REDCONF_BUFFER_COUNT
|
||||
#error "Configuration error: REDCONF_BUFFER_COUNT must be defined."
|
||||
#endif
|
||||
#ifndef REDCONF_BLOCK_SIZE
|
||||
#error "Configuration error: REDCONF_BLOCK_SIZE must be defined."
|
||||
#endif
|
||||
#ifndef REDCONF_VOLUME_COUNT
|
||||
#error "Configuration error: REDCONF_VOLUME_COUNT must be defined."
|
||||
#endif
|
||||
#ifndef REDCONF_DISCARDS
|
||||
/* Reliance Edge 1.0.5 and below did not have REDCONF_DISCARDS. You can
|
||||
fix this error by downloading the latest version of the Configuration
|
||||
Utility (assuming you are using the latest version of Reliance Edge)
|
||||
from http://www.datalight.com/reliance-edge, loading your redconf.c
|
||||
and redconf.h files, and saving them again, replacing the original
|
||||
files.
|
||||
*/
|
||||
#error "Configuration error: your redconf.h is not compatible. Update your redconf files with a compatible version of the configuration utility."
|
||||
#endif
|
||||
#ifndef REDCONF_IMAGE_BUILDER
|
||||
#error "Configuration error: REDCONF_IMAGE_BUILDER must be defined."
|
||||
#endif
|
||||
#ifndef REDCONF_CHECKER
|
||||
#error "Configuration error: REDCONF_CHECKER must be defined."
|
||||
#endif
|
||||
|
||||
|
||||
#if (REDCONF_READ_ONLY != 0) && (REDCONF_READ_ONLY != 1)
|
||||
#error "Configuration error: REDCONF_READ_ONLY must be either 0 or 1"
|
||||
#endif
|
||||
|
||||
#if (REDCONF_API_POSIX != 0) && (REDCONF_API_POSIX != 1)
|
||||
#error "Configuration error: REDCONF_API_POSIX must be either 0 or 1."
|
||||
#endif
|
||||
#if (REDCONF_API_FSE != 0) && (REDCONF_API_FSE != 1)
|
||||
#error "Configuration error: REDCONF_API_FSE must be either 0 or 1."
|
||||
#endif
|
||||
|
||||
#if (REDCONF_API_FSE == 0) && (REDCONF_API_POSIX == 0)
|
||||
#error "Configuration error: either REDCONF_API_FSE or REDCONF_API_POSIX must be set to 1."
|
||||
#endif
|
||||
|
||||
#if REDCONF_API_POSIX == 1
|
||||
#if REDCONF_API_FSE != 0
|
||||
#error "Configuration error: REDCONF_API_FSE must be 0 if REDCONF_API_POSIX is 1"
|
||||
#endif
|
||||
|
||||
#if (REDCONF_API_POSIX_FORMAT != 0) && (REDCONF_API_POSIX_FORMAT != 1)
|
||||
#error "Configuration error: REDCONF_API_POSIX_FORMAT must be either 0 or 1."
|
||||
#endif
|
||||
|
||||
#if (REDCONF_API_POSIX_UNLINK != 0) && (REDCONF_API_POSIX_UNLINK != 1)
|
||||
#error "Configuration error: REDCONF_API_POSIX_UNLINK must be either 0 or 1."
|
||||
#endif
|
||||
|
||||
#if (REDCONF_API_POSIX_MKDIR != 0) && (REDCONF_API_POSIX_MKDIR != 1)
|
||||
#error "Configuration error: REDCONF_API_POSIX_MKDIR must be either 0 or 1."
|
||||
#endif
|
||||
|
||||
#if (REDCONF_API_POSIX_RMDIR != 0) && (REDCONF_API_POSIX_RMDIR != 1)
|
||||
#error "Configuration error: REDCONF_API_POSIX_RMDIR must be either 0 or 1."
|
||||
#endif
|
||||
|
||||
#if (REDCONF_API_POSIX_RENAME != 0) && (REDCONF_API_POSIX_RENAME != 1)
|
||||
#error "Configuration error: REDCONF_API_POSIX_RENAME must be either 0 or 1."
|
||||
#endif
|
||||
|
||||
#if (REDCONF_API_POSIX_LINK != 0) && (REDCONF_API_POSIX_LINK != 1)
|
||||
#error "Configuration error: REDCONF_API_POSIX_LINK must be either 0 or 1."
|
||||
#endif
|
||||
|
||||
#if (REDCONF_API_POSIX_FTRUNCATE != 0) && (REDCONF_API_POSIX_FTRUNCATE != 1)
|
||||
#error "Configuration error: REDCONF_API_POSIX_FTRUNCATE must be either 0 or 1."
|
||||
#endif
|
||||
|
||||
#if (REDCONF_API_POSIX_READDIR != 0) && (REDCONF_API_POSIX_READDIR != 1)
|
||||
#error "Configuration error: REDCONF_API_POSIX_READDIR must be either 0 or 1."
|
||||
#endif
|
||||
|
||||
#if (REDCONF_NAME_MAX < 1U) || (REDCONF_NAME_MAX > (REDCONF_BLOCK_SIZE - 4U))
|
||||
#error "Configuration error: invalid value of REDCONF_NAME_MAX"
|
||||
#endif
|
||||
|
||||
#if (REDCONF_PATH_SEPARATOR < 1) || (REDCONF_PATH_SEPARATOR > 127)
|
||||
#error "Configuration error: invalid value of REDCONF_PATH_SEPARATOR"
|
||||
#endif
|
||||
|
||||
#if (REDCONF_RENAME_ATOMIC != 0) && (REDCONF_RENAME_ATOMIC != 1)
|
||||
#error "Configuration error: REDCONF_RENAME_ATOMIC must be either 0 or 1."
|
||||
#endif
|
||||
|
||||
#if (REDCONF_HANDLE_COUNT < 1U) || (REDCONF_HANDLE_COUNT > 4096U)
|
||||
#error "Configuration error: invalid value of REDCONF_HANDLE_COUNT"
|
||||
#endif
|
||||
#endif
|
||||
#if REDCONF_API_FSE == 1
|
||||
#if (REDCONF_API_FSE_FORMAT != 0) && (REDCONF_API_FSE_FORMAT != 1)
|
||||
#error "Configuration error: REDCONF_API_FSE_FORMAT must be either 0 or 1."
|
||||
#endif
|
||||
|
||||
#if (REDCONF_API_FSE_TRUNCATE != 0) && (REDCONF_API_FSE_TRUNCATE != 1)
|
||||
#error "Configuration error: REDCONF_API_FSE_TRUNCATE must be either 0 or 1."
|
||||
#endif
|
||||
|
||||
#if (REDCONF_API_FSE_TRANSMASKSET != 0) && (REDCONF_API_FSE_TRANSMASKSET != 1)
|
||||
#error "Configuration error: REDCONF_API_FSE_TRANSMASKSET must be either 0 or 1."
|
||||
#endif
|
||||
|
||||
#if (REDCONF_API_FSE_TRANSMASKGET != 0) && (REDCONF_API_FSE_TRANSMASKGET != 1)
|
||||
#error "Configuration error: REDCONF_API_FSE_TRANSMASKGET must be either 0 or 1."
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if REDCONF_TASK_COUNT < 1U
|
||||
#error "Configuration error: invalid value of REDCONF_TASK_COUNT"
|
||||
#endif
|
||||
|
||||
#if (REDCONF_ENDIAN_BIG != 0) && (REDCONF_ENDIAN_BIG != 1)
|
||||
#error "Configuration error: REDCONF_ENDIAN_BIG must be either 0 or 1."
|
||||
#endif
|
||||
|
||||
#if (REDCONF_ALIGNMENT_SIZE != 1U) && (REDCONF_ALIGNMENT_SIZE != 2U) && (REDCONF_ALIGNMENT_SIZE != 4U) && (REDCONF_ALIGNMENT_SIZE != 8U)
|
||||
#error "Configuration error: invalid value REDCONF_ALIGNMENT_SIZE"
|
||||
#endif
|
||||
|
||||
/* REDCONF_CRC_ALGORITHM checked in crc.c
|
||||
*/
|
||||
|
||||
#if (REDCONF_INODE_TIMESTAMPS != 0) && (REDCONF_INODE_TIMESTAMPS != 1)
|
||||
#error "Configuration error: REDCONF_INODE_TIMESTAMPS must be either 0 or 1."
|
||||
#endif
|
||||
|
||||
#if (REDCONF_ATIME != 0) && (REDCONF_ATIME != 1)
|
||||
#error "Configuration error: REDCONF_ATIME must be either 0 or 1."
|
||||
#endif
|
||||
|
||||
#if (REDCONF_INODE_TIMESTAMPS == 0) && (REDCONF_ATIME == 1)
|
||||
#error "Configuration error: REDCONF_ATIME must be 0 when REDCONF_INODE_TIMESTAMPS is 0."
|
||||
#endif
|
||||
|
||||
/* REDCONF_DIRECT_POINTERS and REDCONF_INDIRECT_POINTERS checked in rednodes.h
|
||||
*/
|
||||
|
||||
#if (REDCONF_INODE_BLOCKS != 0) && (REDCONF_INODE_BLOCKS != 1)
|
||||
#error "Configuration error: REDCONF_INODE_BLOCKS must be either 0 or 1."
|
||||
#endif
|
||||
|
||||
/* Further validity checking of imap specs done in RelCoreInit()
|
||||
*/
|
||||
#if (REDCONF_IMAP_EXTERNAL != 0) && (REDCONF_IMAP_EXTERNAL != 1)
|
||||
#error "Configuration error: REDCONF_IMAP_EXTERNAL must be either 0 or 1."
|
||||
#endif
|
||||
#if (REDCONF_IMAP_INLINE != 0) && (REDCONF_IMAP_INLINE != 1)
|
||||
#error "Configuration error: REDCONF_IMAP_INLINE must be either 0 or 1."
|
||||
#endif
|
||||
#if (REDCONF_IMAP_INLINE == 0) && (REDCONF_IMAP_EXTERNAL == 0)
|
||||
#error "Configuration error: At least one of REDCONF_IMAP_INLINE and REDCONF_IMAP_EXTERNAL must be set"
|
||||
#endif
|
||||
|
||||
#if (REDCONF_OUTPUT != 0) && (REDCONF_OUTPUT != 1)
|
||||
#error "Configuration error: REDCONF_OUTPUT must be either 0 or 1."
|
||||
#endif
|
||||
|
||||
#if (REDCONF_ASSERTS != 0) && (REDCONF_ASSERTS != 1)
|
||||
#error "Configuration error: REDCONF_ASSERTS must be either 0 or 1."
|
||||
#endif
|
||||
|
||||
/* REDCONF_BLOCK_SIZE checked in redmacs.h
|
||||
*/
|
||||
|
||||
#if (REDCONF_VOLUME_COUNT < 1U) || (REDCONF_VOLUME_COUNT > 255U)
|
||||
#error "REDCONF_VOLUME_COUNT must be an integer between 1 and 255"
|
||||
#endif
|
||||
|
||||
#if (REDCONF_DISCARDS != 0) && (REDCONF_DISCARDS != 1)
|
||||
#error "Configuration error: REDCONF_DISCARDS must be either 0 or 1."
|
||||
#endif
|
||||
|
||||
/* REDCONF_BUFFER_COUNT lower limit checked in buffer.c
|
||||
*/
|
||||
#if REDCONF_BUFFER_COUNT > 255U
|
||||
#error "REDCONF_BUFFER_COUNT cannot be greater than 255"
|
||||
#endif
|
||||
|
||||
#if (REDCONF_IMAGE_BUILDER != 0) && (REDCONF_IMAGE_BUILDER != 1)
|
||||
#error "Configuration error: REDCONF_IMAGE_BUILDER must be either 0 or 1."
|
||||
#endif
|
||||
|
||||
#if (REDCONF_CHECKER != 0) && (REDCONF_CHECKER != 1)
|
||||
#error "Configuration error: REDCONF_CHECKER must be either 0 or 1."
|
||||
#endif
|
||||
|
||||
|
||||
#if (REDCONF_DISCARDS == 1) && (RED_KIT == RED_KIT_GPL)
|
||||
#error "REDCONF_DISCARDS not supported in Reliance Edge under GPL. Contact sales@datalight.com to upgrade."
|
||||
#endif
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
@@ -0,0 +1,97 @@
|
||||
/* ----> DO NOT REMOVE THE FOLLOWING NOTICE <----
|
||||
|
||||
Copyright (c) 2014-2015 Datalight, Inc.
|
||||
All Rights Reserved Worldwide.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; use version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but "AS-IS," WITHOUT ANY WARRANTY; without even the implied warranty
|
||||
of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
/* Businesses and individuals that for commercial or other reasons cannot
|
||||
comply with the terms of the GPLv2 license may obtain a commercial license
|
||||
before incorporating Reliance Edge into proprietary software for
|
||||
distribution in any form. Visit http://www.datalight.com/reliance-edge for
|
||||
more information.
|
||||
*/
|
||||
/** @file
|
||||
*/
|
||||
#ifndef REDCOREAPI_H
|
||||
#define REDCOREAPI_H
|
||||
|
||||
|
||||
#include <redstat.h>
|
||||
|
||||
|
||||
REDSTATUS RedCoreInit(void);
|
||||
REDSTATUS RedCoreUninit(void);
|
||||
|
||||
REDSTATUS RedCoreVolSetCurrent(uint8_t bVolNum);
|
||||
|
||||
#if FORMAT_SUPPORTED
|
||||
REDSTATUS RedCoreVolFormat(void);
|
||||
#endif
|
||||
#if REDCONF_CHECKER == 1
|
||||
REDSTATUS RedCoreVolCheck(void);
|
||||
#endif
|
||||
REDSTATUS RedCoreVolMount(void);
|
||||
REDSTATUS RedCoreVolUnmount(void);
|
||||
#if REDCONF_READ_ONLY == 0
|
||||
REDSTATUS RedCoreVolTransact(void);
|
||||
#endif
|
||||
#if REDCONF_API_POSIX == 1
|
||||
REDSTATUS RedCoreVolStat(REDSTATFS *pStatFS);
|
||||
#endif
|
||||
|
||||
#if (REDCONF_READ_ONLY == 0) && ((REDCONF_API_POSIX == 1) || (REDCONF_API_FSE_TRANSMASKSET == 1))
|
||||
REDSTATUS RedCoreTransMaskSet(uint32_t ulEventMask);
|
||||
#endif
|
||||
#if (REDCONF_API_POSIX == 1) || (REDCONF_API_FSE_TRANSMASKGET == 1)
|
||||
REDSTATUS RedCoreTransMaskGet(uint32_t *pulEventMask);
|
||||
#endif
|
||||
|
||||
#if (REDCONF_READ_ONLY == 0) && (REDCONF_API_POSIX == 1)
|
||||
REDSTATUS RedCoreCreate(uint32_t ulPInode, const char *pszName, bool fDir, uint32_t *pulInode);
|
||||
#endif
|
||||
#if (REDCONF_READ_ONLY == 0) && (REDCONF_API_POSIX == 1) && (REDCONF_API_POSIX_LINK == 1)
|
||||
REDSTATUS RedCoreLink(uint32_t ulPInode, const char *pszName, uint32_t ulInode);
|
||||
#endif
|
||||
#if (REDCONF_READ_ONLY == 0) && (REDCONF_API_POSIX == 1) && ((REDCONF_API_POSIX_UNLINK == 1) || (REDCONF_API_POSIX_RMDIR == 1))
|
||||
REDSTATUS RedCoreUnlink(uint32_t ulPInode, const char *pszName);
|
||||
#endif
|
||||
#if REDCONF_API_POSIX == 1
|
||||
REDSTATUS RedCoreLookup(uint32_t ulPInode, const char *pszName, uint32_t *pulInode);
|
||||
#endif
|
||||
#if (REDCONF_READ_ONLY == 0) && (REDCONF_API_POSIX == 1) && (REDCONF_API_POSIX_RENAME == 1)
|
||||
REDSTATUS RedCoreRename(uint32_t ulSrcPInode, const char *pszSrcName, uint32_t ulDstPInode, const char *pszDstName);
|
||||
#endif
|
||||
#if REDCONF_API_POSIX == 1
|
||||
REDSTATUS RedCoreStat(uint32_t ulInode, REDSTAT *pStat);
|
||||
#endif
|
||||
#if REDCONF_API_FSE == 1
|
||||
REDSTATUS RedCoreFileSizeGet(uint32_t ulInode, uint64_t *pullSize);
|
||||
#endif
|
||||
|
||||
REDSTATUS RedCoreFileRead(uint32_t ulInode, uint64_t ullStart, uint32_t *pulLen, void *pBuffer);
|
||||
#if REDCONF_READ_ONLY == 0
|
||||
REDSTATUS RedCoreFileWrite(uint32_t ulInode, uint64_t ullStart, uint32_t *pulLen, const void *pBuffer);
|
||||
#endif
|
||||
#if TRUNCATE_SUPPORTED
|
||||
REDSTATUS RedCoreFileTruncate(uint32_t ulInode, uint64_t ullSize);
|
||||
#endif
|
||||
|
||||
#if (REDCONF_API_POSIX == 1) && (REDCONF_API_POSIX_READDIR == 1)
|
||||
REDSTATUS RedCoreDirRead(uint32_t ulInode, uint32_t *pulPos, char *pszName, uint32_t *pulInode);
|
||||
#endif
|
||||
|
||||
|
||||
#endif
|
||||
|
@@ -0,0 +1,224 @@
|
||||
/* ----> DO NOT REMOVE THE FOLLOWING NOTICE <----
|
||||
|
||||
Copyright (c) 2014-2015 Datalight, Inc.
|
||||
All Rights Reserved Worldwide.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; use version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but "AS-IS," WITHOUT ANY WARRANTY; without even the implied warranty
|
||||
of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
/* Businesses and individuals that for commercial or other reasons cannot
|
||||
comply with the terms of the GPLv2 license may obtain a commercial license
|
||||
before incorporating Reliance Edge into proprietary software for
|
||||
distribution in any form. Visit http://www.datalight.com/reliance-edge for
|
||||
more information.
|
||||
*/
|
||||
/** @file
|
||||
@brief This header contains macros which deviate from MISRA C:2012
|
||||
*/
|
||||
#ifndef REDDEVIATIONS_H
|
||||
#define REDDEVIATIONS_H
|
||||
|
||||
|
||||
/** @brief Append a suffix to a constant so that it is an unsigned 64-bit value.
|
||||
|
||||
Usages of this macro deviate from MISRA C:2012 Rule 1.2 (advisory). The
|
||||
rule prohibits the use of language extensions. The ULL suffix became part
|
||||
of the C standard with C99. Since this code base adheres to C89, use of
|
||||
this suffix is a language extension. Reliance Edge needs to deal with
|
||||
64-bit quantities, which by convention are explicitly suffixed. In at
|
||||
least one case, with the INODE_SIZE_MAX macro, the code needs a way to force
|
||||
a constant to be 64-bits even though its value is not so large that it would
|
||||
be automatically promoted to 64-bits. Thus the need for this macro and the
|
||||
deviation. In practice, the ULL suffix has proven to be a nearly universal
|
||||
extension among C89 compilers.
|
||||
|
||||
As rule 19.2 is advisory, a deviation record is not required. This notice
|
||||
is the only record of the deviation. PC-Lint does not issue an error for
|
||||
this deviation so there is no error inhibition option.
|
||||
|
||||
Usages of this macro also deviate from MISRA C:2012 Rule 20.10 (advisory).
|
||||
The rule prohibits use of the ## preprocessor operator. The code is not
|
||||
obscure, and the operator is used only once, so this is deemed to be safe.
|
||||
|
||||
As rule 20.10 is advisory, a deviation record is not required. This notice
|
||||
is the only record of the deviation.
|
||||
|
||||
Consistent use of this macro, even in non MISRA C code, is encouraged to
|
||||
make it easier to search for 64-bit values.
|
||||
|
||||
*/
|
||||
#define UINT64_SUFFIX(number) (number##ULL)
|
||||
|
||||
|
||||
/** @brief Append a suffix to a constant so that it is a signed 64-bit value.
|
||||
|
||||
Usages of this macro deviate from MISRA C:2012 Rule 1.2 (advisory). See the
|
||||
description of UINT64_SUFFIX() for details.
|
||||
|
||||
Usages of this macro deviate from MISRA C:2012 Rule 20.10 (advisory). See
|
||||
the description of UINT64_SUFFIX() for details.
|
||||
*/
|
||||
#define INT64_SUFFIX(number) (number##LL)
|
||||
|
||||
|
||||
/** @brief Cast a pointer to a const uint8_t pointer.
|
||||
|
||||
All usages of this macro deviate from MISRA C:2012 Rule 11.5 (advisory).
|
||||
Because there are no alignment requirements for a uint8_t pointer, this is
|
||||
safe. However, it is technically a deviation from the rule.
|
||||
|
||||
As Rule 11.5 is advisory, a deviation record is not required. This notice
|
||||
and the PC-Lint error inhibition option are the only records of the
|
||||
deviation.
|
||||
*/
|
||||
#define CAST_VOID_PTR_TO_CONST_UINT8_PTR(PTR) ((const uint8_t *)(PTR))
|
||||
|
||||
|
||||
/** @brief Cast a pointer to a uint8_t pointer.
|
||||
|
||||
All usages of this macro deviate from MISRA C:2012 Rule 11.5 (advisory).
|
||||
Because there are no alignment requirements for a uint8_t pointer, this is
|
||||
safe. However, it is technically a deviation from the rule.
|
||||
|
||||
As Rule 11.5 is advisory, a deviation record is not required. This notice
|
||||
and the PC-Lint error inhibition option are the only records of the
|
||||
deviation.
|
||||
*/
|
||||
#define CAST_VOID_PTR_TO_UINT8_PTR(PTR) ((uint8_t *)(PTR))
|
||||
|
||||
|
||||
/** @brief Cast a pointer to a const uint32_t pointer.
|
||||
|
||||
Usages of this macro may deviate from MISRA C:2012 Rule 11.5 (advisory).
|
||||
It is only used in cases where the pointer is known to be aligned, and thus
|
||||
it is safe to do so.
|
||||
|
||||
As Rule 11.5 is advisory, a deviation record is not required. This notice
|
||||
and the PC-Lint error inhibition option are the only records of the
|
||||
deviation.
|
||||
|
||||
Usages of this macro may deviate from MISRA C:2012 Rule 11.3 (required).
|
||||
As Rule 11.3 is required, a separate deviation record is required.
|
||||
|
||||
Regarding the cast to (const void *): this is there to placate some
|
||||
compilers which emit warnings when a type with lower alignment requirements
|
||||
(such as const uint8_t *) is cast to a type with higher alignment
|
||||
requirements. In the places where this macro is used, the pointer is
|
||||
checked to be of sufficient alignment.
|
||||
*/
|
||||
#define CAST_CONST_UINT32_PTR(PTR) ((const uint32_t *)(const void *)(PTR))
|
||||
|
||||
|
||||
/** @brief Cast a pointer to a pointer to (void **).
|
||||
|
||||
Usages of this macro deviate from MISRA C:2012 Rule 11.3 (required).
|
||||
It is only used for populating a node structure pointer with a buffer
|
||||
pointer. Buffer pointers are 8-byte aligned, thus it is safe to do so.
|
||||
|
||||
As Rule 11.3 is required, a separate deviation record is required.
|
||||
*/
|
||||
#define CAST_VOID_PTR_PTR(PTRPTR) ((void **)(PTRPTR))
|
||||
|
||||
|
||||
/** @brief Create a two-dimensional byte array which is safely aligned.
|
||||
|
||||
Usages of this macro deviate from MISRA C:2012 Rule 19.2 (advisory).
|
||||
A union is required to force alignment of the block buffers, which are used
|
||||
to access metadata nodes, which must be safely aligned for 64-bit types.
|
||||
|
||||
As rule 19.2 is advisory, a deviation record is not required. This notice
|
||||
and the PC-Lint error inhibition option are the only records of the
|
||||
deviation.
|
||||
*/
|
||||
#define ALIGNED_2D_BYTE_ARRAY(un, nam, size1, size2) \
|
||||
union \
|
||||
{ \
|
||||
uint8_t nam[size1][size2]; \
|
||||
uint64_t DummyAlign; \
|
||||
} un
|
||||
|
||||
|
||||
/** @brief Determine whether RedMemMove() must copy memory in the forward
|
||||
direction, instead of in the reverse.
|
||||
|
||||
In order to copy between overlapping memory regions, RedMemMove() must copy
|
||||
forward if the destination memory is lower, and backward if the destination
|
||||
memory is higher. Failure to do so would yield incorrect results.
|
||||
|
||||
The only way to make this determination without gross inefficiency is to
|
||||
use pointer comparison. Pointer comparisons are undefined unless both
|
||||
pointers point within the same object or array (or one element past the end
|
||||
of the array); see section 6.3.8 of ANSI C89. While RedMemMove() is
|
||||
normally only used when memory regions overlap, which would not result in
|
||||
undefined behavior, it (like memmove()) is supposed to work even for non-
|
||||
overlapping regions, which would make this function invoke undefined
|
||||
behavior. Experience has shown the pointer comparisons of this sort behave
|
||||
intuitively on common platforms, even though the behavior is undefined. For
|
||||
those platforms where this is not the case, this implementation of memmove()
|
||||
should be replaced with an alternate one.
|
||||
|
||||
Usages of this macro deviate from MISRA-C:2012 Rule 18.3 (required). As
|
||||
Rule 18.3 is required, a separate deviation record is required.
|
||||
*/
|
||||
#define MEMMOVE_MUST_COPY_FORWARD(dest, src) ((dest) < (src))
|
||||
|
||||
|
||||
/** @brief Cast a pointer to a (const DIRENT *).
|
||||
|
||||
Usages of this macro deviate from MISRA-C:2012 Rule 11.3 (required).
|
||||
It is used for populating a directory entry structure pointer with a
|
||||
buffer pointer. Buffer pointers are 8-byte aligned, and DIRENT only
|
||||
requires 4-byte alignment, thus the typecast is safe.
|
||||
|
||||
As Rule 11.3 is required, a separate deviation record is required.
|
||||
*/
|
||||
#define CAST_CONST_DIRENT_PTR(PTR) ((const DIRENT *)(PTR))
|
||||
|
||||
|
||||
/** @brief Determine whether a pointer is aligned.
|
||||
|
||||
A pointer is aligned if its address is an even multiple of
|
||||
::REDCONF_ALIGNMENT_SIZE.
|
||||
|
||||
This is used in the slice-by-8 RedCrc32Update() function, which needs to
|
||||
know whether a pointer is aligned, since the slice-by-8 algorithm needs to
|
||||
access the memory in an aligned fashion, and if the pointer is not aligned,
|
||||
this can result in faults or suboptimal performance (depending on platform).
|
||||
|
||||
There is no way to perform this check without deviating from MISRA C rules
|
||||
against casting pointers to integer types. Usage of this macro deviates
|
||||
from MISRA C:2012 Rule 11.4 (advisory). The main rationale the rule cites
|
||||
against converting pointers to integers is that the chosen integer type may
|
||||
not be able to represent the pointer; this is a non-issue here since we use
|
||||
uintptr_t. The text says the rule still applies when using uintptr_t due to
|
||||
concern about unaligned pointers, but that is not an issue here since the
|
||||
integer value of the pointer is not saved and not converted back into a
|
||||
pointer and dereferenced. The result of casting a pointer to a sufficiently
|
||||
large integer is implementation-defined, but macros similar to this one have
|
||||
been used by Datalight for a long time in a wide variety of environments and
|
||||
they have always worked as expected.
|
||||
|
||||
As Rule 11.4 is advisory, a deviation record is not required. This notice
|
||||
and the PC-Lint error inhibition option are the only records of the
|
||||
deviation.
|
||||
|
||||
@note PC-Lint also thinks this macro as it is used below violates Rule 11.6
|
||||
(required). This is a false positive, since Rule 11.6 only applies to
|
||||
void pointers. Below, we use it on a pointer-to-object (uint8_t *),
|
||||
which is covered by Rule 11.4.
|
||||
*/
|
||||
#define IS_ALIGNED_PTR(ptr) (((uintptr_t)(ptr) & (REDCONF_ALIGNMENT_SIZE - 1U)) == 0U)
|
||||
|
||||
|
||||
#endif
|
||||
|
@@ -0,0 +1,114 @@
|
||||
/* ----> DO NOT REMOVE THE FOLLOWING NOTICE <----
|
||||
|
||||
Copyright (c) 2014-2015 Datalight, Inc.
|
||||
All Rights Reserved Worldwide.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; use version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but "AS-IS," WITHOUT ANY WARRANTY; without even the implied warranty
|
||||
of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
/* Businesses and individuals that for commercial or other reasons cannot
|
||||
comply with the terms of the GPLv2 license may obtain a commercial license
|
||||
before incorporating Reliance Edge into proprietary software for
|
||||
distribution in any form. Visit http://www.datalight.com/reliance-edge for
|
||||
more information.
|
||||
*/
|
||||
/** @file
|
||||
@brief Error values for Reliance Edge APIs
|
||||
*/
|
||||
#ifndef REDERRNO_H
|
||||
#define REDERRNO_H
|
||||
|
||||
|
||||
/** @brief Return type for Reliance Edge error values.
|
||||
*/
|
||||
typedef int32_t REDSTATUS;
|
||||
|
||||
|
||||
/* The errno numbers are the same as Linux.
|
||||
*/
|
||||
|
||||
/** Operation not permitted. */
|
||||
#define RED_EPERM 1
|
||||
|
||||
/** No such file or directory. */
|
||||
#define RED_ENOENT 2
|
||||
|
||||
/** I/O error. */
|
||||
#define RED_EIO 5
|
||||
|
||||
/** Bad file number. */
|
||||
#define RED_EBADF 9
|
||||
|
||||
/** Out of memory */
|
||||
#define RED_ENOMEM 12
|
||||
|
||||
/** Device or resource busy. */
|
||||
#define RED_EBUSY 16
|
||||
|
||||
/** File exists. */
|
||||
#define RED_EEXIST 17
|
||||
|
||||
/** Cross-device link. */
|
||||
#define RED_EXDEV 18
|
||||
|
||||
/** Not a directory. */
|
||||
#define RED_ENOTDIR 20
|
||||
|
||||
/** Is a directory. */
|
||||
#define RED_EISDIR 21
|
||||
|
||||
/** Invalid argument. */
|
||||
#define RED_EINVAL 22
|
||||
|
||||
/** File table overflow. */
|
||||
#define RED_ENFILE 23
|
||||
|
||||
/** Too many open files. */
|
||||
#define RED_EMFILE 24
|
||||
|
||||
/** File too large. */
|
||||
#define RED_EFBIG 27
|
||||
|
||||
/** No space left on device. */
|
||||
#define RED_ENOSPC 28
|
||||
|
||||
/** Read-only file system. */
|
||||
#define RED_EROFS 30
|
||||
|
||||
/** Too many links. */
|
||||
#define RED_EMLINK 31
|
||||
|
||||
/** Math result not representable. */
|
||||
#define RED_ERANGE 34
|
||||
|
||||
/** File name too long. */
|
||||
#define RED_ENAMETOOLONG 36
|
||||
|
||||
/** Function not implemented. */
|
||||
#define RED_ENOSYS 38
|
||||
|
||||
/** Directory not empty. */
|
||||
#define RED_ENOTEMPTY 39
|
||||
|
||||
/** No data available. */
|
||||
#define RED_ENODATA 61
|
||||
|
||||
/** Too many users. */
|
||||
#define RED_EUSERS 87
|
||||
|
||||
/** Nothing will be okay ever again. */
|
||||
#define RED_EFUBAR RED_EINVAL
|
||||
|
||||
|
||||
#endif
|
||||
|
@@ -0,0 +1,53 @@
|
||||
/* ----> DO NOT REMOVE THE FOLLOWING NOTICE <----
|
||||
|
||||
Copyright (c) 2014-2015 Datalight, Inc.
|
||||
All Rights Reserved Worldwide.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; use version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but "AS-IS," WITHOUT ANY WARRANTY; without even the implied warranty
|
||||
of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
/* Businesses and individuals that for commercial or other reasons cannot
|
||||
comply with the terms of the GPLv2 license may obtain a commercial license
|
||||
before incorporating Reliance Edge into proprietary software for
|
||||
distribution in any form. Visit http://www.datalight.com/reliance-edge for
|
||||
more information.
|
||||
*/
|
||||
/** @file
|
||||
*/
|
||||
#ifndef REDEXCLUDE_H
|
||||
#define REDEXCLUDE_H
|
||||
|
||||
|
||||
#define DELETE_SUPPORTED \
|
||||
( \
|
||||
(REDCONF_READ_ONLY == 0) \
|
||||
&& ( (REDCONF_API_POSIX == 1) \
|
||||
&& ( (REDCONF_API_POSIX_RMDIR == 1) \
|
||||
|| (REDCONF_API_POSIX_UNLINK == 1) \
|
||||
|| ((REDCONF_API_POSIX_RENAME == 1) && (REDCONF_RENAME_ATOMIC == 1)))))
|
||||
|
||||
#define TRUNCATE_SUPPORTED \
|
||||
( \
|
||||
(REDCONF_READ_ONLY == 0) \
|
||||
&& ( ((REDCONF_API_POSIX == 1) && (REDCONF_API_POSIX_FTRUNCATE == 1)) \
|
||||
|| ((REDCONF_API_FSE == 1) && (REDCONF_API_FSE_TRUNCATE == 1))))
|
||||
|
||||
#define FORMAT_SUPPORTED \
|
||||
( \
|
||||
(REDCONF_READ_ONLY == 0) \
|
||||
&& ( ((REDCONF_API_POSIX == 1) && (REDCONF_API_POSIX_FORMAT == 1)) \
|
||||
|| ((REDCONF_API_FSE == 1) && (REDCONF_API_FSE_FORMAT == 1)) \
|
||||
|| (REDCONF_IMAGE_BUILDER == 1)))
|
||||
|
||||
#endif
|
||||
|
@@ -0,0 +1,46 @@
|
||||
/* ----> DO NOT REMOVE THE FOLLOWING NOTICE <----
|
||||
|
||||
Copyright (c) 2014-2015 Datalight, Inc.
|
||||
All Rights Reserved Worldwide.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; use version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but "AS-IS," WITHOUT ANY WARRANTY; without even the implied warranty
|
||||
of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
/* Businesses and individuals that for commercial or other reasons cannot
|
||||
comply with the terms of the GPLv2 license may obtain a commercial license
|
||||
before incorporating Reliance Edge into proprietary software for
|
||||
distribution in any form. Visit http://www.datalight.com/reliance-edge for
|
||||
more information.
|
||||
*/
|
||||
/** @file
|
||||
*/
|
||||
#ifndef REDFS_H
|
||||
#define REDFS_H
|
||||
|
||||
|
||||
#include <redconf.h>
|
||||
#include "redver.h"
|
||||
#include "redconfigchk.h"
|
||||
#include <redtypes.h>
|
||||
#include "rederrno.h"
|
||||
#include "reddeviations.h"
|
||||
#include "redmacs.h"
|
||||
#include "redapimacs.h"
|
||||
#include "redutils.h"
|
||||
#include "redosserv.h"
|
||||
#include "redmisc.h"
|
||||
#include "redexclude.h"
|
||||
|
||||
|
||||
#endif
|
||||
|
@@ -0,0 +1,105 @@
|
||||
/* ----> DO NOT REMOVE THE FOLLOWING NOTICE <----
|
||||
|
||||
Copyright (c) 2014-2015 Datalight, Inc.
|
||||
All Rights Reserved Worldwide.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; use version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but "AS-IS," WITHOUT ANY WARRANTY; without even the implied warranty
|
||||
of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
/* Businesses and individuals that for commercial or other reasons cannot
|
||||
comply with the terms of the GPLv2 license may obtain a commercial license
|
||||
before incorporating Reliance Edge into proprietary software for
|
||||
distribution in any form. Visit http://www.datalight.com/reliance-edge for
|
||||
more information.
|
||||
*/
|
||||
/** @file
|
||||
@brief Interface for the Reliance Edge FSE API.
|
||||
|
||||
The FSE (File Systems Essentials) API is a minimalist file system API
|
||||
intended for simple use cases with a fixed number of statically-defined
|
||||
files. It does not support creating or deleting files dynamically. Files
|
||||
are referenced by a fixed file number, rather than by name; there are no
|
||||
file names and no directories. There are also no file handles: files are
|
||||
not opened or closed, and file offsets are given explicitly.
|
||||
|
||||
If the FSE API is too limited to meet the needs of your application,
|
||||
consider using the more feature-rich POSIX-like file system API instead.
|
||||
*/
|
||||
#ifndef REDFSE_H
|
||||
#define REDFSE_H
|
||||
|
||||
/* This header is intended for application use; some applications are written
|
||||
in C++.
|
||||
*/
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <redconf.h>
|
||||
|
||||
#if REDCONF_API_FSE == 1
|
||||
|
||||
#include <redtypes.h>
|
||||
#include "redapimacs.h"
|
||||
#include "rederrno.h"
|
||||
|
||||
|
||||
/** @brief First valid file number.
|
||||
|
||||
This macro can be used to statically define file numbers for given files,
|
||||
as in the below example:
|
||||
|
||||
~~~{.c}
|
||||
#define LOG_FILE (RED_FILENUM_FIRST_VALID)
|
||||
#define DATABASE_FILE (RED_FILENUM_FIRST_VALID + 1U)
|
||||
#define ICON1_FILE (RED_FILENUM_FIRST_VALID + 2U)
|
||||
#define ICON2_FILE (RED_FILENUM_FIRST_VALID + 3U)
|
||||
~~~
|
||||
*/
|
||||
#define RED_FILENUM_FIRST_VALID (2U)
|
||||
|
||||
|
||||
REDSTATUS RedFseInit(void);
|
||||
REDSTATUS RedFseUninit(void);
|
||||
REDSTATUS RedFseMount(uint8_t bVolNum);
|
||||
REDSTATUS RedFseUnmount(uint8_t bVolNum);
|
||||
#if (REDCONF_READ_ONLY == 0) && (REDCONF_API_FSE_FORMAT == 1)
|
||||
REDSTATUS RedFseFormat(uint8_t bVolNum);
|
||||
#endif
|
||||
int32_t RedFseRead(uint8_t bVolNum, uint32_t ulFileNum, uint64_t ullFileOffset, uint32_t ulLength, void *pBuffer);
|
||||
#if REDCONF_READ_ONLY == 0
|
||||
int32_t RedFseWrite(uint8_t bVolNum, uint32_t ulFileNum, uint64_t ullFileOffset, uint32_t ulLength, const void *pBuffer);
|
||||
#endif
|
||||
#if (REDCONF_READ_ONLY == 0) && (REDCONF_API_FSE_TRUNCATE == 1)
|
||||
REDSTATUS RedFseTruncate(uint8_t bVolNum, uint32_t ulFileNum, uint64_t ullNewFileSize);
|
||||
#endif
|
||||
int64_t RedFseSizeGet(uint8_t bVolNum, uint32_t ulFileNum);
|
||||
#if (REDCONF_READ_ONLY == 0) && (REDCONF_API_FSE_TRANSMASKSET == 1)
|
||||
REDSTATUS RedFseTransMaskSet(uint8_t bVolNum, uint32_t ulEventMask);
|
||||
#endif
|
||||
#if REDCONF_API_FSE_TRANSMASKGET == 1
|
||||
REDSTATUS RedFseTransMaskGet(uint8_t bVolNum, uint32_t *pulEventMask);
|
||||
#endif
|
||||
#if REDCONF_READ_ONLY == 0
|
||||
REDSTATUS RedFseTransact(uint8_t bVolNum);
|
||||
#endif
|
||||
|
||||
#endif /* REDCONF_API_FSE == 1 */
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
@@ -0,0 +1,77 @@
|
||||
/*-
|
||||
* Copyright (c) 2000 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
* by Dieter Baron and Thomas Klausner.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
/** @file
|
||||
@brief Interfaces for getopt() and getopt_long() work-alike functions.
|
||||
|
||||
This code was taken from FreeBSD and slightly modified, mostly to rename
|
||||
symbols with external linkage to avoid naming conflicts in systems where
|
||||
there are real getopt()/getopt_long() implementations. Changed to use
|
||||
fixed-width types to allow code using these interfaces to be consistent
|
||||
with the rest of the product.
|
||||
*/
|
||||
#ifndef REDGETOPT_H
|
||||
#define REDGETOPT_H
|
||||
|
||||
|
||||
#define red_no_argument 0
|
||||
#define red_required_argument 1
|
||||
#define red_optional_argument 2
|
||||
|
||||
|
||||
/** @brief Specifies a long option.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
/* name of long option */
|
||||
const char *name;
|
||||
/*
|
||||
* one of red_no_argument, red_required_argument, and red_optional_argument:
|
||||
* whether option takes an argument
|
||||
*/
|
||||
int32_t has_arg;
|
||||
/* if not NULL, set *flag to val when option found */
|
||||
int32_t *flag;
|
||||
/* if flag not NULL, value to set *flag to; else return value */
|
||||
int32_t val;
|
||||
} REDOPTION;
|
||||
|
||||
|
||||
int32_t RedGetopt(int32_t nargc, char * const *nargv, const char *options);
|
||||
int32_t RedGetoptLong(int32_t nargc, char * const *nargv, const char *options, const REDOPTION *long_options, int32_t *idx);
|
||||
|
||||
|
||||
extern const char *red_optarg;
|
||||
extern int32_t red_optind;
|
||||
extern int32_t red_opterr;
|
||||
extern int32_t red_optopt;
|
||||
extern int32_t red_optreset;
|
||||
|
||||
|
||||
#endif
|
||||
|
@@ -0,0 +1,103 @@
|
||||
/* ----> DO NOT REMOVE THE FOLLOWING NOTICE <----
|
||||
|
||||
Copyright (c) 2014-2015 Datalight, Inc.
|
||||
All Rights Reserved Worldwide.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; use version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but "AS-IS," WITHOUT ANY WARRANTY; without even the implied warranty
|
||||
of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
/* Businesses and individuals that for commercial or other reasons cannot
|
||||
comply with the terms of the GPLv2 license may obtain a commercial license
|
||||
before incorporating Reliance Edge into proprietary software for
|
||||
distribution in any form. Visit http://www.datalight.com/reliance-edge for
|
||||
more information.
|
||||
*/
|
||||
/** @file
|
||||
*/
|
||||
#ifndef REDMACS_H
|
||||
#define REDMACS_H
|
||||
|
||||
|
||||
#ifndef NULL
|
||||
#define NULL ((void *)0)
|
||||
#endif
|
||||
|
||||
#ifndef UINT8_MAX
|
||||
#define UINT8_MAX (0xFFU)
|
||||
#endif
|
||||
#ifndef UINT16_MAX
|
||||
#define UINT16_MAX (0xFFFFU)
|
||||
#endif
|
||||
#ifndef UINT32_MAX
|
||||
#define UINT32_MAX (0xFFFFFFFFU)
|
||||
#endif
|
||||
#ifndef UINT64_MAX
|
||||
#define UINT64_MAX UINT64_SUFFIX(0xFFFFFFFFFFFFFFFF)
|
||||
#endif
|
||||
#ifndef INT32_MAX
|
||||
#define INT32_MAX (0x7FFFFFFF)
|
||||
#endif
|
||||
#ifndef INT64_MAX
|
||||
#define INT64_MAX INT64_SUFFIX(0x7FFFFFFFFFFFFFFF)
|
||||
#endif
|
||||
|
||||
#ifndef true
|
||||
#define true (1)
|
||||
#endif
|
||||
#ifndef false
|
||||
#define false (0)
|
||||
#endif
|
||||
|
||||
#define SECTOR_SIZE_MIN (256U)
|
||||
|
||||
#if REDCONF_BLOCK_SIZE == 256U
|
||||
#define BLOCK_SIZE_P2 8U
|
||||
#elif REDCONF_BLOCK_SIZE == 512U
|
||||
#define BLOCK_SIZE_P2 9U
|
||||
#elif REDCONF_BLOCK_SIZE == 1024U
|
||||
#define BLOCK_SIZE_P2 10U
|
||||
#elif REDCONF_BLOCK_SIZE == 2048U
|
||||
#define BLOCK_SIZE_P2 11U
|
||||
#elif REDCONF_BLOCK_SIZE == 4096U
|
||||
#define BLOCK_SIZE_P2 12U
|
||||
#elif REDCONF_BLOCK_SIZE == 8192U
|
||||
#define BLOCK_SIZE_P2 13U
|
||||
#elif REDCONF_BLOCK_SIZE == 16384U
|
||||
#define BLOCK_SIZE_P2 14U
|
||||
#elif REDCONF_BLOCK_SIZE == 32768U
|
||||
#define BLOCK_SIZE_P2 15U
|
||||
#elif REDCONF_BLOCK_SIZE == 65536U
|
||||
#define BLOCK_SIZE_P2 16U
|
||||
#else
|
||||
#error "REDCONF_BLOCK_SIZE must be a power of two value between 256 and 65536"
|
||||
#endif
|
||||
|
||||
#define REDMIN(a, b) (((a) < (b)) ? (a) : (b))
|
||||
|
||||
#define INODE_INVALID (0U) /* General-purpose invalid inode number (must be zero). */
|
||||
#define INODE_FIRST_VALID (2U) /* First valid inode number. */
|
||||
#define INODE_ROOTDIR (INODE_FIRST_VALID) /* Inode number of the root directory. */
|
||||
|
||||
/* Expands to a "const" qualifier when the volume count is one, otherwise
|
||||
expands to nothing. This is useful for variables that never change in
|
||||
single-volume configurations but do change in multi-volume configurations.
|
||||
*/
|
||||
#if REDCONF_VOLUME_COUNT == 1U
|
||||
#define CONST_IF_ONE_VOLUME const
|
||||
#else
|
||||
#define CONST_IF_ONE_VOLUME
|
||||
#endif
|
||||
|
||||
|
||||
#endif
|
||||
|
@@ -0,0 +1,48 @@
|
||||
/* ----> DO NOT REMOVE THE FOLLOWING NOTICE <----
|
||||
|
||||
Copyright (c) 2014-2015 Datalight, Inc.
|
||||
All Rights Reserved Worldwide.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; use version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but "AS-IS," WITHOUT ANY WARRANTY; without even the implied warranty
|
||||
of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
/* Businesses and individuals that for commercial or other reasons cannot
|
||||
comply with the terms of the GPLv2 license may obtain a commercial license
|
||||
before incorporating Reliance Edge into proprietary software for
|
||||
distribution in any form. Visit http://www.datalight.com/reliance-edge for
|
||||
more information.
|
||||
*/
|
||||
/** @file
|
||||
*/
|
||||
#ifndef REDMISC_H
|
||||
#define REDMISC_H
|
||||
|
||||
|
||||
/** @brief Type of an inode or handle.
|
||||
|
||||
Used to indicate the actual or expected type of an inode or handle.
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
FTYPE_FILE, /**< Type is file. */
|
||||
FTYPE_DIR, /**< Type is directory. */
|
||||
|
||||
/** Type is either file or directory: used only to indicate an expected
|
||||
type, never as an actual type.
|
||||
*/
|
||||
FTYPE_EITHER
|
||||
} FTYPE;
|
||||
|
||||
|
||||
#endif
|
||||
|
@@ -0,0 +1,86 @@
|
||||
/* ----> DO NOT REMOVE THE FOLLOWING NOTICE <----
|
||||
|
||||
Copyright (c) 2014-2015 Datalight, Inc.
|
||||
All Rights Reserved Worldwide.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; use version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but "AS-IS," WITHOUT ANY WARRANTY; without even the implied warranty
|
||||
of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
/* Businesses and individuals that for commercial or other reasons cannot
|
||||
comply with the terms of the GPLv2 license may obtain a commercial license
|
||||
before incorporating Reliance Edge into proprietary software for
|
||||
distribution in any form. Visit http://www.datalight.com/reliance-edge for
|
||||
more information.
|
||||
*/
|
||||
/** @file
|
||||
*/
|
||||
#ifndef REDOSSERV_H
|
||||
#define REDOSSERV_H
|
||||
|
||||
|
||||
#include <redostypes.h>
|
||||
|
||||
|
||||
/** @brief Type of access requested when opening a block device.
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
BDEV_O_RDONLY, /**< Open block device for read access. */
|
||||
BDEV_O_WRONLY, /**< Open block device for write access. */
|
||||
BDEV_O_RDWR /**< Open block device for read and write access. */
|
||||
} BDEVOPENMODE;
|
||||
|
||||
REDSTATUS RedOsBDevOpen(uint8_t bVolNum, BDEVOPENMODE mode);
|
||||
REDSTATUS RedOsBDevClose(uint8_t bVolNum);
|
||||
REDSTATUS RedOsBDevRead(uint8_t bVolNum, uint64_t ullSectorStart, uint32_t ulSectorCount, void *pBuffer);
|
||||
|
||||
#if REDCONF_READ_ONLY == 0
|
||||
REDSTATUS RedOsBDevWrite(uint8_t bVolNum, uint64_t ullSectorStart, uint32_t ulSectorCount, const void *pBuffer);
|
||||
REDSTATUS RedOsBDevFlush(uint8_t bVolNum);
|
||||
#endif
|
||||
|
||||
/* Non-standard API: for host machines only.
|
||||
*/
|
||||
REDSTATUS RedOsBDevConfig(uint8_t bVolNum, const char *pszBDevSpec);
|
||||
|
||||
|
||||
#if REDCONF_TASK_COUNT > 1U
|
||||
REDSTATUS RedOsMutexInit(void);
|
||||
REDSTATUS RedOsMutexUninit(void);
|
||||
void RedOsMutexAcquire(void);
|
||||
void RedOsMutexRelease(void);
|
||||
#endif
|
||||
#if (REDCONF_TASK_COUNT > 1U) && (REDCONF_API_POSIX == 1)
|
||||
uint32_t RedOsTaskId(void);
|
||||
#endif
|
||||
|
||||
REDSTATUS RedOsClockInit(void);
|
||||
REDSTATUS RedOsClockUninit(void);
|
||||
uint32_t RedOsClockGetTime(void);
|
||||
|
||||
REDSTATUS RedOsTimestampInit(void);
|
||||
REDSTATUS RedOsTimestampUninit(void);
|
||||
REDTIMESTAMP RedOsTimestamp(void);
|
||||
uint64_t RedOsTimePassed(REDTIMESTAMP tsSince);
|
||||
|
||||
#if REDCONF_OUTPUT == 1
|
||||
void RedOsOutputString(const char *pszString);
|
||||
#endif
|
||||
|
||||
#if REDCONF_ASSERTS == 1
|
||||
void RedOsAssertFail(const char *pszFileName, uint32_t ulLineNum);
|
||||
#endif
|
||||
|
||||
|
||||
#endif
|
||||
|
@@ -0,0 +1,38 @@
|
||||
/* ----> DO NOT REMOVE THE FOLLOWING NOTICE <----
|
||||
|
||||
Copyright (c) 2014-2015 Datalight, Inc.
|
||||
All Rights Reserved Worldwide.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; use version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but "AS-IS," WITHOUT ANY WARRANTY; without even the implied warranty
|
||||
of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
/* Businesses and individuals that for commercial or other reasons cannot
|
||||
comply with the terms of the GPLv2 license may obtain a commercial license
|
||||
before incorporating Reliance Edge into proprietary software for
|
||||
distribution in any form. Visit http://www.datalight.com/reliance-edge for
|
||||
more information.
|
||||
*/
|
||||
/** @file
|
||||
@brief Interfaces of path utilities for the POSIX-like API layer.
|
||||
*/
|
||||
#ifndef REDPATH_H
|
||||
#define REDPATH_H
|
||||
|
||||
|
||||
REDSTATUS RedPathSplit(const char *pszPath, uint8_t *pbVolNum, const char **ppszLocalPath);
|
||||
REDSTATUS RedPathLookup(const char *pszLocalPath, uint32_t *pulInode);
|
||||
REDSTATUS RedPathToName(const char *pszLocalPath, uint32_t *pulPInode, const char **ppszName);
|
||||
|
||||
|
||||
#endif
|
||||
|
@@ -0,0 +1,196 @@
|
||||
/* ----> DO NOT REMOVE THE FOLLOWING NOTICE <----
|
||||
|
||||
Copyright (c) 2014-2015 Datalight, Inc.
|
||||
All Rights Reserved Worldwide.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; use version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but "AS-IS," WITHOUT ANY WARRANTY; without even the implied warranty
|
||||
of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
/* Businesses and individuals that for commercial or other reasons cannot
|
||||
comply with the terms of the GPLv2 license may obtain a commercial license
|
||||
before incorporating Reliance Edge into proprietary software for
|
||||
distribution in any form. Visit http://www.datalight.com/reliance-edge for
|
||||
more information.
|
||||
*/
|
||||
/** @file
|
||||
@brief Interface for the Reliance Edge POSIX-like API.
|
||||
|
||||
The POSIX-like file system API is the primary file system API for
|
||||
Reliance Edge, which supports the full functionality of the file system.
|
||||
This API aims to be compatible with POSIX where reasonable, but it is
|
||||
simplified considerably to meet the needs of resource-constrained embedded
|
||||
systems. The API has also been extended to provide access to the unique
|
||||
features of Reliance Edge, and to cover areas (like mountins and formatting)
|
||||
which do not have APIs in the POSIX specification.
|
||||
*/
|
||||
#ifndef REDPOSIX_H
|
||||
#define REDPOSIX_H
|
||||
|
||||
/* This header is intended for application use; some applications are written
|
||||
in C++.
|
||||
*/
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <redconf.h>
|
||||
|
||||
#if REDCONF_API_POSIX == 1
|
||||
|
||||
#include <redtypes.h>
|
||||
#include "redapimacs.h"
|
||||
#include "rederrno.h"
|
||||
#include "redstat.h"
|
||||
|
||||
/** Open for reading only. */
|
||||
#define RED_O_RDONLY 0x00000001U
|
||||
|
||||
/** Open for writing only. */
|
||||
#define RED_O_WRONLY 0x00000002U
|
||||
|
||||
/** Open for reading and writing. */
|
||||
#define RED_O_RDWR 0x00000004U
|
||||
|
||||
/** File offset for all writes is end-of-file. */
|
||||
#define RED_O_APPEND 0x00000008U
|
||||
|
||||
/** Create the file. */
|
||||
#define RED_O_CREAT 0x00000010U
|
||||
|
||||
/** Error if path already exists. */
|
||||
#define RED_O_EXCL 0x00000020U
|
||||
|
||||
/** Truncate file to size zero. */
|
||||
#define RED_O_TRUNC 0x00000040U
|
||||
|
||||
|
||||
/** @brief Last file system error (errno).
|
||||
|
||||
Under normal circumstances, each task using the file system has an
|
||||
independent `red_errno` value. Applications do not need to worry about
|
||||
one task obliterating an error value that another task needed to read. The
|
||||
value is initially zero. When one of the POSIX-like APIs return an
|
||||
indication of error, `red_errno` is set to an error value.
|
||||
|
||||
In some circumstances, `red_errno` will be a global errno location which
|
||||
is shared by multiple tasks. If the calling task is not registered as a
|
||||
file system user and all of the task slots are full, there can be no
|
||||
task-specific errno, so the global errno is used. Likewise, if the file
|
||||
system driver is uninitialized, there are no registered file system users
|
||||
and `red_errno` always refers to the global errno. Under these
|
||||
circumstances, multiple tasks manipulating `red_errno` could be
|
||||
problematic. When the task count is set to one, `red_errno` always refers
|
||||
to the global errno.
|
||||
|
||||
Note that `red_errno` is usable as an lvalue; i.e., in addition to reading
|
||||
the error value, the error value can be set:
|
||||
|
||||
~~~{.c}
|
||||
red_errno = 0;
|
||||
~~~
|
||||
*/
|
||||
#define red_errno (*red_errnoptr())
|
||||
|
||||
|
||||
/** @brief Positions from which to seek within a file.
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
/* 0/1/2 are the traditional values for SET/CUR/END, respectively. Prior
|
||||
to the release of Unix System V in 1983, the SEEK_* symbols did not
|
||||
exist and C programs hard-coded the 0/1/2 values with those meanings.
|
||||
*/
|
||||
RED_SEEK_SET = 0, /**< Set file offset to given offset. */
|
||||
RED_SEEK_CUR = 1, /**< Set file offset to current offset plus signed offset. */
|
||||
RED_SEEK_END = 2 /**< Set file offset to EOF plus signed offset. */
|
||||
} REDWHENCE;
|
||||
|
||||
|
||||
#if REDCONF_API_POSIX_READDIR == 1
|
||||
/** @brief Opaque directory handle.
|
||||
*/
|
||||
typedef struct sREDHANDLE REDDIR;
|
||||
|
||||
|
||||
/** @brief Directory entry information.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
uint32_t d_ino; /**< File serial number (inode number). */
|
||||
char d_name[REDCONF_NAME_MAX+1U]; /**< Name of entry. */
|
||||
REDSTAT d_stat; /**< File information (POSIX extension). */
|
||||
} REDDIRENT;
|
||||
#endif
|
||||
|
||||
|
||||
int32_t red_init(void);
|
||||
int32_t red_uninit(void);
|
||||
int32_t red_mount(const char *pszVolume);
|
||||
int32_t red_umount(const char *pszVolume);
|
||||
#if (REDCONF_READ_ONLY == 0) && (REDCONF_API_POSIX_FORMAT == 1)
|
||||
int32_t red_format(const char *pszVolume);
|
||||
#endif
|
||||
#if REDCONF_READ_ONLY == 0
|
||||
int32_t red_transact(const char *pszVolume);
|
||||
#endif
|
||||
#if REDCONF_READ_ONLY == 0
|
||||
int32_t red_settransmask(const char *pszVolume, uint32_t ulEventMask);
|
||||
#endif
|
||||
int32_t red_gettransmask(const char *pszVolume, uint32_t *pulEventMask);
|
||||
int32_t red_statvfs(const char *pszVolume, REDSTATFS *pStatvfs);
|
||||
int32_t red_open(const char *pszPath, uint32_t ulOpenMode);
|
||||
#if (REDCONF_READ_ONLY == 0) && (REDCONF_API_POSIX_UNLINK == 1)
|
||||
int32_t red_unlink(const char *pszPath);
|
||||
#endif
|
||||
#if (REDCONF_READ_ONLY == 0) && (REDCONF_API_POSIX_MKDIR == 1)
|
||||
int32_t red_mkdir(const char *pszPath);
|
||||
#endif
|
||||
#if (REDCONF_READ_ONLY == 0) && (REDCONF_API_POSIX_RMDIR == 1)
|
||||
int32_t red_rmdir(const char *pszPath);
|
||||
#endif
|
||||
#if (REDCONF_READ_ONLY == 0) && (REDCONF_API_POSIX_RENAME == 1)
|
||||
int32_t red_rename(const char *pszOldPath, const char *pszNewPath);
|
||||
#endif
|
||||
#if (REDCONF_READ_ONLY == 0) && (REDCONF_API_POSIX_LINK == 1)
|
||||
int32_t red_link(const char *pszPath, const char *pszHardLink);
|
||||
#endif
|
||||
int32_t red_close(int32_t iFildes);
|
||||
int32_t red_read(int32_t iFildes, void *pBuffer, uint32_t ulLength);
|
||||
#if REDCONF_READ_ONLY == 0
|
||||
int32_t red_write(int32_t iFildes, const void *pBuffer, uint32_t ulLength);
|
||||
#endif
|
||||
#if REDCONF_READ_ONLY == 0
|
||||
int32_t red_fsync(int32_t iFildes);
|
||||
#endif
|
||||
int64_t red_lseek(int32_t iFildes, int64_t llOffset, REDWHENCE whence);
|
||||
#if (REDCONF_READ_ONLY == 0) && (REDCONF_API_POSIX_FTRUNCATE == 1)
|
||||
int32_t red_ftruncate(int32_t iFildes, uint64_t ullSize);
|
||||
#endif
|
||||
int32_t red_fstat(int32_t iFildes, REDSTAT *pStat);
|
||||
#if REDCONF_API_POSIX_READDIR == 1
|
||||
REDDIR *red_opendir(const char *pszPath);
|
||||
REDDIRENT *red_readdir(REDDIR *pDirStream);
|
||||
void red_rewinddir(REDDIR *pDirStream);
|
||||
int32_t red_closedir(REDDIR *pDirStream);
|
||||
#endif
|
||||
REDSTATUS *red_errnoptr(void);
|
||||
|
||||
#endif /* REDCONF_API_POSIX */
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
@@ -0,0 +1,94 @@
|
||||
/* ----> DO NOT REMOVE THE FOLLOWING NOTICE <----
|
||||
|
||||
Copyright (c) 2014-2015 Datalight, Inc.
|
||||
All Rights Reserved Worldwide.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; use version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but "AS-IS," WITHOUT ANY WARRANTY; without even the implied warranty
|
||||
of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
/* Businesses and individuals that for commercial or other reasons cannot
|
||||
comply with the terms of the GPLv2 license may obtain a commercial license
|
||||
before incorporating Reliance Edge into proprietary software for
|
||||
distribution in any form. Visit http://www.datalight.com/reliance-edge for
|
||||
more information.
|
||||
*/
|
||||
/** @file
|
||||
*/
|
||||
#ifndef REDSTAT_H
|
||||
#define REDSTAT_H
|
||||
|
||||
|
||||
/** Mode bit for a directory. */
|
||||
#define RED_S_IFDIR 0x4000U
|
||||
|
||||
/** Mode bit for a regular file. */
|
||||
#define RED_S_IFREG 0x8000U
|
||||
|
||||
/** @brief Test for a directory.
|
||||
*/
|
||||
#define RED_S_ISDIR(m) (((m) & RED_S_IFDIR) != 0U)
|
||||
|
||||
/** @brief Test for a regular file.
|
||||
*/
|
||||
#define RED_S_ISREG(m) (((m) & RED_S_IFREG) != 0U)
|
||||
|
||||
|
||||
/** File system is read-only. */
|
||||
#define RED_ST_RDONLY 0x00000001U
|
||||
|
||||
/** File system ignores suid and sgid bits. */
|
||||
#define RED_ST_NOSUID 0x00000002U
|
||||
|
||||
|
||||
/** @brief Status information on an inode.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
uint8_t st_dev; /**< Volume number of volume containing file. */
|
||||
uint32_t st_ino; /**< File serial number (inode number). */
|
||||
uint16_t st_mode; /**< Mode of file. */
|
||||
uint16_t st_nlink; /**< Number of hard links to the file. */
|
||||
uint64_t st_size; /**< File size in bytes. */
|
||||
#if REDCONF_INODE_TIMESTAMPS == 1
|
||||
uint32_t st_atime; /**< Time of last access (seconds since 01-01-1970). */
|
||||
uint32_t st_mtime; /**< Time of last data modification (seconds since 01-01-1970). */
|
||||
uint32_t st_ctime; /**< Time of last status change (seconds since 01-01-1970). */
|
||||
#endif
|
||||
#if REDCONF_INODE_BLOCKS == 1
|
||||
uint32_t st_blocks; /**< Number of blocks allocated for this object. */
|
||||
#endif
|
||||
} REDSTAT;
|
||||
|
||||
|
||||
/** @brief Status information on a file system volume.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
uint32_t f_bsize; /**< File system block size. */
|
||||
uint32_t f_frsize; /**< Fundamental file system block size. */
|
||||
uint32_t f_blocks; /**< Total number of blocks on file system in units of f_frsize. */
|
||||
uint32_t f_bfree; /**< Total number of free blocks. */
|
||||
uint32_t f_bavail; /**< Number of free blocks available to non-privileged process. */
|
||||
uint32_t f_files; /**< Total number of file serial numbers. */
|
||||
uint32_t f_ffree; /**< Total number of free file serial numbers. */
|
||||
uint32_t f_favail; /**< Number of file serial numbers available to non-privileged process. */
|
||||
uint32_t f_fsid; /**< File system ID (useless, populated with zero). */
|
||||
uint32_t f_flag; /**< Bit mask of f_flag values. Includes read-only file system flag. */
|
||||
uint32_t f_namemax; /**< Maximum filename length. */
|
||||
uint64_t f_maxfsize; /**< Maximum file size (POSIX extension). */
|
||||
uint32_t f_dev; /**< Volume number (POSIX extension). */
|
||||
} REDSTATFS;
|
||||
|
||||
|
||||
#endif
|
||||
|
@@ -0,0 +1,265 @@
|
||||
/* ----> DO NOT REMOVE THE FOLLOWING NOTICE <----
|
||||
|
||||
Copyright (c) 2014-2015 Datalight, Inc.
|
||||
All Rights Reserved Worldwide.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; use version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but "AS-IS," WITHOUT ANY WARRANTY; without even the implied warranty
|
||||
of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
/* Businesses and individuals that for commercial or other reasons cannot
|
||||
comply with the terms of the GPLv2 license may obtain a commercial license
|
||||
before incorporating Reliance Edge into proprietary software for
|
||||
distribution in any form. Visit http://www.datalight.com/reliance-edge for
|
||||
more information.
|
||||
*/
|
||||
/** @file
|
||||
@brief Prototypes for Reliance Edge test entry points.
|
||||
*/
|
||||
#ifndef REDTESTS_H
|
||||
#define REDTESTS_H
|
||||
|
||||
#include <redtypes.h>
|
||||
#include "redtestutils.h"
|
||||
#include "redver.h"
|
||||
|
||||
/* This macro is only defined by the error injection project.
|
||||
*/
|
||||
#ifdef REDCONF_ERROR_INJECTION
|
||||
#include <rederrinject.h>
|
||||
#endif
|
||||
|
||||
#define FSSTRESS_SUPPORTED \
|
||||
( ((RED_KIT == RED_KIT_GPL) || (RED_KIT == RED_KIT_SANDBOX)) \
|
||||
&& (REDCONF_OUTPUT == 1) && (REDCONF_READ_ONLY == 0) && (REDCONF_PATH_SEPARATOR == '/') \
|
||||
&& (REDCONF_API_POSIX == 1) && (REDCONF_API_POSIX_UNLINK == 1) && (REDCONF_API_POSIX_MKDIR == 1) \
|
||||
&& (REDCONF_API_POSIX_RMDIR == 1) && (REDCONF_API_POSIX_RENAME == 1) && (REDCONF_API_POSIX_LINK == 1) \
|
||||
&& (REDCONF_API_POSIX_FTRUNCATE == 1) && (REDCONF_API_POSIX_READDIR == 1))
|
||||
|
||||
#define FSE_STRESS_TEST_SUPPORTED \
|
||||
( ((RED_KIT == RED_KIT_COMMERCIAL) || (RED_KIT == RED_KIT_SANDBOX)) \
|
||||
&& (REDCONF_OUTPUT == 1) && (REDCONF_READ_ONLY == 0) && (REDCONF_API_FSE == 1) \
|
||||
&& (REDCONF_API_FSE_FORMAT == 1) && (REDCONF_API_FSE_TRANSMASKSET == 1) && (REDCONF_API_FSE_TRANSMASKGET == 1) \
|
||||
&& (REDCONF_API_FSE_TRUNCATE == 1))
|
||||
|
||||
#define POSIX_API_TEST_SUPPORTED \
|
||||
( ((RED_KIT == RED_KIT_COMMERCIAL) || (RED_KIT == RED_KIT_SANDBOX)) \
|
||||
&& (REDCONF_OUTPUT == 1) && (REDCONF_READ_ONLY == 0) && (REDCONF_API_POSIX == 1) \
|
||||
&& (REDCONF_API_POSIX_FORMAT == 1) && (REDCONF_API_POSIX_UNLINK == 1))
|
||||
|
||||
#define FSE_API_TEST_SUPPORTED \
|
||||
( ((RED_KIT == RED_KIT_COMMERCIAL) || (RED_KIT == RED_KIT_SANDBOX)) \
|
||||
&& (REDCONF_OUTPUT == 1) && (REDCONF_READ_ONLY == 0) && (REDCONF_API_FSE == 1) \
|
||||
&& (REDCONF_API_FSE_FORMAT == 1))
|
||||
|
||||
#define STOCH_POSIX_TEST_SUPPORTED \
|
||||
( ((RED_KIT == RED_KIT_COMMERCIAL) || (RED_KIT == RED_KIT_SANDBOX)) \
|
||||
&& (REDCONF_OUTPUT == 1) && (REDCONF_READ_ONLY == 0) && (REDCONF_API_POSIX == 1) \
|
||||
&& (REDCONF_API_POSIX_FORMAT == 1) && (REDCONF_API_POSIX_READDIR == 1) \
|
||||
&& (REDCONF_API_POSIX_MKDIR == 1) && (REDCONF_API_POSIX_RMDIR == 1) && (REDCONF_API_POSIX_UNLINK == 1) \
|
||||
&& (REDCONF_API_POSIX_RENAME == 1))
|
||||
|
||||
#define FSIOTEST_SUPPORTED \
|
||||
( ((RED_KIT == RED_KIT_COMMERCIAL) || (RED_KIT == RED_KIT_SANDBOX)) \
|
||||
&& (REDCONF_OUTPUT == 1) && (REDCONF_API_POSIX == 1))
|
||||
|
||||
#define BDEVTEST_SUPPORTED \
|
||||
( ((RED_KIT == RED_KIT_COMMERCIAL) || (RED_KIT == RED_KIT_SANDBOX)) \
|
||||
&& (REDCONF_OUTPUT == 1) && (REDCONF_READ_ONLY == 0))
|
||||
|
||||
#define DISKFULL_TEST_SUPPORTED \
|
||||
( ((RED_KIT == RED_KIT_COMMERCIAL) || (RED_KIT == RED_KIT_SANDBOX)) \
|
||||
&& (REDCONF_OUTPUT == 1) && (REDCONF_READ_ONLY == 0) && (REDCONF_API_POSIX == 1) \
|
||||
&& (REDCONF_API_POSIX_FORMAT == 1) && (REDCONF_API_POSIX_FTRUNCATE == 1))
|
||||
|
||||
|
||||
typedef enum
|
||||
{
|
||||
PARAMSTATUS_OK, /* Parameters were good; continue. */
|
||||
PARAMSTATUS_BAD, /* Parameters were bad; stop. */
|
||||
PARAMSTATUS_HELP /* Help request; not an error, but stop. */
|
||||
} PARAMSTATUS;
|
||||
|
||||
|
||||
#if FSSTRESS_SUPPORTED
|
||||
typedef struct
|
||||
{
|
||||
bool fNoCleanup; /**< --no-cleanup */
|
||||
uint32_t ulLoops; /**< --loops */
|
||||
uint32_t ulNops; /**< --nops */
|
||||
bool fNamePad; /**< --namepad */
|
||||
uint32_t ulSeed; /**< --seed */
|
||||
bool fVerbose; /**< --verbose */
|
||||
} FSSTRESSPARAM;
|
||||
|
||||
PARAMSTATUS FsstressParseParams(int argc, char *argv[], FSSTRESSPARAM *pParam, uint8_t *pbVolNum, const char **ppszDevice);
|
||||
void FsstressDefaultParams(FSSTRESSPARAM *pParam);
|
||||
int FsstressStart(const FSSTRESSPARAM *pParam);
|
||||
#endif
|
||||
|
||||
#if STOCH_POSIX_TEST_SUPPORTED
|
||||
typedef struct
|
||||
{
|
||||
const char *pszVolume; /**< Volume path prefix. */
|
||||
uint32_t ulIterations; /**< --iterations */
|
||||
uint32_t ulFileListMax; /**< --files */
|
||||
uint32_t ulDirListMax; /**< --dirs */
|
||||
uint32_t ulOpenFileListMax; /**< --open-files */
|
||||
uint32_t ulOpenDirListMax; /**< --open-dirs */
|
||||
uint32_t ulRandomSeed; /**< --seed */
|
||||
} STOCHPOSIXPARAM;
|
||||
|
||||
PARAMSTATUS RedStochPosixParseParams(int argc, char *argv[], STOCHPOSIXPARAM *pParam, uint8_t *pbVolNum, const char **ppszDevice);
|
||||
void RedStochPosixDefaultParams(STOCHPOSIXPARAM *pParam);
|
||||
int RedStochPosixStart(const STOCHPOSIXPARAM *pParam);
|
||||
#endif
|
||||
|
||||
#if FSE_STRESS_TEST_SUPPORTED
|
||||
typedef struct
|
||||
{
|
||||
uint8_t bVolNum; /**< Volume number. */
|
||||
uint32_t ulFileCount; /**< --files */
|
||||
uint32_t ulMaxFileSize; /**< --max */
|
||||
uint32_t ulMaxOpSize; /**< --buffer-size */
|
||||
uint32_t ulNops; /**< --nops */
|
||||
uint32_t ulLoops; /**< --loops */
|
||||
uint32_t ulSampleRate; /**< --sample-rate */
|
||||
uint64_t ullSeed; /**< --seed */
|
||||
} FSESTRESSPARAM;
|
||||
|
||||
PARAMSTATUS FseStressParseParams(int argc, char *argv[], FSESTRESSPARAM *pParam, uint8_t *pbVolNum, const char **ppszDevice);
|
||||
void FseStressDefaultParams(FSESTRESSPARAM *pParam);
|
||||
int FseStressStart(const FSESTRESSPARAM *pParam);
|
||||
#endif
|
||||
|
||||
#if POSIX_API_TEST_SUPPORTED
|
||||
typedef struct
|
||||
{
|
||||
const char *pszVolume; /**< Volume path prefix. */
|
||||
bool fQuick; /**< --quick */
|
||||
bool fQuitOnFailure; /**< --quit-on-failure */
|
||||
bool fDebugErrors; /**< --debug */
|
||||
} POSIXTESTPARAM;
|
||||
|
||||
PARAMSTATUS RedPosixTestParseParams(int argc, char *argv[], POSIXTESTPARAM *pParam, uint8_t *pbVolNum, const char **ppszDevice);
|
||||
void RedPosixTestDefaultParams(POSIXTESTPARAM *pParam);
|
||||
int RedPosixTestStart(const POSIXTESTPARAM *pParam);
|
||||
#endif
|
||||
|
||||
|
||||
#if POSIX_API_TEST_SUPPORTED
|
||||
typedef struct
|
||||
{
|
||||
const char *pszVolume; /**< Volume path prefix. */
|
||||
bool fQuick; /**< --quick */
|
||||
bool fVerbose; /**< --verbose */
|
||||
bool fQuitOnFailure; /**< --quit-on-failure */
|
||||
bool fDebugErrors; /**< --debug */
|
||||
} OSAPITESTPARAM;
|
||||
|
||||
PARAMSTATUS RedOsApiTestParseParams(int argc, char *argv[], OSAPITESTPARAM *pParam, const char **ppszDevice);
|
||||
void RedOsApiTestDefaultParams(OSAPITESTPARAM *pParam);
|
||||
int RedOsApiTestStart(const OSAPITESTPARAM *pParam);
|
||||
#endif
|
||||
|
||||
|
||||
#if FSE_API_TEST_SUPPORTED
|
||||
typedef struct
|
||||
{
|
||||
uint8_t bVolNum; /**< Volume number. */
|
||||
bool fQuitOnFailure; /**< --quit-on-failure */
|
||||
bool fDebugErrors; /**< --debug */
|
||||
} FSETESTPARAM;
|
||||
|
||||
PARAMSTATUS RedFseTestParseParams(int argc, char *argv[], FSETESTPARAM *pParam, uint8_t *pbVolNum, const char **ppszDevice);
|
||||
void RedFseTestDefaultParams(FSETESTPARAM *pParam);
|
||||
int RedFseTestStart(const FSETESTPARAM *pParam);
|
||||
#endif
|
||||
|
||||
#if FSIOTEST_SUPPORTED
|
||||
typedef enum
|
||||
{
|
||||
TESTFS_RELEDGE, /* Datalight Reliance Edge */
|
||||
TESTFS_FATFS, /* ChaN's FatFs */
|
||||
TESTFS_FATSL /* FreeRTOS+FAT SL */
|
||||
} TESTFS;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
TESTFS testfs; /**< --fs */
|
||||
const char *pszVolume; /**< Volume path prefix. */
|
||||
bool fSeqRead; /**< --seq=r */
|
||||
bool fSeqWrite; /**< --seq=w */
|
||||
bool fSeqRewrite; /**< --seq=e */
|
||||
bool fRandomRead; /**< --rand=r */
|
||||
bool fRandomWrite; /**< --rand=w */
|
||||
bool fMixedWrite; /**< --mixed */
|
||||
bool fScanTest; /**< --scan */
|
||||
uint32_t ulFSBlockSize; /**< --block-size */
|
||||
uint32_t ulMaxFileSize; /**< --max */
|
||||
uint32_t ulRandomReadPasses; /**< --rand-pass=r:w (r part) */
|
||||
uint32_t ulRandomWritePasses; /**< --rand-pass=r:w (w part) */
|
||||
uint32_t ulMixedWritePasses; /**< --mixed-pass */
|
||||
int32_t iFlushOnWriteRatio; /**< --rand-fow */
|
||||
uint32_t ulBufferMin; /**< --start */
|
||||
uint32_t ulBufferSize; /**< --buffer-size */
|
||||
bool fWriteVerify; /**< --verify */
|
||||
uint32_t ulSampleRate; /**< --sample-rate */
|
||||
uint32_t ulScanCount; /**< --scan-files */
|
||||
uint64_t ullSeed; /**< --seed */
|
||||
} FSIOTESTPARAM;
|
||||
|
||||
PARAMSTATUS FSIOTestParseParams(int argc, char *argv[], FSIOTESTPARAM *pParam, uint8_t *pbVolNum, const char **ppszDevice);
|
||||
void FSIOTestDefaultParams(FSIOTESTPARAM *pParam);
|
||||
int FSIOTestStart(const FSIOTESTPARAM *pParam);
|
||||
#endif
|
||||
|
||||
#if BDEVTEST_SUPPORTED
|
||||
typedef struct
|
||||
{
|
||||
uint8_t bDrvNum; /**< Volume number (for sector size/count). */
|
||||
bool fSeqWrite; /**< --seq:w */
|
||||
bool fSeqRead; /**< --seq:r */
|
||||
bool fRandWrite; /**< --rand:w */
|
||||
bool fRandRead; /**< --rand:r */
|
||||
uint32_t ulSampleSecs; /**< --sample-rate */
|
||||
uint32_t ulPasses; /**< --passes */
|
||||
uint32_t ulMinIOSectors; /**< --count=min[:max] (min part) */
|
||||
uint32_t ulMaxIOSectors; /**< --count=min[:max] (max part) */
|
||||
uint32_t ulMaxSizeKB; /**< --max */
|
||||
uint32_t ulTestSeconds; /**< --time */
|
||||
bool fVerify; /**< --verify */
|
||||
bool fAsyncWrites; /**< --async */
|
||||
uint64_t ullSeed; /**< --seed */
|
||||
} BDEVTESTPARAM;
|
||||
|
||||
PARAMSTATUS BDevTestParseParams(int argc, char *argv[], BDEVTESTPARAM *pParam, uint8_t *pbVolNum, const char **ppszDevice);
|
||||
void BDevTestDefaultParams(BDEVTESTPARAM *pParam);
|
||||
int BDevTestStart(const BDEVTESTPARAM *pParam);
|
||||
#endif
|
||||
|
||||
#if DISKFULL_TEST_SUPPORTED
|
||||
typedef struct
|
||||
{
|
||||
const char *pszVolume; /**< Volume path prefix. */
|
||||
bool fQuitOnFailure; /**< --quit-on-failure */
|
||||
bool fDebugErrors; /**< --debug */
|
||||
} DISKFULLTESTPARAM;
|
||||
|
||||
PARAMSTATUS DiskFullTestParseParams(int argc, char *argv[], DISKFULLTESTPARAM *pParam, uint8_t *pbVolNum, const char **ppszDevice);
|
||||
void DiskFullTestDefaultParams(DISKFULLTESTPARAM *pParam);
|
||||
int DiskFullTestStart(const DISKFULLTESTPARAM *pParam);
|
||||
#endif
|
||||
|
||||
|
||||
#endif
|
||||
|
@@ -0,0 +1,71 @@
|
||||
/* ----> DO NOT REMOVE THE FOLLOWING NOTICE <----
|
||||
|
||||
Copyright (c) 2014-2015 Datalight, Inc.
|
||||
All Rights Reserved Worldwide.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; use version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but "AS-IS," WITHOUT ANY WARRANTY; without even the implied warranty
|
||||
of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
/* Businesses and individuals that for commercial or other reasons cannot
|
||||
comply with the terms of the GPLv2 license may obtain a commercial license
|
||||
before incorporating Reliance Edge into proprietary software for
|
||||
distribution in any form. Visit http://www.datalight.com/reliance-edge for
|
||||
more information.
|
||||
*/
|
||||
/** @file
|
||||
@brief Reliance Edge utilities only needed for tests.
|
||||
*/
|
||||
#ifndef REDTESTUTILS_H
|
||||
#define REDTESTUTILS_H
|
||||
|
||||
|
||||
#define ISDIGIT(c) (((c) >= '0') && ((c) <= '9'))
|
||||
|
||||
|
||||
void RedRandSeed(uint64_t ullSeed);
|
||||
uint64_t RedRand64(uint64_t *pullSeed);
|
||||
uint32_t RedRand32(uint32_t *pulSeed);
|
||||
|
||||
char *RedRatio(char *pBuffer, uint32_t ulBufferLen, uint64_t ullDividend, uint64_t ullDivisor, uint32_t ulDecPlaces);
|
||||
uint64_t RedMulDiv64(uint64_t ullBase, uint32_t ulMultiplier, uint64_t ullDivisor);
|
||||
uint64_t RedUint64DivMod32(uint64_t ullDividend, uint32_t ulDivisor, uint32_t *pulRemainder);
|
||||
uint64_t RedUint64DivMod64(uint64_t ullDividend, uint64_t ullDivisor, uint64_t *pullRemainder);
|
||||
|
||||
char *RedScaleBytes(uint32_t ulByteValue, char *pszBuffer, uint32_t ulBufferSize);
|
||||
char *RedScaleKB(uint32_t ulKBValue, char *pszBuffer, uint32_t ulBufferSize);
|
||||
uint32_t RedGetKBPerSecond(uint64_t ullKB, uint32_t ulMS);
|
||||
uint32_t RedGetKBPerSecondSectors(uint32_t ulBytesPerSector, uint64_t ullSectors, uint64_t ullUS);
|
||||
|
||||
int32_t RedAtoI(const char *pszNum);
|
||||
const char *RedHtoUL(const char *pszNum, uint32_t *pulNum);
|
||||
const char *RedHtoULL(const char *pszNum, uint64_t *pullNum);
|
||||
const char *RedNtoUL(const char *pszNum, uint32_t *pulNum);
|
||||
const char *RedNtoULL(const char *pszNum, uint64_t *pullNum);
|
||||
const char *RedSizeToUL(const char *pszNum, uint32_t *pulResult);
|
||||
|
||||
int32_t RedStrICmp(const char *pszStr1, const char *pszStr2);
|
||||
int32_t RedStrNICmp(const char *pszStr1, const char *pszStr2, uint32_t ulLen);
|
||||
char RedToLower(char c);
|
||||
|
||||
#include <stdarg.h>
|
||||
|
||||
#if REDCONF_OUTPUT == 1
|
||||
void RedPrintf(const char *pszFormat, ...);
|
||||
void RedVPrintf(const char *pszFormat, va_list arglist);
|
||||
#endif
|
||||
int32_t RedSNPrintf(char *pcBuffer, uint32_t ulBufferLen, const char *pszFormat, ...);
|
||||
int32_t RedVSNPrintf(char *pcBuffer, uint32_t ulBufferLen, const char *pszFormat, va_list arglist);
|
||||
|
||||
|
||||
#endif
|
||||
|
@@ -0,0 +1,37 @@
|
||||
/* ----> DO NOT REMOVE THE FOLLOWING NOTICE <----
|
||||
|
||||
Copyright (c) 2014-2015 Datalight, Inc.
|
||||
All Rights Reserved Worldwide.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; use version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but "AS-IS," WITHOUT ANY WARRANTY; without even the implied warranty
|
||||
of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
/* Businesses and individuals that for commercial or other reasons cannot
|
||||
comply with the terms of the GPLv2 license may obtain a commercial license
|
||||
before incorporating Reliance Edge into proprietary software for
|
||||
distribution in any form. Visit http://www.datalight.com/reliance-edge for
|
||||
more information.
|
||||
*/
|
||||
/** @file
|
||||
@brief Interfaces for common-code utilities for tools and tests.
|
||||
*/
|
||||
#ifndef REDTOOLCMN_H
|
||||
#define REDTOOLCMN_H
|
||||
|
||||
|
||||
uint8_t RedFindVolumeNumber(const char *pszVolume);
|
||||
bool RedConfirmOperation(const char *pszMessage);
|
||||
|
||||
|
||||
#endif
|
||||
|
@@ -0,0 +1,183 @@
|
||||
/* ----> DO NOT REMOVE THE FOLLOWING NOTICE <----
|
||||
|
||||
Copyright (c) 2014-2015 Datalight, Inc.
|
||||
All Rights Reserved Worldwide.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; use version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but "AS-IS," WITHOUT ANY WARRANTY; without even the implied warranty
|
||||
of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
/* Businesses and individuals that for commercial or other reasons cannot
|
||||
comply with the terms of the GPLv2 license may obtain a commercial license
|
||||
before incorporating Reliance Edge into proprietary software for
|
||||
distribution in any form. Visit http://www.datalight.com/reliance-edge for
|
||||
more information.
|
||||
*/
|
||||
#ifndef REDTOOLS_H
|
||||
#define REDTOOLS_H
|
||||
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <Windows.h>
|
||||
#define HOST_PATH_MAX MAX_PATH
|
||||
#else
|
||||
#include <linux/limits.h>
|
||||
#define HOST_PATH_MAX PATH_MAX
|
||||
#endif
|
||||
|
||||
|
||||
#if REDCONF_IMAGE_BUILDER == 1
|
||||
|
||||
#define MACRO_NAME_MAX_LEN 32
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint8_t bVolNumber;
|
||||
const char *pszInputDir;
|
||||
const char *pszOutputFile;
|
||||
#if REDCONF_API_POSIX == 1
|
||||
const char *pszVolName;
|
||||
#else
|
||||
const char *pszMapFile;
|
||||
const char *pszDefineFile;
|
||||
bool fNowarn;
|
||||
#endif
|
||||
} IMGBLDPARAM;
|
||||
|
||||
|
||||
void ImgbldParseParams(int argc, char *argv [], IMGBLDPARAM *pParam);
|
||||
int ImgbldStart(IMGBLDPARAM *pParam);
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
#if REDCONF_API_POSIX == 1
|
||||
char asOutFilePath[HOST_PATH_MAX];
|
||||
#else
|
||||
uint32_t ulOutFileIndex;
|
||||
#endif
|
||||
char asInFilePath[HOST_PATH_MAX];
|
||||
} FILEMAPPING;
|
||||
|
||||
|
||||
extern void *gpCopyBuffer;
|
||||
extern uint32_t gulCopyBufferSize;
|
||||
|
||||
|
||||
/* Implemented in ibposix.c
|
||||
*/
|
||||
#if REDCONF_API_POSIX == 1
|
||||
REDSTATUS IbPosixCopyDir(const char *pszVolName, const char *pszInDir);
|
||||
int IbPosixCreateDir(const char *pszVolName, const char *pszFullPath, const char *pszBasePath);
|
||||
int IbConvertPath(const char *pszVolName, const char *pszFullPath, const char *pszBasePath, char *szOutPath);
|
||||
#endif
|
||||
|
||||
|
||||
/* Implemented in ibfse.c
|
||||
*/
|
||||
#if REDCONF_API_FSE == 1
|
||||
typedef struct sFILELISTENTRY FILELISTENTRY;
|
||||
struct sFILELISTENTRY
|
||||
{
|
||||
FILEMAPPING fileMapping;
|
||||
FILELISTENTRY *pNext;
|
||||
};
|
||||
|
||||
|
||||
void FreeFileList(FILELISTENTRY **ppsFileList);
|
||||
|
||||
int IbFseGetFileList(const char *pszPath, const char *pszIndirPath, FILELISTENTRY **ppFileListHead);
|
||||
int IbFseOutputDefines(FILELISTENTRY *pFileList, const IMGBLDPARAM *pOptions);
|
||||
int IbFseCopyFiles(int volNum, const FILELISTENTRY *pFileList);
|
||||
#endif
|
||||
|
||||
|
||||
/* Implemented in os-specific space (ibwin.c and iblinux.c)
|
||||
*/
|
||||
#if REDCONF_API_POSIX == 1
|
||||
int IbPosixCopyDirRecursive(const char *pszVolName, const char *pszInDir);
|
||||
#endif
|
||||
#if REDCONF_API_FSE == 1
|
||||
int IbFseBuildFileList(const char *pszDirPath, FILELISTENTRY **ppFileListHead);
|
||||
#endif
|
||||
#if REDCONF_API_FSE == 1
|
||||
int IbSetRelativePath(char *pszPath, const char *pszParentPath);
|
||||
#endif
|
||||
bool IsRegularFile(const char *pszPath);
|
||||
|
||||
|
||||
/* Implemented in ibcommon.c
|
||||
*/
|
||||
int IbCopyFile(int volNum, const FILEMAPPING *pFileMapping);
|
||||
int IbCheckFileExists(const char *pszPath, bool *pfExists);
|
||||
|
||||
|
||||
/* Implemented separately in ibfse.c and ibposix.c
|
||||
*/
|
||||
int IbApiInit(void);
|
||||
int IbApiUninit(void);
|
||||
int IbWriteFile(int volNum, const FILEMAPPING *pFileMapping, uint64_t ullOffset, void *pData, uint32_t ulDataLen);
|
||||
|
||||
#endif /* IMAGE_BUILDER */
|
||||
|
||||
/* For image copier tool
|
||||
*/
|
||||
|
||||
#ifdef _WIN32
|
||||
#define HOST_PSEP '\\'
|
||||
#if !__STDC__
|
||||
#define snprintf _snprintf
|
||||
#define stat _stat
|
||||
#define S_IFDIR _S_IFDIR
|
||||
#define rmdir _rmdir
|
||||
#endif
|
||||
#else
|
||||
#define HOST_PSEP '/'
|
||||
#endif
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint8_t bVolNumber;
|
||||
const char *pszOutputDir;
|
||||
const char *pszBDevSpec;
|
||||
#if REDCONF_API_POSIX == 1
|
||||
const char *pszVolName;
|
||||
#endif
|
||||
bool fNoWarn;
|
||||
} IMGCOPYPARAM;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
#if REDCONF_API_POSIX == 1
|
||||
const char *pszVolume; /* Volume path prefix. */
|
||||
uint32_t ulVolPrefixLen; /* strlen(COPIER::pszVolume) */
|
||||
#else
|
||||
uint8_t bVolNum; /* Volume number. */
|
||||
#endif
|
||||
const char *pszOutputDir; /* Output directory path. */
|
||||
bool fNoWarn; /* If true, no warning to overwrite. */
|
||||
uint8_t *pbCopyBuffer; /* Buffer for copying file data. */
|
||||
} COPIER;
|
||||
|
||||
|
||||
void ImgcopyParseParams(int argc, char *argv [], IMGCOPYPARAM *pParam);
|
||||
int ImgcopyStart(IMGCOPYPARAM *pParam);
|
||||
|
||||
/* Implemented separately in imgcopywin.c and imgcopylinux.c. These functions
|
||||
print an error message and abort on failure.
|
||||
*/
|
||||
void ImgcopyMkdir(const char *pszDir);
|
||||
void ImgcopyRecursiveRmdir(const char *pszDir);
|
||||
|
||||
|
||||
#endif /* REDTOOLS_H */
|
||||
|
@@ -0,0 +1,71 @@
|
||||
/* ----> DO NOT REMOVE THE FOLLOWING NOTICE <----
|
||||
|
||||
Copyright (c) 2014-2015 Datalight, Inc.
|
||||
All Rights Reserved Worldwide.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; use version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but "AS-IS," WITHOUT ANY WARRANTY; without even the implied warranty
|
||||
of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
/* Businesses and individuals that for commercial or other reasons cannot
|
||||
comply with the terms of the GPLv2 license may obtain a commercial license
|
||||
before incorporating Reliance Edge into proprietary software for
|
||||
distribution in any form. Visit http://www.datalight.com/reliance-edge for
|
||||
more information.
|
||||
*/
|
||||
/** @file
|
||||
*/
|
||||
#ifndef REDUTILS_H
|
||||
#define REDUTILS_H
|
||||
|
||||
|
||||
#if REDCONF_ASSERTS == 1
|
||||
#define REDERROR() RedOsAssertFail(__FILE__, __LINE__)
|
||||
#define REDASSERT(EXP) ((EXP) ? (void)0 : REDERROR())
|
||||
#else
|
||||
#define REDERROR() ((void)0)
|
||||
#define REDASSERT(EXP) ((void)0)
|
||||
#endif
|
||||
|
||||
|
||||
void RedMemCpy(void *pDest, const void *pSrc, uint32_t ulLen);
|
||||
void RedMemMove(void *pDest, const void *pSrc, uint32_t ulLen);
|
||||
void RedMemSet(void *pDest, uint8_t bVal, uint32_t ulLen);
|
||||
int32_t RedMemCmp(const void *pMem1, const void *pMem2, uint32_t ulLen);
|
||||
|
||||
uint32_t RedStrLen(const char *pszStr);
|
||||
int32_t RedStrCmp(const char *pszStr1, const char *pszStr2);
|
||||
int32_t RedStrNCmp(const char *pszStr1, const char *pszStr2, uint32_t ulLen);
|
||||
void RedStrNCpy(char *pszDst, const char *pszSrc, uint32_t ulLen);
|
||||
|
||||
uint32_t RedCrc32Update(uint32_t ulInitCrc32, const void *pBuffer, uint32_t ulLength);
|
||||
uint32_t RedCrcNode(const void *pBuffer);
|
||||
|
||||
#if REDCONF_API_POSIX == 1
|
||||
uint32_t RedNameLen(const char *pszName);
|
||||
#endif
|
||||
|
||||
bool RedBitGet(const uint8_t *pbBitmap, uint32_t ulBit);
|
||||
void RedBitSet(uint8_t *pbBitmap, uint32_t ulBit);
|
||||
void RedBitClear(uint8_t *pbBitmap, uint32_t ulBit);
|
||||
|
||||
#ifdef REDCONF_ENDIAN_SWAP
|
||||
uint64_t RedRev64(uint64_t ullToRev);
|
||||
uint32_t RedRev32(uint32_t ulToRev);
|
||||
uint16_t RedRev16(uint16_t uToRev);
|
||||
#endif
|
||||
|
||||
void RedSignOn(void);
|
||||
|
||||
|
||||
#endif
|
||||
|
@@ -0,0 +1,111 @@
|
||||
/* ----> DO NOT REMOVE THE FOLLOWING NOTICE <----
|
||||
|
||||
Copyright (c) 2014-2015 Datalight, Inc.
|
||||
All Rights Reserved Worldwide.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; use version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but "AS-IS," WITHOUT ANY WARRANTY; without even the implied warranty
|
||||
of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
/* Businesses and individuals that for commercial or other reasons cannot
|
||||
comply with the terms of the GPLv2 license may obtain a commercial license
|
||||
before incorporating Reliance Edge into proprietary software for
|
||||
distribution in any form. Visit http://www.datalight.com/reliance-edge for
|
||||
more information.
|
||||
*/
|
||||
/** @file
|
||||
@brief Macros for version numbers, build number, and product information.
|
||||
*/
|
||||
#ifndef REDVER_H
|
||||
#define REDVER_H
|
||||
|
||||
|
||||
/** @brief Consecutive number assigned to each automated build.
|
||||
|
||||
<!-- This macro is updated automatically: do not edit! -->
|
||||
*/
|
||||
#define RED_BUILD_NUMBER "700"
|
||||
|
||||
#define RED_KIT_GPL 0U /* Open source GPL kit. */
|
||||
#define RED_KIT_COMMERCIAL 1U /* Commercially-licensed kit. */
|
||||
#define RED_KIT_SANDBOX 2U /* Not a kit: developer sandbox. */
|
||||
|
||||
/** @brief Indicates the Reliance Edge kit.
|
||||
|
||||
<!-- This macro is updated automatically: do not edit! -->
|
||||
*/
|
||||
#define RED_KIT RED_KIT_GPL
|
||||
|
||||
|
||||
/** @brief Version number to display in output.
|
||||
*/
|
||||
#define RED_VERSION "v2.0"
|
||||
|
||||
/** @brief Version number in hex.
|
||||
|
||||
The most significant byte is the major version number, etc.
|
||||
*/
|
||||
#define RED_VERSION_VAL 0x02000000U
|
||||
|
||||
/** @brief On-disk version number.
|
||||
|
||||
This is incremented only when the on-disk layout is updated in such a way
|
||||
which is incompatible with previously released versions of the file system.
|
||||
*/
|
||||
#define RED_DISK_LAYOUT_VERSION 1U
|
||||
|
||||
|
||||
/** @brief Base name of the file system product.
|
||||
*/
|
||||
#define RED_PRODUCT_BASE_NAME "Reliance Edge"
|
||||
|
||||
|
||||
/* Specifies whether the product is in alpha stage, beta stage, or neither.
|
||||
*/
|
||||
#if 0
|
||||
#if 0
|
||||
#define ALPHABETA " (Alpha)"
|
||||
#else
|
||||
#define ALPHABETA " (Beta)"
|
||||
#endif
|
||||
#else
|
||||
#define ALPHABETA ""
|
||||
#endif
|
||||
|
||||
/** @brief Full product name and version.
|
||||
*/
|
||||
#define RED_PRODUCT_NAME "Datalight " RED_PRODUCT_BASE_NAME " " RED_VERSION " Build " RED_BUILD_NUMBER ALPHABETA
|
||||
|
||||
|
||||
/** @brief Product copyright.
|
||||
*/
|
||||
#define RED_PRODUCT_LEGAL "Copyright (c) 2014-2017 Datalight, Inc. All Rights Reserved Worldwide."
|
||||
|
||||
|
||||
/** @brief Product patents.
|
||||
*/
|
||||
#define RED_PRODUCT_PATENT "Patents: US#7284101."
|
||||
|
||||
|
||||
/** @brief Product edition.
|
||||
*/
|
||||
#if RED_KIT == RED_KIT_GPL
|
||||
#define RED_PRODUCT_EDITION "Open-Source GPLv2 Edition -- Compiled " __DATE__ " at " __TIME__
|
||||
#elif RED_KIT == RED_KIT_COMMERCIAL
|
||||
#define RED_PRODUCT_EDITION "Commercial Edition -- Compiled " __DATE__ " at " __TIME__
|
||||
#else
|
||||
#define RED_PRODUCT_EDITION "Developer Sandbox -- Compiled " __DATE__ " at " __TIME__
|
||||
#endif
|
||||
|
||||
|
||||
#endif
|
||||
|
@@ -0,0 +1,141 @@
|
||||
/* ----> DO NOT REMOVE THE FOLLOWING NOTICE <----
|
||||
|
||||
Copyright (c) 2014-2015 Datalight, Inc.
|
||||
All Rights Reserved Worldwide.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; use version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but "AS-IS," WITHOUT ANY WARRANTY; without even the implied warranty
|
||||
of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
/* Businesses and individuals that for commercial or other reasons cannot
|
||||
comply with the terms of the GPLv2 license may obtain a commercial license
|
||||
before incorporating Reliance Edge into proprietary software for
|
||||
distribution in any form. Visit http://www.datalight.com/reliance-edge for
|
||||
more information.
|
||||
*/
|
||||
/** @file
|
||||
*/
|
||||
#ifndef REDVOLUME_H
|
||||
#define REDVOLUME_H
|
||||
|
||||
|
||||
/** @brief Per-volume configuration structure.
|
||||
|
||||
Contains the configuration values that may differ between volumes. Must be
|
||||
declared in an array in redconf.c in the Reliance Edge project directory and
|
||||
statically initialized with values representing the volume configuration of
|
||||
the target system.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
/** The sector size for the block device underlying the volume: the basic
|
||||
unit for reading and writing to the storage media. Commonly ranges
|
||||
between 512 and 4096, but any power-of-two value not greater than the
|
||||
block size will work.
|
||||
*/
|
||||
uint32_t ulSectorSize;
|
||||
|
||||
/** The number of sectors in this file system volume.
|
||||
*/
|
||||
uint64_t ullSectorCount;
|
||||
|
||||
/** Whether a sector write on the block device underlying the volume is
|
||||
atomic. It is atomic if when the sector write is interrupted, the
|
||||
contents of the sector are guaranteed to be either all of the new data,
|
||||
or all of the old data. If unsure, leave as false.
|
||||
*/
|
||||
bool fAtomicSectorWrite;
|
||||
|
||||
/** This is the maximum number of inodes (files and directories). This
|
||||
number includes the root directory inode (inode 2; created during
|
||||
format), but does not include inodes 0 or 1, which do not exist on
|
||||
disk. The number of inodes cannot be less than 1.
|
||||
*/
|
||||
uint32_t ulInodeCount;
|
||||
|
||||
/** This is the maximum number of times a block device I/O operation will
|
||||
be retried. If a block device read, write, or flush fails, Reliance
|
||||
Edge will try again up to this number of times until the operation is
|
||||
successful. Set this to 0 to disable retries.
|
||||
*/
|
||||
uint8_t bBlockIoRetries;
|
||||
|
||||
#if REDCONF_API_POSIX == 1
|
||||
/** The path prefix for the volume; for example, "VOL1:", "FlashDisk", etc.
|
||||
*/
|
||||
const char *pszPathPrefix;
|
||||
#endif
|
||||
} VOLCONF;
|
||||
|
||||
extern const VOLCONF gaRedVolConf[REDCONF_VOLUME_COUNT];
|
||||
extern const VOLCONF * CONST_IF_ONE_VOLUME gpRedVolConf;
|
||||
|
||||
|
||||
/** @brief Per-volume run-time data.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
/** Whether the volume is currently mounted.
|
||||
*/
|
||||
bool fMounted;
|
||||
|
||||
#if REDCONF_READ_ONLY == 0
|
||||
/** Whether the volume is read-only.
|
||||
*/
|
||||
bool fReadOnly;
|
||||
|
||||
/** The active automatic transaction mask.
|
||||
*/
|
||||
uint32_t ulTransMask;
|
||||
#endif
|
||||
|
||||
/** The power of 2 difference between sector size and block size.
|
||||
*/
|
||||
uint8_t bBlockSectorShift;
|
||||
|
||||
/** The number of logical blocks in this file system volume. The unit here
|
||||
is the global block size.
|
||||
*/
|
||||
uint32_t ulBlockCount;
|
||||
|
||||
/** The total number of allocable blocks; Also the maximum count of free
|
||||
blocks.
|
||||
*/
|
||||
uint32_t ulBlocksAllocable;
|
||||
|
||||
/** The maximum number of bytes that an inode is capable of addressing.
|
||||
*/
|
||||
uint64_t ullMaxInodeSize;
|
||||
|
||||
/** The current metadata sequence number. This value is included in all
|
||||
metadata nodes and incremented every time a metadata node is written.
|
||||
It is assumed to never wrap around.
|
||||
*/
|
||||
uint64_t ullSequence;
|
||||
} VOLUME;
|
||||
|
||||
/* Array of VOLUME structures, populated at during RedCoreInit().
|
||||
*/
|
||||
extern VOLUME gaRedVolume[REDCONF_VOLUME_COUNT];
|
||||
|
||||
/* Volume number currently being accessed; populated during
|
||||
RedCoreVolSetCurrent().
|
||||
*/
|
||||
extern CONST_IF_ONE_VOLUME uint8_t gbRedVolNum;
|
||||
|
||||
/* Pointer to the volume currently being accessed; populated during
|
||||
RedCoreVolSetCurrent().
|
||||
*/
|
||||
extern VOLUME * CONST_IF_ONE_VOLUME gpRedVolume;
|
||||
|
||||
#endif
|
||||
|
@@ -0,0 +1,244 @@
|
||||
/* ----> DO NOT REMOVE THE FOLLOWING NOTICE <----
|
||||
|
||||
Copyright (c) 2014-2015 Datalight, Inc.
|
||||
All Rights Reserved Worldwide.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; use version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but "AS-IS," WITHOUT ANY WARRANTY; without even the implied warranty
|
||||
of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
/* Businesses and individuals that for commercial or other reasons cannot
|
||||
comply with the terms of the GPLv2 license may obtain a commercial license
|
||||
before incorporating Reliance Edge into proprietary software for
|
||||
distribution in any form. Visit http://www.datalight.com/reliance-edge for
|
||||
more information.
|
||||
*/
|
||||
/** @file
|
||||
@brief Macros to encapsulate MISRA C:2012 deviations in OS-specific code.
|
||||
*/
|
||||
#ifndef REDOSDEVIATIONS_H
|
||||
#define REDOSDEVIATIONS_H
|
||||
|
||||
|
||||
#if REDCONF_OUTPUT == 1
|
||||
/* Needed for PRINT_ASSERT() and OUTPUT_CHARACTER().
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#endif
|
||||
|
||||
|
||||
#if (REDCONF_ASSERTS == 1) && (REDCONF_OUTPUT == 1)
|
||||
/** Print a formatted message for an assertion.
|
||||
|
||||
Usages of this macro deviate from MISRA C:2012 Rule 21.6 (required). Using
|
||||
printf() is the most convenient way to output this information; and the risk
|
||||
of "unspecified, undefined and implementation-defined" behavior causing
|
||||
problems (as cited in the rationale for the rule) is small. The driver does
|
||||
not depend on this string being outputted correctly. Furthermore, use of
|
||||
printf() disappears when either asserts or output are disabled.
|
||||
|
||||
As Rule 21.6 is required, a separate deviation record is required.
|
||||
*/
|
||||
#define PRINT_ASSERT(file, line) \
|
||||
printf("Assertion failed in \"%s\" at line %u\n\r", ((file) == NULL) ? "" : (file), (unsigned)(line))
|
||||
#endif
|
||||
|
||||
|
||||
/** Cast a value to unsigned long.
|
||||
|
||||
Usages of this macro deviate from MISRA C:2012 Directive 4.6. This macro is
|
||||
used in two places to cast a uint64_t value (used by the block device
|
||||
abstraction for sector numbers) to unsigned long, since third-party code
|
||||
which is not under the control of this project uses unsigned long for sector
|
||||
numbers. The cast is guaranteed to not lose any information, since when the
|
||||
disk is opened the sector count is verified to be less than or equal to an
|
||||
unsigned long value. The text of the directive mentions that "it might be
|
||||
desirable not to apply this guideline when interfacing with ... code outside
|
||||
the project's control", which describes the situation for this deviation.
|
||||
|
||||
As Directive 4.6 is advisory, a deviation record is not required. This
|
||||
notice is the only record of the deviation.
|
||||
*/
|
||||
#define CAST_ULONG(ull) ((unsigned long)(ull))
|
||||
|
||||
|
||||
/** Cast a const-qualified pointer to a pointer which is *not* const-qualified.
|
||||
|
||||
Usages of this macro deviate from MISRA C:2012 Rule 11.8. This macro is
|
||||
used in exactly one place in order to cope with a poorly designed
|
||||
third-party interface. Reliance Edge, at every level of the stack, uses
|
||||
const-qualified pointers for buffers used in write operations, since the
|
||||
data is read from the buffer, and the buffer does not need to be modified
|
||||
(consistent with Rule 8.13). One of the third-party block device interfaces
|
||||
that Reliance Edge interfaces with does not follow this convention: it uses
|
||||
an unqualified pointer for the buffer parameter of its sector write
|
||||
function. This forces the need for the cast to avoid warnings. The
|
||||
implementation of the sector write function is provided by the user, so it
|
||||
is to be hoped that the buffer is not actually modified.
|
||||
|
||||
As Rule 11.8 is required, a separate deviation record is required.
|
||||
*/
|
||||
#define CAST_AWAY_CONST(type, ptr) ((type *)(ptr))
|
||||
|
||||
|
||||
/** Allocate zero-initialized (cleared) memory.
|
||||
|
||||
All usages of this macro deviate from MISRA C:2012 Directive 4.12 (required)
|
||||
and Rule 21.3 (required). In the context of the single place it is actually
|
||||
used, this macro also deviates from Rule 22.1 (required).
|
||||
|
||||
This macro is used in the FreeRTOS block device code in order to allocate a
|
||||
RAM disk, when that implementation of the block device is selected. The
|
||||
primary rationale for all these deviations is that a) the RAM disk cannot be
|
||||
allocated statically (since the volume information is stored in a
|
||||
structure), and b) the RAM disk is primarily intended as a temporary testing
|
||||
tool for users who want to try out Reliance Edge before the real storage
|
||||
media is available. In most real systems, Reliance Edge is used with
|
||||
non-volatile storage like SD/MMC or eMMC, not with RAM disks.
|
||||
|
||||
Rule 22.1 states that all resources which are allocated must also be
|
||||
explicitly freed. The RAM disk is allocated and never freed, deviating from
|
||||
that rule. This is done because the data in the RAM disk is emulating a
|
||||
non-volatile storage medium, and thus needs to persist even after the block
|
||||
device is closed, to allow the file system to be ormatted and then mounted,
|
||||
or unmounted and remounted in the course of a test. Thus the memory will
|
||||
remain allocated until the target device is rebooted. This is assumed to be
|
||||
acceptable for the primary purpose of the RAM disk, which is preliminary
|
||||
testing.
|
||||
|
||||
As Directive 4.12, Rule 21.3, and Rule 22.1 are all required, separate
|
||||
deviation records are required.
|
||||
*/
|
||||
#define ALLOCATE_CLEARED_MEMORY(nelem, elsize) calloc(nelem, elsize)
|
||||
|
||||
|
||||
#if REDCONF_OUTPUT == 1
|
||||
/** Output a character to a serial port or other display device.
|
||||
|
||||
Usages of this macro deviate from MISRA C:2012 Rule 21.6 (required).
|
||||
FreeRTOS does not include a standard method of printing characters, so
|
||||
putchar() is the most convenient and portable way to accomplish the task.
|
||||
The risk of "unspecified, undefined and implementation-defined" behavior
|
||||
causing problems (as cited in the rationale for the rule) is small. The
|
||||
driver does not depend on the character being outputted correctly.
|
||||
Furthermore, use of putchar() disappears when output is disabled.
|
||||
|
||||
As Rule 21.6 is required, a separate deviation record is required.
|
||||
*/
|
||||
#define OUTPUT_CHARACTER(ch) (void)putchar(ch)
|
||||
#endif
|
||||
|
||||
|
||||
#if (REDCONF_TASK_COUNT > 1U) && (REDCONF_API_POSIX == 1)
|
||||
/** Cast a TaskHandle_t (a pointer type) to uintptr_t.
|
||||
|
||||
Usage of this macro deivate from MISRA-C:2012 Rule 11.4 (advisory). This
|
||||
macro is used for the FreeRTOS version of RedOsTaskId(). Some RTOSes
|
||||
natively use an integer for task IDs; others use pointers. RedOsTaskId()
|
||||
uses integers, FreeRTOS uses pointers; to reconcile this difference, the
|
||||
pointer must be cast to integer. This is fairly safe, since the resulting
|
||||
integer is never cast back to a pointer; and although the integer
|
||||
representation of a pointer is implementation-defined, the representation is
|
||||
irrelevant provided that unique pointers are converted to unique integers.
|
||||
|
||||
As Rule 11.4 is advisory, a deviation record is not required. This notice
|
||||
is the only record of the deviation.
|
||||
*/
|
||||
#define CAST_TASK_PTR_TO_UINTPTR(taskptr) ((uintptr_t)(taskptr))
|
||||
#endif
|
||||
|
||||
|
||||
/** Ignore the return value of a function (cast to void)
|
||||
|
||||
Usages of this macro deviate from MISRA C:2012 Directive 4.7, which states
|
||||
that error information must be checked immediately after a function returns
|
||||
potential error information.
|
||||
|
||||
If asserts and output are enabled, then this macro is used to document that
|
||||
the return value of printf() is ignored. A failure of printf() does not
|
||||
impact the filesystem core, nor is there anything the filesystem can do to
|
||||
respond to such an error (especially since it occurs within an assert).
|
||||
Thus, the most reasonable action is to ignore the error.
|
||||
|
||||
In the STM32 SDIO block device implementation, errors are also ignored in an
|
||||
IRQ interrupt handler. This is the most reasonable action to take for two
|
||||
reasons: (a) it would be dangerous to spend processor time responding to the
|
||||
error inside the IRQ handler; (b) it has been verified that the same error
|
||||
is propegated to the DiskRead/Write method, which does return the error to
|
||||
the core.
|
||||
|
||||
In the Atmel SD/MMC block device implementation, error information from
|
||||
sd_mmc_read_capacity() is ignored. This is a reasonable action because all
|
||||
of the possible error conditions were eliminated by a previous check.
|
||||
sd_mmc_read_capacity() fails under the same conditions as
|
||||
sd_mmc_test_unit_ready(), which was checked ealier in the same function.
|
||||
|
||||
In the mutex module, error information returned from the mutex release
|
||||
function is ignored when asserts are disabled. This is a reasonable action
|
||||
because the mutex release function (xSemaphoreGive) is documented only to
|
||||
fail if the mutex was not obtained correctly, which can be demonstrably
|
||||
avoided.
|
||||
|
||||
As Directive 4.7 is required, a separate deviation record is required.
|
||||
*/
|
||||
#define IGNORE_ERRORS(fn) ((void) (fn))
|
||||
|
||||
|
||||
/** @brief Determine whether a pointer is aligned on a 32-bit boundary.
|
||||
|
||||
This is used to determine whether a data buffer meets the requirements of
|
||||
the underlying block device implementation. When transferring data via
|
||||
DMA (Direct Memory Access) on an STM32 device, the data buffer must be cast
|
||||
as a uint32 pointer, and unexpected behavior may occur if the buffer is not
|
||||
aligned correctly.
|
||||
|
||||
There is no way to perform this check without deviating from MISRA C rules
|
||||
against casting pointers to integer types. Usage of this macro deviates
|
||||
from MISRA C:2012 Rule 11.4 (advisory). The main rationale the rule cites
|
||||
against converting pointers to integers is that the chosen integer type may
|
||||
not be able to represent the pointer; this is a non-issue here since we use
|
||||
uintptr_t. The text says the rule still applies when using uintptr_t due to
|
||||
concern about unaligned pointers, but that is not an issue here since the
|
||||
integer value of the pointer is not saved and not converted back into a
|
||||
pointer and dereferenced. The result of casting a pointer to a sufficiently
|
||||
large integer is implementation-defined, but macros similar to this one have
|
||||
been used by Datalight for a long time in a wide variety of environments and
|
||||
they have always worked as expected.
|
||||
|
||||
This deviation only occurs when using the STM32 SDIO block device
|
||||
implementation.
|
||||
|
||||
As Rule 11.4 is advisory, a deviation record is not required. This notice
|
||||
is the only record of deviation.
|
||||
*/
|
||||
#define IS_UINT32_ALIGNED_PTR(ptr) (((uintptr_t)(ptr) & (sizeof(uint32_t) - 1U)) == 0U)
|
||||
|
||||
|
||||
/** @brief Cast a 32-bit aligned void pointer to a uint32 pointer.
|
||||
|
||||
Usages of this macro deviate from MISRA C:2012 Rule 11.5 (advisory). A
|
||||
cast from a void pointer to an object pointer is discouraged because of
|
||||
potential alignment issues. However, this macro is only used to cast
|
||||
pointers that have already been tested to be 32-bit aligned, so the
|
||||
operation will be safe.
|
||||
|
||||
This deviation only occurs when using the STM32 SDIO block device
|
||||
implementation.
|
||||
|
||||
As rule 11.5 is advisory, a deviation record is not required. This notice
|
||||
is the only record of the deviation.
|
||||
*/
|
||||
#define CAST_UINT32_PTR(ptr) ((uint32_t *) (ptr))
|
||||
|
||||
|
||||
#endif
|
||||
|
@@ -0,0 +1,42 @@
|
||||
/* ----> DO NOT REMOVE THE FOLLOWING NOTICE <----
|
||||
|
||||
Copyright (c) 2014-2015 Datalight, Inc.
|
||||
All Rights Reserved Worldwide.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; use version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but "AS-IS," WITHOUT ANY WARRANTY; without even the implied warranty
|
||||
of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
/* Businesses and individuals that for commercial or other reasons cannot
|
||||
comply with the terms of the GPLv2 license may obtain a commercial license
|
||||
before incorporating Reliance Edge into proprietary software for
|
||||
distribution in any form. Visit http://www.datalight.com/reliance-edge for
|
||||
more information.
|
||||
*/
|
||||
/** @file
|
||||
@brief Defines OS-specific types for use in common code.
|
||||
*/
|
||||
#ifndef REDOSTYPES_H
|
||||
#define REDOSTYPES_H
|
||||
|
||||
|
||||
/** @brief Implementation-defined timestamp type.
|
||||
|
||||
This can be an integer, a structure, or a pointer: anything that is
|
||||
convenient for the implementation. Since the underlying type is not fixed,
|
||||
common code should treat this as an opaque type.
|
||||
*/
|
||||
typedef uint32_t REDTIMESTAMP;
|
||||
|
||||
|
||||
#endif
|
||||
|
@@ -0,0 +1,56 @@
|
||||
/* ----> DO NOT REMOVE THE FOLLOWING NOTICE <----
|
||||
|
||||
Copyright (c) 2014-2015 Datalight, Inc.
|
||||
All Rights Reserved Worldwide.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; use version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but "AS-IS," WITHOUT ANY WARRANTY; without even the implied warranty
|
||||
of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
/* Businesses and individuals that for commercial or other reasons cannot
|
||||
comply with the terms of the GPLv2 license may obtain a commercial license
|
||||
before incorporating Reliance Edge into proprietary software for
|
||||
distribution in any form. Visit http://www.datalight.com/reliance-edge for
|
||||
more information.
|
||||
*/
|
||||
/** @file
|
||||
@brief Implements assertion handling.
|
||||
*/
|
||||
#include <redfs.h>
|
||||
|
||||
#if REDCONF_ASSERTS == 1
|
||||
|
||||
#include <redosdeviations.h>
|
||||
|
||||
|
||||
/** @brief Invoke the native assertion handler.
|
||||
|
||||
@param pszFileName Null-terminated string containing the name of the file
|
||||
where the assertion fired.
|
||||
@param ulLineNum Line number in @p pszFileName where the assertion
|
||||
fired.
|
||||
*/
|
||||
void RedOsAssertFail(
|
||||
const char *pszFileName,
|
||||
uint32_t ulLineNum)
|
||||
{
|
||||
#if REDCONF_OUTPUT == 1
|
||||
IGNORE_ERRORS(PRINT_ASSERT(pszFileName, ulLineNum));
|
||||
#endif
|
||||
|
||||
while(true)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,79 @@
|
||||
/* ----> DO NOT REMOVE THE FOLLOWING NOTICE <----
|
||||
|
||||
Copyright (c) 2014-2015 Datalight, Inc.
|
||||
All Rights Reserved Worldwide.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; use version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but "AS-IS," WITHOUT ANY WARRANTY; without even the implied warranty
|
||||
of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
/* Businesses and individuals that for commercial or other reasons cannot
|
||||
comply with the terms of the GPLv2 license may obtain a commercial license
|
||||
before incorporating Reliance Edge into proprietary software for
|
||||
distribution in any form. Visit http://www.datalight.com/reliance-edge for
|
||||
more information.
|
||||
*/
|
||||
/** @file
|
||||
@brief Implements real-time clock functions.
|
||||
*/
|
||||
#include <redfs.h>
|
||||
|
||||
|
||||
/** @brief Initialize the real time clock.
|
||||
|
||||
The behavior of calling this function when the RTC is already initialized
|
||||
is undefined.
|
||||
|
||||
@return A negated ::REDSTATUS code indicating the operation result.
|
||||
|
||||
@retval 0 Operation was successful.
|
||||
*/
|
||||
REDSTATUS RedOsClockInit(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/** @brief Uninitialize the real time clock.
|
||||
|
||||
The behavior of calling this function when the RTC is not initialized is
|
||||
undefined.
|
||||
|
||||
@return A negated ::REDSTATUS code indicating the operation result.
|
||||
|
||||
@retval 0 Operation was successful.
|
||||
*/
|
||||
REDSTATUS RedOsClockUninit(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/** @brief Get the date/time.
|
||||
|
||||
The behavior of calling this function when the RTC is not initialized is
|
||||
undefined.
|
||||
|
||||
@return The number of seconds since January 1, 1970 excluding leap seconds
|
||||
(in other words, standard Unix time). If the resolution or epoch
|
||||
of the RTC is different than this, the implementation must convert
|
||||
it to the expected representation.
|
||||
*/
|
||||
uint32_t RedOsClockGetTime(void)
|
||||
{
|
||||
/* FreeRTOS does not provide an RTC abstraction since most of the systems
|
||||
it targets have no RTC hardware. If your hardware includes an RTC that
|
||||
you would like to use, this function must be customized.
|
||||
*/
|
||||
return 0;
|
||||
}
|
||||
|
@@ -0,0 +1,134 @@
|
||||
/* ----> DO NOT REMOVE THE FOLLOWING NOTICE <----
|
||||
|
||||
Copyright (c) 2014-2015 Datalight, Inc.
|
||||
All Rights Reserved Worldwide.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; use version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but "AS-IS," WITHOUT ANY WARRANTY; without even the implied warranty
|
||||
of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
/* Businesses and individuals that for commercial or other reasons cannot
|
||||
comply with the terms of the GPLv2 license may obtain a commercial license
|
||||
before incorporating Reliance Edge into proprietary software for
|
||||
distribution in any form. Visit http://www.datalight.com/reliance-edge for
|
||||
more information.
|
||||
*/
|
||||
/** @file
|
||||
@brief Implements a synchronization object to provide mutual exclusion.
|
||||
*/
|
||||
#include <FreeRTOS.h>
|
||||
#include <semphr.h>
|
||||
|
||||
#include <redfs.h>
|
||||
#include <redosdeviations.h>
|
||||
|
||||
#if REDCONF_TASK_COUNT > 1U
|
||||
|
||||
|
||||
static SemaphoreHandle_t xMutex;
|
||||
#if defined(configSUPPORT_STATIC_ALLOCATION) && (configSUPPORT_STATIC_ALLOCATION == 1)
|
||||
static StaticSemaphore_t xMutexBuffer;
|
||||
#endif
|
||||
|
||||
|
||||
/** @brief Initialize the mutex.
|
||||
|
||||
After initialization, the mutex is in the released state.
|
||||
|
||||
The behavior of calling this function when the mutex is still initialized
|
||||
is undefined.
|
||||
|
||||
@return A negated ::REDSTATUS code indicating the operation result.
|
||||
|
||||
@retval 0 Operation was successful.
|
||||
*/
|
||||
REDSTATUS RedOsMutexInit(void)
|
||||
{
|
||||
REDSTATUS ret = 0;
|
||||
|
||||
#if defined(configSUPPORT_STATIC_ALLOCATION) && (configSUPPORT_STATIC_ALLOCATION == 1)
|
||||
xMutex = xSemaphoreCreateMutexStatic(&xMutexBuffer);
|
||||
|
||||
if(xMutex == NULL)
|
||||
{
|
||||
/* The only error case for xSemaphoreCreateMutexStatic is that the mutex
|
||||
buffer parameter is NULL, which is not the case.
|
||||
*/
|
||||
REDERROR();
|
||||
ret = -RED_EINVAL;
|
||||
}
|
||||
|
||||
#else
|
||||
xMutex = xSemaphoreCreateMutex();
|
||||
if(xMutex == NULL)
|
||||
{
|
||||
ret = -RED_ENOMEM;
|
||||
}
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/** @brief Uninitialize the mutex.
|
||||
|
||||
The behavior of calling this function when the mutex is not initialized is
|
||||
undefined; likewise, the behavior of uninitializing the mutex when it is
|
||||
in the acquired state is undefined.
|
||||
|
||||
@return A negated ::REDSTATUS code indicating the operation result.
|
||||
|
||||
@retval 0 Operation was successful.
|
||||
*/
|
||||
REDSTATUS RedOsMutexUninit(void)
|
||||
{
|
||||
vSemaphoreDelete(xMutex);
|
||||
xMutex = NULL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/** @brief Acquire the mutex.
|
||||
|
||||
The behavior of calling this function when the mutex is not initialized is
|
||||
undefined; likewise, the behavior of recursively acquiring the mutex is
|
||||
undefined.
|
||||
*/
|
||||
void RedOsMutexAcquire(void)
|
||||
{
|
||||
while(xSemaphoreTake(xMutex, portMAX_DELAY) != pdTRUE)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/** @brief Release the mutex.
|
||||
|
||||
The behavior is undefined in the following cases:
|
||||
|
||||
- Releasing the mutex when the mutex is not initialized.
|
||||
- Releasing the mutex when it is not in the acquired state.
|
||||
- Releasing the mutex from a task or thread other than the one which
|
||||
acquired the mutex.
|
||||
*/
|
||||
void RedOsMutexRelease(void)
|
||||
{
|
||||
BaseType_t xSuccess;
|
||||
|
||||
xSuccess = xSemaphoreGive(xMutex);
|
||||
REDASSERT(xSuccess == pdTRUE);
|
||||
IGNORE_ERRORS(xSuccess);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@@ -0,0 +1,70 @@
|
||||
/* ----> DO NOT REMOVE THE FOLLOWING NOTICE <----
|
||||
|
||||
Copyright (c) 2014-2015 Datalight, Inc.
|
||||
All Rights Reserved Worldwide.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; use version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but "AS-IS," WITHOUT ANY WARRANTY; without even the implied warranty
|
||||
of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
/* Businesses and individuals that for commercial or other reasons cannot
|
||||
comply with the terms of the GPLv2 license may obtain a commercial license
|
||||
before incorporating Reliance Edge into proprietary software for
|
||||
distribution in any form. Visit http://www.datalight.com/reliance-edge for
|
||||
more information.
|
||||
*/
|
||||
/** @file
|
||||
@brief Implements outputting a character string.
|
||||
*/
|
||||
#include <redfs.h>
|
||||
|
||||
#if REDCONF_OUTPUT == 1
|
||||
|
||||
#include <redosdeviations.h>
|
||||
|
||||
|
||||
/** @brief Write a string to a user-visible output location.
|
||||
|
||||
Write a null-terminated string to the serial port, console, terminal, or
|
||||
other display device, such that the text is visible to the user.
|
||||
|
||||
@param pszString A null-terminated string.
|
||||
*/
|
||||
void RedOsOutputString(
|
||||
const char *pszString)
|
||||
{
|
||||
if(pszString == NULL)
|
||||
{
|
||||
REDERROR();
|
||||
}
|
||||
else
|
||||
{
|
||||
uint32_t ulIdx = 0U;
|
||||
|
||||
while(pszString[ulIdx] != '\0')
|
||||
{
|
||||
OUTPUT_CHARACTER(pszString[ulIdx]);
|
||||
|
||||
/* Serial output often requires a \r to print newlines correctly.
|
||||
*/
|
||||
if(pszString[ulIdx] == '\n')
|
||||
{
|
||||
OUTPUT_CHARACTER('\r');
|
||||
}
|
||||
|
||||
ulIdx++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@@ -0,0 +1,68 @@
|
||||
/* ----> DO NOT REMOVE THE FOLLOWING NOTICE <----
|
||||
|
||||
Copyright (c) 2014-2015 Datalight, Inc.
|
||||
All Rights Reserved Worldwide.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; use version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but "AS-IS," WITHOUT ANY WARRANTY; without even the implied warranty
|
||||
of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
/* Businesses and individuals that for commercial or other reasons cannot
|
||||
comply with the terms of the GPLv2 license may obtain a commercial license
|
||||
before incorporating Reliance Edge into proprietary software for
|
||||
distribution in any form. Visit http://www.datalight.com/reliance-edge for
|
||||
more information.
|
||||
*/
|
||||
/** @file
|
||||
@brief Implements task functions.
|
||||
*/
|
||||
#include <FreeRTOS.h>
|
||||
#include <task.h>
|
||||
|
||||
#include <redfs.h>
|
||||
|
||||
#if (REDCONF_TASK_COUNT > 1U) && (REDCONF_API_POSIX == 1)
|
||||
|
||||
#include <redosdeviations.h>
|
||||
|
||||
#if INCLUDE_xTaskGetCurrentTaskHandle != 1
|
||||
#error "INCLUDE_xTaskGetCurrentTaskHandle must be 1 when REDCONF_TASK_COUNT > 1 and REDCONF_API_POSIX == 1"
|
||||
#endif
|
||||
|
||||
|
||||
/** @brief Get the current task ID.
|
||||
|
||||
This task ID must be unique for all tasks using the file system.
|
||||
|
||||
@return The task ID. Must not be 0.
|
||||
*/
|
||||
uint32_t RedOsTaskId(void)
|
||||
{
|
||||
/* Simply casting the xTaskGetCurrentTaskHandle() return value results in
|
||||
warnings from some compilers, so use variables.
|
||||
*/
|
||||
TaskHandle_t xTask = xTaskGetCurrentTaskHandle();
|
||||
uintptr_t taskptr = CAST_TASK_PTR_TO_UINTPTR(xTask);
|
||||
uint32_t ulTaskPtr = (uint32_t)taskptr;
|
||||
|
||||
/* Assert no information was lost casting from uintptr_t to uint32_t.
|
||||
*/
|
||||
REDASSERT(ulTaskPtr == taskptr);
|
||||
|
||||
/* NULL is a valid task handle in FreeRTOS, so add one to all task IDs.
|
||||
*/
|
||||
REDASSERT((ulTaskPtr + 1U) != 0U);
|
||||
return ulTaskPtr + 1U;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@@ -0,0 +1,109 @@
|
||||
/* ----> DO NOT REMOVE THE FOLLOWING NOTICE <----
|
||||
|
||||
Copyright (c) 2014-2015 Datalight, Inc.
|
||||
All Rights Reserved Worldwide.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; use version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but "AS-IS," WITHOUT ANY WARRANTY; without even the implied warranty
|
||||
of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
/* Businesses and individuals that for commercial or other reasons cannot
|
||||
comply with the terms of the GPLv2 license may obtain a commercial license
|
||||
before incorporating Reliance Edge into proprietary software for
|
||||
distribution in any form. Visit http://www.datalight.com/reliance-edge for
|
||||
more information.
|
||||
*/
|
||||
/** @file
|
||||
@brief Implements timestamp functions.
|
||||
|
||||
The functionality implemented herein is not needed for the file system
|
||||
driver, only to provide accurate results with performance tests.
|
||||
*/
|
||||
#include <FreeRTOS.h>
|
||||
#include <task.h>
|
||||
|
||||
#include <redfs.h>
|
||||
|
||||
|
||||
/* configTICK_RATE_HZ is almost always 100, 250, 500, or 1000. If
|
||||
1000000U % configTICK_RATE_HZ != 0, then RedOsTimePassed() will be a
|
||||
little inaccurate.
|
||||
*/
|
||||
#define MICROSECS_PER_TICK (1000000U / configTICK_RATE_HZ)
|
||||
|
||||
|
||||
/** @brief Initialize the timestamp service.
|
||||
|
||||
The behavior of invoking this function when timestamps are already
|
||||
initialized is undefined.
|
||||
|
||||
@return A negated ::REDSTATUS code indicating the operation result.
|
||||
|
||||
@retval 0 Operation was successful.
|
||||
@retval -RED_ENOSYS The timestamp service has not been implemented.
|
||||
*/
|
||||
REDSTATUS RedOsTimestampInit(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/** @brief Uninitialize the timestamp service.
|
||||
|
||||
The behavior of invoking this function when timestamps are not initialized
|
||||
is undefined.
|
||||
|
||||
@return A negated ::REDSTATUS code indicating the operation result.
|
||||
|
||||
@retval 0 Operation was successful.
|
||||
*/
|
||||
REDSTATUS RedOsTimestampUninit(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/** @brief Retrieve a timestamp.
|
||||
|
||||
The behavior of invoking this function when timestamps are not initialized
|
||||
is undefined
|
||||
|
||||
@return A timestamp which can later be passed to RedOsTimePassed() to
|
||||
determine the amount of time which passed between the two calls.
|
||||
*/
|
||||
REDTIMESTAMP RedOsTimestamp(void)
|
||||
{
|
||||
return xTaskGetTickCount();
|
||||
}
|
||||
|
||||
|
||||
/** @brief Determine how much time has passed since a timestamp was retrieved.
|
||||
|
||||
The behavior of invoking this function when timestamps are not initialized
|
||||
is undefined.
|
||||
|
||||
@param tsSince A timestamp acquired earlier via RedOsTimestamp().
|
||||
|
||||
@return The number of microseconds which have passed since @p tsSince.
|
||||
*/
|
||||
uint64_t RedOsTimePassed(
|
||||
REDTIMESTAMP tsSince)
|
||||
{
|
||||
/* This works even if the tick count has wrapped around, provided it has
|
||||
only wrapped around once.
|
||||
*/
|
||||
uint32_t ulTicksPassed = (uint32_t)xTaskGetTickCount() - tsSince;
|
||||
uint64_t ullMicrosecs = (uint64_t)ulTicksPassed * MICROSECS_PER_TICK;
|
||||
|
||||
return ullMicrosecs;
|
||||
}
|
||||
|
448
FreeRTOSv10.2.1/FreeRTOS-Plus/Source/Reliance-Edge/posix/path.c
Normal file
448
FreeRTOSv10.2.1/FreeRTOS-Plus/Source/Reliance-Edge/posix/path.c
Normal file
@@ -0,0 +1,448 @@
|
||||
/* ----> DO NOT REMOVE THE FOLLOWING NOTICE <----
|
||||
|
||||
Copyright (c) 2014-2015 Datalight, Inc.
|
||||
All Rights Reserved Worldwide.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; use version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but "AS-IS," WITHOUT ANY WARRANTY; without even the implied warranty
|
||||
of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
/* Businesses and individuals that for commercial or other reasons cannot
|
||||
comply with the terms of the GPLv2 license may obtain a commercial license
|
||||
before incorporating Reliance Edge into proprietary software for
|
||||
distribution in any form. Visit http://www.datalight.com/reliance-edge for
|
||||
more information.
|
||||
*/
|
||||
/** @file
|
||||
@brief Implements path utilities for the POSIX-like API layer.
|
||||
*/
|
||||
#include <redfs.h>
|
||||
|
||||
#if REDCONF_API_POSIX == 1
|
||||
|
||||
#include <redcoreapi.h>
|
||||
#include <redvolume.h>
|
||||
#include <redposix.h>
|
||||
#include <redpath.h>
|
||||
|
||||
|
||||
static bool IsRootDir(const char *pszLocalPath);
|
||||
static bool PathHasMoreNames(const char *pszPathIdx);
|
||||
|
||||
|
||||
/** @brief Split a path into its component parts: a volume and a volume-local
|
||||
path.
|
||||
|
||||
@param pszPath The path to split.
|
||||
@param pbVolNum On successful return, if non-NULL, populated with
|
||||
the volume number extracted from the path.
|
||||
@param ppszLocalPath On successful return, populated with the
|
||||
volume-local path: the path stripped of any volume
|
||||
path prefixing. If this parameter is NULL, that
|
||||
indicates there should be no local path, and any
|
||||
characters beyond the prefix (other than path
|
||||
separators) are treated as an error.
|
||||
|
||||
@return A negated ::REDSTATUS code indicating the operation result.
|
||||
|
||||
@retval 0 Operation was successful.
|
||||
@retval -RED_EINVAL @p pszPath is `NULL`.
|
||||
@retval -RED_ENOENT @p pszPath could not be matched to any volume; or
|
||||
@p ppszLocalPath is NULL but @p pszPath includes a local
|
||||
path.
|
||||
*/
|
||||
REDSTATUS RedPathSplit(
|
||||
const char *pszPath,
|
||||
uint8_t *pbVolNum,
|
||||
const char **ppszLocalPath)
|
||||
{
|
||||
REDSTATUS ret = 0;
|
||||
|
||||
if(pszPath == NULL)
|
||||
{
|
||||
ret = -RED_EINVAL;
|
||||
}
|
||||
else
|
||||
{
|
||||
const char *pszLocalPath = pszPath;
|
||||
uint8_t bMatchVol = UINT8_MAX;
|
||||
uint32_t ulMatchLen = 0U;
|
||||
uint8_t bDefaultVolNum = UINT8_MAX;
|
||||
uint8_t bVolNum;
|
||||
|
||||
for(bVolNum = 0U; bVolNum < REDCONF_VOLUME_COUNT; bVolNum++)
|
||||
{
|
||||
const char *pszPrefix = gaRedVolConf[bVolNum].pszPathPrefix;
|
||||
uint32_t ulPrefixLen = RedStrLen(pszPrefix);
|
||||
|
||||
if(ulPrefixLen == 0U)
|
||||
{
|
||||
/* A volume with a path prefix of an empty string is the
|
||||
default volume, used when the path does not match the
|
||||
prefix of any other volume.
|
||||
|
||||
The default volume should only be found once. During
|
||||
initialization, RedCoreInit() ensures that all volume
|
||||
prefixes are unique (including empty prefixes).
|
||||
*/
|
||||
REDASSERT(bDefaultVolNum == UINT8_MAX);
|
||||
bDefaultVolNum = bVolNum;
|
||||
}
|
||||
/* For a path to match, it must either be the prefix exactly, or
|
||||
be followed by a path separator character. Thus, with a volume
|
||||
prefix of "/foo", both "/foo" and "/foo/bar" are matches, but
|
||||
"/foobar" is not.
|
||||
*/
|
||||
else if( (RedStrNCmp(pszPath, pszPrefix, ulPrefixLen) == 0)
|
||||
&& ((pszPath[ulPrefixLen] == '\0') || (pszPath[ulPrefixLen] == REDCONF_PATH_SEPARATOR)))
|
||||
{
|
||||
/* The length of this match should never exactly equal the
|
||||
length of a previous match: that would require a duplicate
|
||||
volume name, which should have been detected during init.
|
||||
*/
|
||||
REDASSERT(ulPrefixLen != ulMatchLen);
|
||||
|
||||
/* If multiple prefixes match, the longest takes precedence.
|
||||
Thus, if there are two prefixes "Flash" and "Flash/Backup",
|
||||
the path "Flash/Backup/" will not be erroneously matched
|
||||
with the "Flash" volume.
|
||||
*/
|
||||
if(ulPrefixLen > ulMatchLen)
|
||||
{
|
||||
bMatchVol = bVolNum;
|
||||
ulMatchLen = ulPrefixLen;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* No match, keep looking.
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
if(bMatchVol != UINT8_MAX)
|
||||
{
|
||||
/* The path matched a volume path prefix.
|
||||
*/
|
||||
bVolNum = bMatchVol;
|
||||
pszLocalPath = &pszPath[ulMatchLen];
|
||||
}
|
||||
else if(bDefaultVolNum != UINT8_MAX)
|
||||
{
|
||||
/* The path didn't match any of the prefixes, but one of the
|
||||
volumes has a path prefix of "", so an unprefixed path is
|
||||
assigned to that volume.
|
||||
*/
|
||||
bVolNum = bDefaultVolNum;
|
||||
REDASSERT(pszLocalPath == pszPath);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* The path cannot be assigned a volume.
|
||||
*/
|
||||
ret = -RED_ENOENT;
|
||||
}
|
||||
|
||||
if(ret == 0)
|
||||
{
|
||||
if(pbVolNum != NULL)
|
||||
{
|
||||
*pbVolNum = bVolNum;
|
||||
}
|
||||
|
||||
if(ppszLocalPath != NULL)
|
||||
{
|
||||
*ppszLocalPath = pszLocalPath;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* If no local path is expected, then the string should either
|
||||
terminate after the path prefix or the local path should name
|
||||
the root directory. Allowing path separators here means that
|
||||
red_mount("/data/") is OK with a path prefix of "/data".
|
||||
*/
|
||||
if(pszLocalPath[0U] != '\0')
|
||||
{
|
||||
if(!IsRootDir(pszLocalPath))
|
||||
{
|
||||
ret = -RED_ENOENT;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/** @brief Lookup the inode named by the given path.
|
||||
|
||||
@param pszLocalPath The path to lookup; this is a local path, without any
|
||||
volume prefix.
|
||||
@param pulInode On successful return, populated with the number of the
|
||||
inode named by @p pszLocalPath.
|
||||
|
||||
@return A negated ::REDSTATUS code indicating the operation result.
|
||||
|
||||
@retval 0 Operation was successful.
|
||||
@retval -RED_EINVAL @p pszLocalPath is `NULL`; or @p pulInode is
|
||||
`NULL`.
|
||||
@retval -RED_EIO A disk I/O error occurred.
|
||||
@retval -RED_ENOENT @p pszLocalPath is an empty string; or
|
||||
@p pszLocalPath does not name an existing file
|
||||
or directory.
|
||||
@retval -RED_ENOTDIR A component of the path other than the last is
|
||||
not a directory.
|
||||
@retval -RED_ENAMETOOLONG The length of a component of @p pszLocalPath is
|
||||
longer than #REDCONF_NAME_MAX.
|
||||
*/
|
||||
REDSTATUS RedPathLookup(
|
||||
const char *pszLocalPath,
|
||||
uint32_t *pulInode)
|
||||
{
|
||||
REDSTATUS ret;
|
||||
|
||||
if((pszLocalPath == NULL) || (pulInode == NULL))
|
||||
{
|
||||
REDERROR();
|
||||
ret = -RED_EINVAL;
|
||||
}
|
||||
else if(pszLocalPath[0U] == '\0')
|
||||
{
|
||||
ret = -RED_ENOENT;
|
||||
}
|
||||
else if(IsRootDir(pszLocalPath))
|
||||
{
|
||||
ret = 0;
|
||||
*pulInode = INODE_ROOTDIR;
|
||||
}
|
||||
else
|
||||
{
|
||||
uint32_t ulPInode;
|
||||
const char *pszName;
|
||||
|
||||
ret = RedPathToName(pszLocalPath, &ulPInode, &pszName);
|
||||
|
||||
if(ret == 0)
|
||||
{
|
||||
ret = RedCoreLookup(ulPInode, pszName, pulInode);
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/** @brief Given a path, return the parent inode number and a pointer to the
|
||||
last component in the path (the name).
|
||||
|
||||
@param pszLocalPath The path to examine; this is a local path, without any
|
||||
volume prefix.
|
||||
@param pulPInode On successful return, populated with the inode number of
|
||||
the parent directory of the last component in the path.
|
||||
For example, with the path "a/b/c", populated with the
|
||||
inode number of "b".
|
||||
@param ppszName On successful return, populated with a pointer to the
|
||||
last component in the path. For example, with the path
|
||||
"a/b/c", populated with a pointer to "c".
|
||||
|
||||
@return A negated ::REDSTATUS code indicating the operation result.
|
||||
|
||||
@retval 0 Operation was successful.
|
||||
@retval -RED_EINVAL @p pszLocalPath is `NULL`; or @p pulPInode is
|
||||
`NULL`; or @p ppszName is `NULL`; or the path
|
||||
names the root directory.
|
||||
@retval -RED_EIO A disk I/O error occurred.
|
||||
@retval -RED_ENOENT @p pszLocalPath is an empty string; or a
|
||||
component of the path other than the last does
|
||||
not exist.
|
||||
@retval -RED_ENOTDIR A component of the path other than the last is
|
||||
not a directory.
|
||||
@retval -RED_ENAMETOOLONG The length of a component of @p pszLocalPath is
|
||||
longer than #REDCONF_NAME_MAX.
|
||||
*/
|
||||
REDSTATUS RedPathToName(
|
||||
const char *pszLocalPath,
|
||||
uint32_t *pulPInode,
|
||||
const char **ppszName)
|
||||
{
|
||||
REDSTATUS ret;
|
||||
|
||||
if((pszLocalPath == NULL) || (pulPInode == NULL) || (ppszName == NULL))
|
||||
{
|
||||
REDERROR();
|
||||
ret = -RED_EINVAL;
|
||||
}
|
||||
else if(IsRootDir(pszLocalPath))
|
||||
{
|
||||
ret = -RED_EINVAL;
|
||||
}
|
||||
else if(pszLocalPath[0U] == '\0')
|
||||
{
|
||||
ret = -RED_ENOENT;
|
||||
}
|
||||
else
|
||||
{
|
||||
uint32_t ulInode = INODE_ROOTDIR;
|
||||
uint32_t ulPInode = INODE_INVALID;
|
||||
uint32_t ulPathIdx = 0U;
|
||||
uint32_t ulLastNameIdx = 0U;
|
||||
|
||||
ret = 0;
|
||||
|
||||
do
|
||||
{
|
||||
uint32_t ulNameLen;
|
||||
|
||||
/* Skip over path separators, to get pszLocalPath[ulPathIdx]
|
||||
pointing at the next name.
|
||||
*/
|
||||
while(pszLocalPath[ulPathIdx] == REDCONF_PATH_SEPARATOR)
|
||||
{
|
||||
ulPathIdx++;
|
||||
}
|
||||
|
||||
if(pszLocalPath[ulPathIdx] == '\0')
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
/* Point ulLastNameIdx at the first character of the name; after
|
||||
we exit the loop, it will point at the first character of the
|
||||
last name in the path.
|
||||
*/
|
||||
ulLastNameIdx = ulPathIdx;
|
||||
|
||||
/* Point ulPInode at the parent inode: either the root inode
|
||||
(first pass) or the inode of the previous name. After we exit
|
||||
the loop, this will point at the parent inode of the last name.
|
||||
*/
|
||||
ulPInode = ulInode;
|
||||
|
||||
ulNameLen = RedNameLen(&pszLocalPath[ulPathIdx]);
|
||||
|
||||
/* Lookup the inode of the name, unless we are at the last name in
|
||||
the path: we don't care whether the last name exists or not.
|
||||
*/
|
||||
if(PathHasMoreNames(&pszLocalPath[ulPathIdx + ulNameLen]))
|
||||
{
|
||||
ret = RedCoreLookup(ulPInode, &pszLocalPath[ulPathIdx], &ulInode);
|
||||
}
|
||||
|
||||
/* Move on to the next path element.
|
||||
*/
|
||||
if(ret == 0)
|
||||
{
|
||||
ulPathIdx += ulNameLen;
|
||||
}
|
||||
}
|
||||
while(ret == 0);
|
||||
|
||||
if(ret == 0)
|
||||
{
|
||||
*pulPInode = ulPInode;
|
||||
*ppszName = &pszLocalPath[ulLastNameIdx];
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/** @brief Determine whether a path names the root directory.
|
||||
|
||||
@param pszLocalPath The path to examine; this is a local path, without any
|
||||
volume prefix.
|
||||
|
||||
@return Returns whether @p pszLocalPath names the root directory.
|
||||
|
||||
@retval true @p pszLocalPath names the root directory.
|
||||
@retval false @p pszLocalPath does not name the root directory.
|
||||
*/
|
||||
static bool IsRootDir(
|
||||
const char *pszLocalPath)
|
||||
{
|
||||
bool fRet;
|
||||
|
||||
if(pszLocalPath == NULL)
|
||||
{
|
||||
REDERROR();
|
||||
fRet = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
uint32_t ulIdx = 0U;
|
||||
|
||||
/* A string containing nothing but path separators (usually only one)
|
||||
names the root directory. An empty string does *not* name the root
|
||||
directory, since in POSIX empty strings typically elicit -RED_ENOENT
|
||||
errors.
|
||||
*/
|
||||
while(pszLocalPath[ulIdx] == REDCONF_PATH_SEPARATOR)
|
||||
{
|
||||
ulIdx++;
|
||||
}
|
||||
|
||||
fRet = (ulIdx > 0U) && (pszLocalPath[ulIdx] == '\0');
|
||||
}
|
||||
|
||||
return fRet;
|
||||
}
|
||||
|
||||
|
||||
/** @brief Determine whether there are more names in a path.
|
||||
|
||||
Example | Result
|
||||
------- | ------
|
||||
"" false
|
||||
"/" false
|
||||
"//" false
|
||||
"a" true
|
||||
"/a" true
|
||||
"//a" true
|
||||
|
||||
@param pszPathIdx The path to examine, incremented to the point of
|
||||
interest.
|
||||
|
||||
@return Returns whether there are more names in @p pszPathIdx.
|
||||
|
||||
@retval true @p pszPathIdx has more names.
|
||||
@retval false @p pszPathIdx has no more names.
|
||||
*/
|
||||
static bool PathHasMoreNames(
|
||||
const char *pszPathIdx)
|
||||
{
|
||||
bool fRet;
|
||||
|
||||
if(pszPathIdx == NULL)
|
||||
{
|
||||
REDERROR();
|
||||
fRet = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
uint32_t ulIdx = 0U;
|
||||
|
||||
while(pszPathIdx[ulIdx] == REDCONF_PATH_SEPARATOR)
|
||||
{
|
||||
ulIdx++;
|
||||
}
|
||||
|
||||
fRet = pszPathIdx[ulIdx] != '\0';
|
||||
}
|
||||
|
||||
return fRet;
|
||||
}
|
||||
|
||||
#endif /* REDCONF_API_POSIX */
|
||||
|
3088
FreeRTOSv10.2.1/FreeRTOS-Plus/Source/Reliance-Edge/posix/posix.c
Normal file
3088
FreeRTOSv10.2.1/FreeRTOS-Plus/Source/Reliance-Edge/posix/posix.c
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,152 @@
|
||||
/* ----> DO NOT REMOVE THE FOLLOWING NOTICE <----
|
||||
|
||||
Copyright (c) 2014-2015 Datalight, Inc.
|
||||
All Rights Reserved Worldwide.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; use version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but "AS-IS," WITHOUT ANY WARRANTY; without even the implied warranty
|
||||
of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
/* Businesses and individuals that for commercial or other reasons cannot
|
||||
comply with the terms of the GPLv2 license may obtain a commercial license
|
||||
before incorporating Reliance Edge into proprietary software for
|
||||
distribution in any form. Visit http://www.datalight.com/reliance-edge for
|
||||
more information.
|
||||
*/
|
||||
/** @file
|
||||
@brief Defines macros which make the Reliance Edge POSIX-like API look more
|
||||
like the actual POSIX API.
|
||||
|
||||
This file is intended for porting POSIX file system tests; it is not
|
||||
intended for application use.
|
||||
*/
|
||||
#ifndef REDPOSIXCOMPAT_H
|
||||
#define REDPOSIXCOMPAT_H
|
||||
|
||||
|
||||
#ifndef assert
|
||||
#define assert(x) REDASSERT(x)
|
||||
#endif
|
||||
|
||||
|
||||
#undef O_RDONLY
|
||||
#undef O_WRONLY
|
||||
#undef O_RDWR
|
||||
#undef O_APPEND
|
||||
#undef O_CREAT
|
||||
#undef O_EXCL
|
||||
#undef O_TRUNC
|
||||
#define O_RDONLY RED_O_RDONLY
|
||||
#define O_WRONLY RED_O_WRONLY
|
||||
#define O_RDWR RED_O_RDWR
|
||||
#define O_APPEND RED_O_APPEND
|
||||
#define O_CREAT RED_O_CREAT
|
||||
#define O_EXCL RED_O_EXCL
|
||||
#define O_TRUNC RED_O_TRUNC
|
||||
|
||||
#undef SEEK_SET
|
||||
#undef SEEK_CUR
|
||||
#undef SEEK_END
|
||||
#define SEEK_SET RED_SEEK_SET
|
||||
#define SEEK_CUR RED_SEEK_CUR
|
||||
#define SEEK_END RED_SEEK_END
|
||||
|
||||
/* Old-fashioned Linux seek names.
|
||||
*/
|
||||
#undef L_SET
|
||||
#undef L_INCR
|
||||
#undef L_XTND
|
||||
#define L_SET SEEK_SET
|
||||
#define L_INCR SEEK_CUR
|
||||
#define L_XTND SEEK_END
|
||||
|
||||
#undef S_IFDIR
|
||||
#undef S_IFREG
|
||||
#undef S_ISDIR
|
||||
#undef S_ISREG
|
||||
#define S_IFDIR RED_S_IFDIR
|
||||
#define S_IFREG RED_S_IFREG
|
||||
#define S_ISDIR(m) RED_S_ISDIR(m)
|
||||
#define S_ISREG(m) RED_S_ISREG(m)
|
||||
|
||||
#undef ST_RDONLY
|
||||
#undef ST_NOSUID
|
||||
#define ST_RDONLY RED_ST_RDONLY
|
||||
#define ST_NOSUID RED_ST_NOSUID
|
||||
|
||||
#undef open
|
||||
#undef creat
|
||||
#undef unlink
|
||||
#undef mkdir
|
||||
#undef rmdir
|
||||
#undef rename
|
||||
#undef link
|
||||
#undef close
|
||||
#undef read
|
||||
#undef write
|
||||
#undef fsync
|
||||
#undef fdatasync
|
||||
#undef lseek
|
||||
#undef ftruncate
|
||||
#undef fstat
|
||||
#undef opendir
|
||||
#undef readdir
|
||||
#undef rewinddir
|
||||
#undef closedir
|
||||
#define open(path, oflag) red_open(path, oflag)
|
||||
#define creat(path, mode) open(path, O_WRONLY|O_CREAT|O_TRUNC)
|
||||
#define unlink(path) red_unlink(path)
|
||||
#define mkdir(path) red_mkdir(path)
|
||||
#define rmdir(path) red_rmdir(path)
|
||||
#define rename(old, new) red_rename(old, new)
|
||||
#define link(path, hardlink) red_link(path, hardlink)
|
||||
#define close(fd) red_close(fd)
|
||||
#define read(fd, buf, len) red_read(fd, buf, len)
|
||||
#define write(fd, buf, len) red_write(fd, buf, len)
|
||||
#define fsync(fd) red_fsync(fd)
|
||||
#define fdatasync(fd) fsync(fd)
|
||||
#define lseek(fd, offset, whence) red_lseek(fd, offset, whence)
|
||||
#define lseek64(fd, offset, whence) lseek(fd, offset, whence)
|
||||
#define ftruncate(fd, size) red_ftruncate(fd, size)
|
||||
#define fstat(fd, stat) red_fstat(fd, stat)
|
||||
#define fstat64(fd, stat) fstat(fd, stat)
|
||||
#define opendir(path) red_opendir(path)
|
||||
#define readdir(dirp) red_readdir(dirp)
|
||||
#define readdir64(dirp) readdir(dirp)
|
||||
#define rewinddir(dirp) red_rewinddir(dirp)
|
||||
#define closedir(dirp) red_closedir(dirp)
|
||||
|
||||
#undef DIR
|
||||
#define DIR REDDIR
|
||||
|
||||
#undef errno
|
||||
#define errno (*(int *)red_errnoptr())
|
||||
|
||||
#undef memcpy
|
||||
#undef memmove
|
||||
#undef memset
|
||||
#undef strlen
|
||||
#undef strncmp
|
||||
#undef strcmp
|
||||
#undef strncpy
|
||||
#define memcpy(d, s, l) RedMemCpy(d, s, (uint32_t)(l))
|
||||
#define memmove(d, s, l) RedMemMove(d, s, (uint32_t)(l))
|
||||
#define memset(d, c, l) RedMemSet(d, (uint8_t)(c), (uint32_t)(l))
|
||||
#define strlen(s) RedStrLen(s)
|
||||
#define strncmp(s1, s2, l) RedStrNCmp(s1, s2, (uint32_t)(l))
|
||||
#define strcmp(s1, s2) RedStrCmp(s1, s2)
|
||||
#define strncpy(d, s, l) RedStrNCpy(d, s, (uint32_t)(l))
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
@@ -0,0 +1,478 @@
|
||||
/* ----> DO NOT REMOVE THE FOLLOWING NOTICE <----
|
||||
|
||||
Copyright (c) 2014-2015 Datalight, Inc.
|
||||
All Rights Reserved Worldwide.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; use version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but "AS-IS," WITHOUT ANY WARRANTY; without even the implied warranty
|
||||
of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
/* Businesses and individuals that for commercial or other reasons cannot
|
||||
comply with the terms of the GPLv2 license may obtain a commercial license
|
||||
before incorporating Reliance Edge into proprietary software for
|
||||
distribution in any form. Visit http://www.datalight.com/reliance-edge for
|
||||
more information.
|
||||
*/
|
||||
/** @file
|
||||
@brief Implements utilities that convert strings to numbers.
|
||||
*/
|
||||
#include <redfs.h>
|
||||
#include <redtestutils.h>
|
||||
|
||||
|
||||
#define ISHEXDIGITU(c) (((c) >= 'A') && ((c) <= 'F'))
|
||||
#define ISHEXDIGITL(c) (((c) >= 'a') && ((c) <= 'f'))
|
||||
#define ISHEXDIGIT(c) (ISHEXDIGITL(c) || ISHEXDIGITU(c))
|
||||
|
||||
|
||||
/** @brief Converts an ASCII number into an int32_t.
|
||||
|
||||
Converts all decimal digit numbers up to the end of the string or to the
|
||||
first non-numerical character.
|
||||
|
||||
@note This function does *not* ignore leading white space.
|
||||
|
||||
@param pszNum Pointer to a constant array of characters.
|
||||
|
||||
@return The integer represented in the string.
|
||||
*/
|
||||
int32_t RedAtoI(
|
||||
const char *pszNum)
|
||||
{
|
||||
int32_t lValue = 0;
|
||||
int32_t lNegative = 1;
|
||||
uint32_t ulIdx = 0U;
|
||||
|
||||
if(pszNum[ulIdx] == '+')
|
||||
{
|
||||
ulIdx++;
|
||||
}
|
||||
else if(pszNum[ulIdx] == '-')
|
||||
{
|
||||
ulIdx++;
|
||||
lNegative = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* No sign, implicitly positive.
|
||||
*/
|
||||
}
|
||||
|
||||
while(ISDIGIT(pszNum[ulIdx]))
|
||||
{
|
||||
lValue *= 10;
|
||||
lValue += pszNum[ulIdx] - '0';
|
||||
ulIdx++;
|
||||
}
|
||||
|
||||
lValue *= lNegative;
|
||||
|
||||
return lValue;
|
||||
}
|
||||
|
||||
|
||||
/** @brief Convert a hexadecimal ASCII number into a uint32_t value.
|
||||
|
||||
The function processes all hex digits up to a NUL-terminator, or to the
|
||||
first non-hex character. Only hexadecimal digits are processed, so leading
|
||||
white space, or a leading "0x" prefix are not allowed.
|
||||
|
||||
If pachNum points to an empty string (points to a NUL), this function will
|
||||
return NULL, and the value at *pulNum will not be modified.
|
||||
|
||||
@note This function does not check for overflow. If there are more
|
||||
significant digits than can be represented in a uint32_t variable, the
|
||||
output is unspecified.
|
||||
|
||||
@param pszNum A pointer to a constant array of hex characters.
|
||||
@param pulNum A pointer to the location in which to store the uint32_t
|
||||
result. Upon return, this value will be modified ONLY if
|
||||
the function succeeds and the returned pointer is valid (not
|
||||
NULL).
|
||||
|
||||
@return A pointer to the byte following the converted number or NULL to
|
||||
indicate failure.
|
||||
*/
|
||||
const char *RedHtoUL(
|
||||
const char *pszNum,
|
||||
uint32_t *pulNum)
|
||||
{
|
||||
uint64_t ullValue;
|
||||
const char *pszReturn;
|
||||
|
||||
pszReturn = RedHtoULL(pszNum, &ullValue);
|
||||
if(pszReturn != NULL)
|
||||
{
|
||||
if(ullValue < UINT32_MAX)
|
||||
{
|
||||
*pulNum = (uint32_t)ullValue;
|
||||
}
|
||||
else
|
||||
{
|
||||
pszReturn = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return pszReturn;
|
||||
}
|
||||
|
||||
|
||||
/** @brief Convert a hexadecimal ASCII number into a D_UINT64 value.
|
||||
|
||||
The function processes all hex digits up to a NUL-terminator, or to the
|
||||
first non-hex character. Only hexadecimal digits are processed, so leading
|
||||
white space, or a leading "0x" prefix are not allowed.
|
||||
|
||||
If pachNum points to an empty string (points to a NUL), this function will
|
||||
return NULL, and the value at *pulNum will not be modified.
|
||||
|
||||
@note This function does not check for overflow. If there are more
|
||||
significant digits than can be represented in a uint64_t variable, the
|
||||
output is unspecified.
|
||||
|
||||
@param pszNum A pointer to a constant array of hex characters.
|
||||
@param pullNum A pointer to the location in which to store the uint64_t
|
||||
result. Upon return, this value will be modified ONLY if
|
||||
the function succeeds and the returned pointer is valid (not
|
||||
NULL).
|
||||
|
||||
@return A pointer to the byte following the converted number, or NULL to
|
||||
indicate failure.
|
||||
*/
|
||||
const char *RedHtoULL(
|
||||
const char *pszNum,
|
||||
uint64_t *pullNum)
|
||||
{
|
||||
uint64_t ullValue = 0U;
|
||||
const char *pszReturn = NULL;
|
||||
uint32_t ulIdx = 0U;
|
||||
|
||||
REDASSERT(pszNum != NULL);
|
||||
REDASSERT(pullNum != NULL);
|
||||
|
||||
while(pszNum[ulIdx] != '\0')
|
||||
{
|
||||
char cDigit = pszNum[ulIdx];
|
||||
|
||||
if(ISDIGIT(cDigit))
|
||||
{
|
||||
cDigit -= '0';
|
||||
}
|
||||
else if(ISHEXDIGITU(cDigit))
|
||||
{
|
||||
cDigit -= ('A' - 10);
|
||||
}
|
||||
else if(ISHEXDIGITL(cDigit))
|
||||
{
|
||||
cDigit -= ('a' - 10);
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
REDASSERT((ullValue & UINT64_SUFFIX(0xF000000000000000)) == 0U);
|
||||
|
||||
ullValue <<= 4U;
|
||||
ullValue += cDigit;
|
||||
|
||||
ulIdx++;
|
||||
pszReturn = &pszNum[ulIdx];
|
||||
}
|
||||
|
||||
/* Modify the number returned only if we found one or more valid hex
|
||||
digits.
|
||||
*/
|
||||
if(pszReturn != NULL)
|
||||
{
|
||||
*pullNum = ullValue;
|
||||
}
|
||||
|
||||
return pszReturn;
|
||||
}
|
||||
|
||||
|
||||
/** @brief Convert the ASCII number to a uint32_t value.
|
||||
|
||||
The number may be hex or decimal. Hex numbers must be prefixed by '0x', and
|
||||
they may be upper or lower case. The conversion process will stop with the
|
||||
first non hex or decimal digit.
|
||||
|
||||
If the number is negative (the first character is a '-' sign), the value
|
||||
will be range checked and returned as the equivalent unsigned value.
|
||||
|
||||
@note This function will NOT fail for numbers which exceed the size of a
|
||||
uint32_t value.
|
||||
|
||||
@param pszNum A pointer to the ASCII number to convert
|
||||
@param pulNum A pointer to the uint32_t location to store the result.
|
||||
This value will be modified on return only if the function
|
||||
succeeds and the returned pointer is valid (not NULL).
|
||||
|
||||
@return A pointer to the byte following the converted number, or NULL to
|
||||
indicate failure.
|
||||
*/
|
||||
const char *RedNtoUL(
|
||||
const char *pszNum,
|
||||
uint32_t *pulNum)
|
||||
{
|
||||
bool fNegative = false;
|
||||
uint32_t ulIdx = 0U;
|
||||
const char *pszReturn;
|
||||
|
||||
REDASSERT(pszNum != NULL);
|
||||
REDASSERT(pulNum != NULL);
|
||||
|
||||
if(pszNum[ulIdx] == '-')
|
||||
{
|
||||
fNegative = true;
|
||||
ulIdx++;
|
||||
}
|
||||
|
||||
/* Hex numbers must be prefixed with '0x'.
|
||||
*/
|
||||
if((pszNum[ulIdx] == '0') && ((pszNum[ulIdx + 1U] == 'x') || (pszNum[ulIdx + 1U] == 'X')))
|
||||
{
|
||||
ulIdx += 2U;
|
||||
|
||||
if(ISDIGIT(pszNum[ulIdx]) || ISHEXDIGIT(pszNum[ulIdx]))
|
||||
{
|
||||
pszReturn = RedHtoUL(&pszNum[ulIdx], pulNum);
|
||||
}
|
||||
else
|
||||
{
|
||||
pszReturn = NULL;
|
||||
}
|
||||
}
|
||||
else if(ISDIGIT(pszNum[ulIdx]))
|
||||
{
|
||||
uint32_t ulTemp;
|
||||
|
||||
ulTemp = RedAtoI(&pszNum[ulIdx]);
|
||||
|
||||
while(ISDIGIT(pszNum[ulIdx]))
|
||||
{
|
||||
ulIdx++;
|
||||
}
|
||||
|
||||
if(fNegative)
|
||||
{
|
||||
/* Fail if the number is out of range.
|
||||
*/
|
||||
if(ulTemp > INT32_MAX)
|
||||
{
|
||||
pszReturn = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
*pulNum = -((int32_t)ulTemp);
|
||||
pszReturn = &pszNum[ulIdx];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
*pulNum = ulTemp;
|
||||
pszReturn = &pszNum[ulIdx];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Return an error if there is not at least one hex or decimal digit.
|
||||
*/
|
||||
pszReturn = NULL;
|
||||
}
|
||||
|
||||
return pszReturn;
|
||||
}
|
||||
|
||||
|
||||
/** @brief Convert the ASCII number pointed to by pachNum to a uint64_t value.
|
||||
|
||||
The number may be hex or decimal. Hex numbers must be prefixed by '0x', and
|
||||
they may be upper or lower case. The conversion process will stop with the
|
||||
first non hex or decimal digit.
|
||||
|
||||
If the number is negative (the first character is a '-' sign), the value
|
||||
will be range checked and returned as the equivalent unsigned value.
|
||||
|
||||
@param pszNum A pointer to the ASCII number to convert.
|
||||
@param pullNum A pointer to the uint64_t location to store the result.
|
||||
This value will be modified on return only if the function
|
||||
succeeds and the returned pointer is valid (not NULL).
|
||||
|
||||
@return A pointer to the byte following the converted number, or NULL to
|
||||
indicate failure.
|
||||
*/
|
||||
const char *RedNtoULL(
|
||||
const char *pszNum,
|
||||
uint64_t *pullNum)
|
||||
{
|
||||
bool fNegative = false;
|
||||
uint32_t ulIdx = 0U;
|
||||
const char *pszReturn;
|
||||
|
||||
REDASSERT(pszNum != NULL);
|
||||
REDASSERT(pullNum != NULL);
|
||||
|
||||
if(pszNum[ulIdx] == '-')
|
||||
{
|
||||
fNegative = true;
|
||||
ulIdx++;
|
||||
}
|
||||
|
||||
/* Hex numbers must be prefixed with '0x'.
|
||||
*/
|
||||
if((pszNum[ulIdx] == '0') && ((pszNum[ulIdx + 1U] == 'x') || (pszNum[ulIdx + 1U] == 'X')))
|
||||
{
|
||||
ulIdx += 2U;
|
||||
|
||||
if(ISDIGIT(pszNum[ulIdx]) || ISHEXDIGIT(pszNum[ulIdx]))
|
||||
{
|
||||
pszReturn = RedHtoULL(&pszNum[ulIdx], pullNum);
|
||||
}
|
||||
else
|
||||
{
|
||||
pszReturn = NULL;
|
||||
}
|
||||
}
|
||||
else if(ISDIGIT(pszNum[ulIdx]))
|
||||
{
|
||||
uint64_t ullTemp = 0U;
|
||||
|
||||
while(ISDIGIT(pszNum[ulIdx]))
|
||||
{
|
||||
ullTemp *= 10U;
|
||||
ullTemp += pszNum[ulIdx] - '0';
|
||||
ulIdx++;
|
||||
}
|
||||
|
||||
if(fNegative)
|
||||
{
|
||||
/* Fail if the number is out of range.
|
||||
*/
|
||||
if(ullTemp > INT64_MAX)
|
||||
{
|
||||
pszReturn = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
*pullNum = (uint64_t)(-((int64_t)ullTemp));
|
||||
pszReturn = &pszNum[ulIdx];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
*pullNum = ullTemp;
|
||||
pszReturn = &pszNum[ulIdx];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Return an error if there is not at least one hex or decimal digit.
|
||||
*/
|
||||
pszReturn = NULL;
|
||||
}
|
||||
|
||||
return pszReturn;
|
||||
}
|
||||
|
||||
|
||||
/** @brief Convert an ASCII hex or decimal number, which may may have a "B",
|
||||
"KB", or "MB" suffix (case insensitive), to a binary value.
|
||||
|
||||
Hex numbers must be prefixed with "0x".
|
||||
|
||||
@note If there is no postfix, KB is assumed!
|
||||
|
||||
May fail due to bad formatting or overflow.
|
||||
|
||||
@param pszNum A pointer to the ASCII number to convert.
|
||||
@param pulResult A pointer to a uint32_t in which to place the result.
|
||||
|
||||
@return A pointer to the byte following the string, or NULL to indicate an
|
||||
error. In the event of an error, *pulResult will not be modified.
|
||||
*/
|
||||
const char *RedSizeToUL(
|
||||
const char *pszNum,
|
||||
uint32_t *pulResult)
|
||||
{
|
||||
uint32_t ulResult;
|
||||
const char *pszSuffix;
|
||||
const char *pszReturn;
|
||||
uint32_t ulIdx = 0U;
|
||||
|
||||
REDASSERT(pszNum != NULL);
|
||||
REDASSERT(pulResult != NULL);
|
||||
|
||||
/* Do the basic hex/decimal conversion
|
||||
*/
|
||||
pszSuffix = RedNtoUL(pszNum, &ulResult);
|
||||
if(pszSuffix != NULL)
|
||||
{
|
||||
if((pszSuffix[ulIdx] == 'B') || (pszSuffix[ulIdx] == 'b'))
|
||||
{
|
||||
ulIdx++;
|
||||
pszReturn = &pszSuffix[ulIdx];
|
||||
}
|
||||
else if( ((pszSuffix[ulIdx] == 'M') || (pszSuffix[ulIdx] == 'm'))
|
||||
&& ((pszSuffix[ulIdx + 1U] == 'B') || (pszSuffix[ulIdx + 1U] == 'b')))
|
||||
{
|
||||
ulIdx += 2U;
|
||||
|
||||
if(ulResult > (UINT32_MAX / (1024U * 1024U)))
|
||||
{
|
||||
pszReturn = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
ulResult *= 1024U * 1024U;
|
||||
pszReturn = &pszSuffix[ulIdx];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* The number is either postfixed with "KB" or something
|
||||
else (we don't care), but we must increment the pointer
|
||||
if it is something recognize.
|
||||
*/
|
||||
if( ((pszSuffix[ulIdx] == 'K') || (pszSuffix[ulIdx] == 'k'))
|
||||
&& ((pszSuffix[ulIdx + 1U] == 'B') || (pszSuffix[ulIdx + 1U] == 'b')))
|
||||
{
|
||||
ulIdx += 2U;
|
||||
}
|
||||
|
||||
/* "B" or "MB" were not specified, so it must be "KB"
|
||||
*/
|
||||
if(ulResult > (UINT32_MAX / 1024U))
|
||||
{
|
||||
pszReturn = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
ulResult *= 1024UL;
|
||||
pszReturn = &pszSuffix[ulIdx];
|
||||
}
|
||||
}
|
||||
|
||||
if(pszReturn != NULL)
|
||||
{
|
||||
*pulResult = ulResult;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
pszReturn = NULL;
|
||||
}
|
||||
|
||||
return pszReturn;
|
||||
}
|
||||
|
@@ -0,0 +1,641 @@
|
||||
/* ----> DO NOT REMOVE THE FOLLOWING NOTICE <----
|
||||
|
||||
Copyright (c) 2014-2015 Datalight, Inc.
|
||||
All Rights Reserved Worldwide.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; use version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but "AS-IS," WITHOUT ANY WARRANTY; without even the implied warranty
|
||||
of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
/* Businesses and individuals that for commercial or other reasons cannot
|
||||
comply with the terms of the GPLv2 license may obtain a commercial license
|
||||
before incorporating Reliance Edge into proprietary software for
|
||||
distribution in any form. Visit http://www.datalight.com/reliance-edge for
|
||||
more information.
|
||||
*/
|
||||
/** @file
|
||||
@brief Implements routines for certain 64-bit math operations and simulated
|
||||
floating point.
|
||||
|
||||
RedUint64DivMod32() and RedUint64DivMod64() are derived from code at
|
||||
http://www.hackersdelight.org. This web site states explicitly that "You
|
||||
are free to use, copy, and distribute any of the code on this web site,
|
||||
whether modified by you or not. You need not give attribution."
|
||||
*/
|
||||
#include <redfs.h>
|
||||
#include <redtestutils.h>
|
||||
|
||||
|
||||
static uint32_t nlz64(uint64_t ullValue);
|
||||
|
||||
|
||||
/** @brief Return a ratio value formatted as a floating point string accurate to
|
||||
the specified number of decimal places.
|
||||
|
||||
The function exists to provide floating point style output without using
|
||||
any actual floating point types.
|
||||
|
||||
This function may scale the numbers down to avoid overflow at the high end.
|
||||
Likewise, potential divide-by-zero errors are internally avoided. Here are
|
||||
some examples:
|
||||
|
||||
Dividend | Divisor | DecPlaces | Result
|
||||
-------- | ------- | --------- | ------
|
||||
12133 | 28545 | 2 | "0.42"
|
||||
1539 | 506 | 2 | "3.04"
|
||||
|
||||
To get a number formatted as a percentage, take the take the portion of the
|
||||
total (normally the smaller part), multiply it by 100, and pass it to this
|
||||
function as the Dividend, pass the "total" value to this function as the
|
||||
Divisor, and specify the desired number of decimal places.
|
||||
|
||||
For example, if you have a disk format overhead value of N blocks out of a
|
||||
total of Y blocks on the disk, and you want to display the format overhead
|
||||
as a percentage, you would use a function call
|
||||
similar to:
|
||||
|
||||
~~~{.c}
|
||||
RedRatio(szBuffer, sizeof(szBuffer), N*100U, Y, 2U);
|
||||
~~~
|
||||
|
||||
If N=145, Y=4096, and decimal places is 2, the resulting output would be
|
||||
"3.54".
|
||||
|
||||
The string returned will always be null-terminated, even if it means
|
||||
stomping on the least significant decimal digit.
|
||||
|
||||
If either the dividend or divisor values are zero, the string "0.0" will be
|
||||
returned, with the prescribed number of decimal places.
|
||||
|
||||
@note This function has "reasonable" limits which meet the needs of the
|
||||
various supplemental utilities which use this function. Extremely
|
||||
large ratios, or using many decimal places may not function as
|
||||
desired.
|
||||
|
||||
Parameters:
|
||||
@param pBuffer A pointer to the buffer in which to store the null
|
||||
terminated results.
|
||||
@param ulBufferLen The length of the output buffer.
|
||||
@param ullDividend The "total" value to divide.
|
||||
@param ullDivisor The portion of ullDividend for which to calculate the
|
||||
ratio (may be greater than ulDividend).
|
||||
@param ulDecPlaces The number of decimal places to use, from 0 to 9.
|
||||
|
||||
@return @p pBuffer.
|
||||
*/
|
||||
char *RedRatio(
|
||||
char *pBuffer,
|
||||
uint32_t ulBufferLen,
|
||||
uint64_t ullDividend,
|
||||
uint64_t ullDivisor,
|
||||
uint32_t ulDecPlaces)
|
||||
{
|
||||
REDASSERT(pBuffer != NULL);
|
||||
REDASSERT(ulBufferLen > 0U);
|
||||
REDASSERT(ulDecPlaces <= 9U); /* arbitrary */
|
||||
|
||||
if((ullDivisor > 0U) && (ullDividend > 0U))
|
||||
{
|
||||
uint32_t ii;
|
||||
uint32_t ulFactor = 1U;
|
||||
uint64_t ullDecimal;
|
||||
uint64_t ullTemp;
|
||||
|
||||
for(ii = 1U; ii <= ulDecPlaces; ii++)
|
||||
{
|
||||
ulFactor *= 10U;
|
||||
}
|
||||
|
||||
ullDecimal = RedMulDiv64(ullDividend, ulFactor, ullDivisor);
|
||||
|
||||
/* Shouldn't really be calling this function in a situation where we
|
||||
can overflow at this point...
|
||||
*/
|
||||
REDASSERT(ullDecimal != UINT64_MAX);
|
||||
|
||||
if(ullDivisor <= ullDividend)
|
||||
{
|
||||
uint32_t ulDecimal;
|
||||
|
||||
(void)RedUint64DivMod32(ullDecimal, ulFactor, &ulDecimal);
|
||||
ullDecimal = ulDecimal;
|
||||
}
|
||||
|
||||
ullTemp = RedUint64DivMod64(ullDividend, ullDivisor, NULL);
|
||||
|
||||
if(ulDecPlaces > 0U)
|
||||
{
|
||||
RedSNPrintf(pBuffer, ulBufferLen, "%llu.%0*llu", (unsigned long long)ullTemp,
|
||||
(unsigned)ulDecPlaces, (unsigned long long)ullDecimal);
|
||||
}
|
||||
else
|
||||
{
|
||||
RedSNPrintf(pBuffer, ulBufferLen, "%llu", (unsigned long long)ullTemp);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* If either the dividend or divisor is zero, then just output a "0.0"
|
||||
string with the prescribed number of decimal places.
|
||||
*/
|
||||
if(ulDecPlaces > 0U)
|
||||
{
|
||||
RedSNPrintf(pBuffer, ulBufferLen, "0.%0*u", (unsigned)ulDecPlaces, 0U);
|
||||
}
|
||||
else
|
||||
{
|
||||
RedStrNCpy(pBuffer, "0", ulBufferLen);
|
||||
}
|
||||
}
|
||||
|
||||
/* Ensure the returned buffer is always null-terminated
|
||||
*/
|
||||
pBuffer[ulBufferLen - 1U] = '\0';
|
||||
|
||||
return pBuffer;
|
||||
}
|
||||
|
||||
|
||||
/** @brief Multiply 64-bit and 32-bit numbers, and divide by a 64-bit number,
|
||||
returning a 64-bit result.
|
||||
|
||||
@note This function may return an approximate value if multiplying
|
||||
@p ullBase and @p ulMultplier results in a number larger than 64-bits
|
||||
_and_ this cannot be avoided by scaling.
|
||||
|
||||
@param ullBase The base 64-bit number number.
|
||||
@param ulMultiplier The 32-bit number by which to multiply.
|
||||
@param ullDivisor The 64-bit number by which to divide.
|
||||
|
||||
@return The 64-bit unsigned integer result. Always returns zero if either
|
||||
@p ullBase or @p ulMultiplier are zero (regardless what
|
||||
@p ullDivisor is). Returns UINT64_MAX if an overflow condition
|
||||
occurred, or if @p ullDivisor is zero.
|
||||
*/
|
||||
uint64_t RedMulDiv64(
|
||||
uint64_t ullBase,
|
||||
uint32_t ulMultiplier,
|
||||
uint64_t ullDivisor)
|
||||
{
|
||||
uint64_t ullTemp;
|
||||
|
||||
/* Result would always be zero if either of these are zero. Specifically
|
||||
test this case before looking for a zero divisor.
|
||||
*/
|
||||
if((ullBase == 0U) || (ulMultiplier == 0U))
|
||||
{
|
||||
return 0U;
|
||||
}
|
||||
|
||||
if(ullDivisor == 0U)
|
||||
{
|
||||
return UINT64_MAX;
|
||||
}
|
||||
|
||||
/* Since we don't have the ability (yet) to use 128-bit numbers, we jump
|
||||
through the following hoops (in order) to try to determine the proper
|
||||
results without losing precision:
|
||||
|
||||
1) Shift the divisor and one of the multiplicands as many times as is
|
||||
necessary to reduce the scale -- only if it can be done without
|
||||
losing precision.
|
||||
2) Divide one of the multiplicands by the divisor first, but only if it
|
||||
divides evenly, preserving precision.
|
||||
3) Same as #2, but try it for the other multiplicand.
|
||||
4) Last ditch, divide the larger multiplicand by the divisor first, then
|
||||
do the multiply. This <WILL> lose precision.
|
||||
|
||||
These solutions are identified as CODE-PATHs #1-4 which are used to
|
||||
identify the matching tests in dltmain.c.
|
||||
|
||||
Note that execution might partially include CODE-PATH #1 up until
|
||||
shifting can no longer be done without losing precision. In that case,
|
||||
one of the three remaining options will be used.
|
||||
*/
|
||||
|
||||
ullTemp = RedUint64DivMod32(UINT64_MAX, ulMultiplier, NULL);
|
||||
while(ullBase > ullTemp)
|
||||
{
|
||||
uint64_t ullMod;
|
||||
uint64_t ullBaseTemp;
|
||||
uint64_t ullWideMultiplier;
|
||||
|
||||
/* CODE-PATH #1
|
||||
*/
|
||||
/* So long as ulDivisor, and at least one of the other numbers, are
|
||||
evenly divisible by 2, we can scale the numbers so the result does
|
||||
not overflow the intermediate 64-bit value.
|
||||
*/
|
||||
if((ullDivisor & 1U) == 0U)
|
||||
{
|
||||
if((ullBase & 1U) == 0U)
|
||||
{
|
||||
/* CODE-PATH #1a
|
||||
*/
|
||||
ullDivisor >>= 1U;
|
||||
ullBase >>= 1U;
|
||||
continue;
|
||||
}
|
||||
|
||||
if(((ulMultiplier & 1U) == 0U) && ((ullTemp & UINT64_SUFFIX(0x8000000000000000)) == 0U))
|
||||
{
|
||||
/* CODE-PATH #1b
|
||||
*/
|
||||
ullDivisor >>= 1U;
|
||||
ulMultiplier >>= 1U;
|
||||
ullTemp <<= 1U;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
/* If we get to this point, the above method (#1) cannot be used
|
||||
because not enough of the numbers are even long enough to scale the
|
||||
operands down. We'll see if either multiplicand is evenly divisble
|
||||
by ulDivisor, and if so, do the divide first, then the multiply.
|
||||
(Note that once we get to this point, we will never exercise the
|
||||
while{} loop anymore.)
|
||||
*/
|
||||
|
||||
/* CODE-PATH #2
|
||||
*/
|
||||
ullBaseTemp = RedUint64DivMod64(ullBase, ullDivisor, &ullMod);
|
||||
if(ullMod == 0U)
|
||||
{
|
||||
/* Evenly divides, so check that we won't overflow, and finish up.
|
||||
*/
|
||||
ullBase = ullBaseTemp;
|
||||
if(ullBase > ullTemp)
|
||||
{
|
||||
return UINT64_MAX;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* We've validated that this will not overflow.
|
||||
*/
|
||||
ullBase *= ulMultiplier;
|
||||
return ullBase;
|
||||
}
|
||||
}
|
||||
|
||||
/* CODE-PATH #3
|
||||
*/
|
||||
ullWideMultiplier = RedUint64DivMod64(ulMultiplier, ullDivisor, &ullMod);
|
||||
if(ullMod == 0U)
|
||||
{
|
||||
/* Evenly divides, so check that we won't overflow, and finish up.
|
||||
*/
|
||||
|
||||
/* Must recalculate ullTemp relative to ullBase
|
||||
*/
|
||||
ullTemp = RedUint64DivMod64(UINT64_MAX, ullBase, NULL);
|
||||
if(ullWideMultiplier > ullTemp)
|
||||
{
|
||||
return UINT64_MAX;
|
||||
}
|
||||
else
|
||||
{
|
||||
uint32_t ulNarrowMultiplier = (uint32_t)ullWideMultiplier;
|
||||
|
||||
/* We've validated that this will not overflow.
|
||||
*/
|
||||
ullBase *= ulNarrowMultiplier;
|
||||
return ullBase;
|
||||
}
|
||||
}
|
||||
|
||||
/* CODE-PATH #4
|
||||
|
||||
Neither of the multipliers is evenly divisible by the divisor, so
|
||||
just punt and divide the larger number first, then do the final
|
||||
multiply.
|
||||
|
||||
All the other attempts above would preserve precision -- this is the
|
||||
only case where precision may be lost.
|
||||
*/
|
||||
|
||||
/* If necessary reverse the ullBase and ulMultiplier operands so that
|
||||
ullBase contains the larger of the two values.
|
||||
*/
|
||||
if(ullBase < ulMultiplier)
|
||||
{
|
||||
uint32_t ulTemp = ulMultiplier;
|
||||
|
||||
ulMultiplier = (uint32_t)ullBase;
|
||||
ullBase = ulTemp;
|
||||
}
|
||||
|
||||
ullBase = RedUint64DivMod64(ullBase, ullDivisor, NULL);
|
||||
ullTemp = RedUint64DivMod32(UINT64_MAX, ulMultiplier, NULL);
|
||||
if(ullBase > ullTemp)
|
||||
{
|
||||
return UINT64_MAX;
|
||||
}
|
||||
else
|
||||
{
|
||||
ullBase *= ulMultiplier;
|
||||
return ullBase;
|
||||
}
|
||||
}
|
||||
|
||||
/* We only get to this point if either there was never any chance of
|
||||
overflow, or if the pure shifting mechanism succeeded in reducing
|
||||
the scale so overflow is not a problem.
|
||||
*/
|
||||
|
||||
ullBase *= ulMultiplier;
|
||||
ullBase = RedUint64DivMod64(ullBase, ullDivisor, NULL);
|
||||
|
||||
return ullBase;
|
||||
}
|
||||
|
||||
|
||||
/** @brief Divide a 64-bit value by a 32-bit value, returning the quotient and
|
||||
the remainder.
|
||||
|
||||
Essentially this function does the following:
|
||||
|
||||
~~~{.c}
|
||||
if(pulRemainder != NULL)
|
||||
{
|
||||
*pulRemainder = (uint32_t)(ullDividend % ulDivisor);
|
||||
}
|
||||
return ullDividend / ulDivisor;
|
||||
~~~
|
||||
|
||||
However, it does so without ever actually dividing/modulating a 64-bit
|
||||
value, since such operations are not allowed in all environments.
|
||||
|
||||
@param ullDividend The value to divide.
|
||||
@param ulDivisor The value to divide by.
|
||||
@param pulRemainder Populated with the remainder; may be NULL.
|
||||
|
||||
@return The quotient (result of the division).
|
||||
*/
|
||||
uint64_t RedUint64DivMod32(
|
||||
uint64_t ullDividend,
|
||||
uint32_t ulDivisor,
|
||||
uint32_t *pulRemainder)
|
||||
{
|
||||
uint64_t ullQuotient;
|
||||
uint32_t ulResultRemainder;
|
||||
|
||||
/* Check for divide by zero.
|
||||
*/
|
||||
if(ulDivisor == 0U)
|
||||
{
|
||||
REDERROR();
|
||||
|
||||
/* Nonsense value if no asserts.
|
||||
*/
|
||||
ullQuotient = UINT64_SUFFIX(0xFFFFFFFFFFFFFBAD);
|
||||
ulResultRemainder = 0xFFFFFBADU;
|
||||
}
|
||||
else if(ullDividend <= UINT32_MAX)
|
||||
{
|
||||
uint32_t ulDividend = (uint32_t)ullDividend;
|
||||
|
||||
ullQuotient = ulDividend / ulDivisor;
|
||||
ulResultRemainder = ulDividend % ulDivisor;
|
||||
}
|
||||
else
|
||||
{
|
||||
uint32_t ulResultHi;
|
||||
uint32_t ulResultLo;
|
||||
uint32_t ulRemainder;
|
||||
uint8_t bIndex;
|
||||
uint32_t ulThisDivision;
|
||||
uint32_t ulMask;
|
||||
uint8_t ucNextValue;
|
||||
uint32_t ulInterimHi, ulInterimLo;
|
||||
uint32_t ulLowDword = (uint32_t)ullDividend;
|
||||
uint32_t ulHighDword = (uint32_t)(ullDividend >> 32U);
|
||||
|
||||
/* Compute the high part and get the remainder
|
||||
*/
|
||||
ulResultHi = ulHighDword / ulDivisor;
|
||||
ulResultLo = 0U;
|
||||
ulRemainder = ulHighDword % ulDivisor;
|
||||
|
||||
/* Compute the low part
|
||||
*/
|
||||
ulMask = 0xFF000000U;
|
||||
for(bIndex = 0U; bIndex < sizeof(uint32_t); bIndex++)
|
||||
{
|
||||
ucNextValue = (uint8_t)((ulLowDword & ulMask) >> ((sizeof(uint32_t) - 1U - bIndex) * 8U));
|
||||
ulInterimHi = ulRemainder >> 24U;
|
||||
ulInterimLo = (ulRemainder << 8U) | ucNextValue;
|
||||
ulThisDivision = 0U;
|
||||
while(ulInterimHi != 0U)
|
||||
{
|
||||
uint64_t ullInterim = ((uint64_t)ulInterimHi << 32U) + ulInterimLo;
|
||||
|
||||
ullInterim -= ulDivisor;
|
||||
ulThisDivision++;
|
||||
|
||||
ulInterimHi = (uint32_t)(ullInterim >> 32U);
|
||||
ulInterimLo = (uint32_t)ullInterim;
|
||||
}
|
||||
ulThisDivision += ulInterimLo / ulDivisor;
|
||||
ulRemainder = ulInterimLo % ulDivisor;
|
||||
ulResultLo <<= 8U;
|
||||
ulResultLo += ulThisDivision;
|
||||
ulMask >>= 8U;
|
||||
}
|
||||
|
||||
ullQuotient = ((uint64_t)ulResultHi << 32U) + ulResultLo;
|
||||
ulResultRemainder = (uint32_t)(ullDividend - (ullQuotient * ulDivisor));
|
||||
}
|
||||
|
||||
if(pulRemainder != NULL)
|
||||
{
|
||||
*pulRemainder = ulResultRemainder;
|
||||
}
|
||||
|
||||
return ullQuotient;
|
||||
}
|
||||
|
||||
|
||||
/** @brief Divide a 64-bit value by a 64-bit value, returning the quotient and
|
||||
the remainder.
|
||||
|
||||
Essentially this function does the following:
|
||||
|
||||
~~~{.c}
|
||||
if(pullRemainder != NULL)
|
||||
{
|
||||
*pullRemainder = ullDividend % ullDivisor;
|
||||
}
|
||||
return ullDividend / ullDivisor;
|
||||
~~~
|
||||
|
||||
However, it does so without ever actually dividing/modulating a 64-bit
|
||||
value, since such operations are not allowed in all environments.
|
||||
|
||||
@param ullDividend The value to divide.
|
||||
@param ullDivisor The value to divide by.
|
||||
@param pullRemainder Populated with the remainder; may be NULL.
|
||||
|
||||
@return The quotient (result of the division).
|
||||
*/
|
||||
uint64_t RedUint64DivMod64(
|
||||
uint64_t ullDividend,
|
||||
uint64_t ullDivisor,
|
||||
uint64_t *pullRemainder)
|
||||
{
|
||||
/* The variables u0, u1, etc. take on only 32-bit values, but they are
|
||||
declared uint64_t to avoid some compiler warning messages and to avoid
|
||||
some unnecessary EXTRs that the compiler would put in, to convert
|
||||
uint64_ts to ints.
|
||||
*/
|
||||
uint64_t u0;
|
||||
uint64_t u1;
|
||||
uint64_t q0;
|
||||
uint64_t q1;
|
||||
uint64_t ullQuotient;
|
||||
|
||||
/* First the procedure takes care of the case in which the divisor is a
|
||||
32-bit quantity. There are two subcases: (1) If the left half of the
|
||||
dividend is less than the divisor, one execution of RedUint64DivMod32()
|
||||
is all that is required (overflow is not possible). (2) Otherwise it
|
||||
does two divisions, using the grade school method.
|
||||
*/
|
||||
|
||||
if((ullDivisor >> 32U) == 0U)
|
||||
{
|
||||
if((ullDividend >> 32U) < ullDivisor)
|
||||
{
|
||||
/* If ullDividend/ullDivisor cannot overflow, just do one division.
|
||||
*/
|
||||
ullQuotient = RedUint64DivMod32(ullDividend, (uint32_t)ullDivisor, NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
uint32_t k;
|
||||
|
||||
/* If ullDividend/ullDivisor would overflow:
|
||||
*/
|
||||
|
||||
/* Break ullDividend up into two halves.
|
||||
*/
|
||||
u1 = ullDividend >> 32U;
|
||||
u0 = ullDividend & 0xFFFFFFFFU;
|
||||
|
||||
/* First quotient digit and first remainder.
|
||||
*/
|
||||
q1 = RedUint64DivMod32(u1, (uint32_t)ullDivisor, &k);
|
||||
|
||||
/* 2nd quot. digit.
|
||||
*/
|
||||
q0 = RedUint64DivMod32(((uint64_t)k << 32U) + u0, (uint32_t)ullDivisor, NULL);
|
||||
|
||||
ullQuotient = (q1 << 32U) + q0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
uint64_t n;
|
||||
uint64_t v1;
|
||||
|
||||
n = nlz64(ullDivisor); /* 0 <= n <= 31. */
|
||||
v1 = (ullDivisor << n) >> 32U; /* Normalize the divisor so its MSB is 1. */
|
||||
u1 = ullDividend >> 1U; /* To ensure no overflow. */
|
||||
|
||||
/* Get quotient from divide unsigned insn.
|
||||
*/
|
||||
q1 = RedUint64DivMod32(u1, (uint32_t)v1, NULL);
|
||||
|
||||
q0 = (q1 << n) >> 31U; /* Undo normalization and division of ullDividend by 2. */
|
||||
|
||||
/* Make q0 correct or too small by 1.
|
||||
*/
|
||||
if(q0 != 0U)
|
||||
{
|
||||
q0--;
|
||||
}
|
||||
|
||||
if((ullDividend - (q0 * ullDivisor)) >= ullDivisor)
|
||||
{
|
||||
q0++; /* Now q0 is correct. */
|
||||
}
|
||||
|
||||
ullQuotient = q0;
|
||||
}
|
||||
|
||||
if(pullRemainder != NULL)
|
||||
{
|
||||
*pullRemainder = ullDividend - (ullQuotient * ullDivisor);
|
||||
}
|
||||
|
||||
return ullQuotient;
|
||||
}
|
||||
|
||||
|
||||
/** @brief Compute the number of leading zeroes in a 64-bit value.
|
||||
|
||||
@param ullValue The value for which to compute the NLZ.
|
||||
|
||||
@return The number of leading zeroes in @p ullValue.
|
||||
*/
|
||||
static uint32_t nlz64(
|
||||
uint64_t ullValue)
|
||||
{
|
||||
uint32_t n;
|
||||
|
||||
if(ullValue == 0U)
|
||||
{
|
||||
n = 64U;
|
||||
}
|
||||
else
|
||||
{
|
||||
uint64_t x = ullValue;
|
||||
|
||||
n = 0U;
|
||||
|
||||
if(x <= UINT64_SUFFIX(0x00000000FFFFFFFF))
|
||||
{
|
||||
n += 32U;
|
||||
x <<= 32U;
|
||||
}
|
||||
|
||||
if(x <= UINT64_SUFFIX(0x0000FFFFFFFFFFFF))
|
||||
{
|
||||
n += 16U;
|
||||
x <<= 16U;
|
||||
}
|
||||
|
||||
if(x <= UINT64_SUFFIX(0x00FFFFFFFFFFFFFF))
|
||||
{
|
||||
n += 8U;
|
||||
x <<= 8U;
|
||||
}
|
||||
|
||||
if(x <= UINT64_SUFFIX(0x0FFFFFFFFFFFFFFF))
|
||||
{
|
||||
n += 4U;
|
||||
x <<= 4U;
|
||||
}
|
||||
|
||||
if(x <= UINT64_SUFFIX(0x3FFFFFFFFFFFFFFF))
|
||||
{
|
||||
n += 2U;
|
||||
x <<= 2U;
|
||||
}
|
||||
|
||||
if(x <= UINT64_SUFFIX(0x7FFFFFFFFFFFFFFF))
|
||||
{
|
||||
n += 1;
|
||||
}
|
||||
}
|
||||
|
||||
return n;
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,159 @@
|
||||
/* ----> DO NOT REMOVE THE FOLLOWING NOTICE <----
|
||||
|
||||
Copyright (c) 2014-2015 Datalight, Inc.
|
||||
All Rights Reserved Worldwide.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; use version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but "AS-IS," WITHOUT ANY WARRANTY; without even the implied warranty
|
||||
of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
/* Businesses and individuals that for commercial or other reasons cannot
|
||||
comply with the terms of the GPLv2 license may obtain a commercial license
|
||||
before incorporating Reliance Edge into proprietary software for
|
||||
distribution in any form. Visit http://www.datalight.com/reliance-edge for
|
||||
more information.
|
||||
*/
|
||||
/** @file
|
||||
@brief Implements a random number generator.
|
||||
*/
|
||||
#include <redfs.h>
|
||||
#include <redtestutils.h>
|
||||
|
||||
|
||||
/* This is the global seed used by the random number generator when the caller
|
||||
has not provided a seed to either the RedRand32() or RedRand64() functions.
|
||||
*/
|
||||
static uint64_t ullGlobalRandomNumberSeed;
|
||||
|
||||
/* Whether the above seed has been initialized.
|
||||
*/
|
||||
static bool fGlobalSeedInited;
|
||||
|
||||
|
||||
/** @brief Set the global seed used by the random number generator.
|
||||
|
||||
The global seed gets used when RedRand64() or RedRand32() are called with
|
||||
a NULL seed argument.
|
||||
|
||||
@param ullSeed The value to use as the global RNG seed.
|
||||
*/
|
||||
void RedRandSeed(
|
||||
uint64_t ullSeed)
|
||||
{
|
||||
ullGlobalRandomNumberSeed = ullSeed;
|
||||
fGlobalSeedInited = true;
|
||||
}
|
||||
|
||||
|
||||
/** @brief Generate a 64-bit pseudo-random number.
|
||||
|
||||
The period of this random number generator is 2^64 (1.8 x 1019). These
|
||||
parameters are the same as the default one-stream SPRNG lcg64 generator and
|
||||
it satisfies the requirements for a maximal period.
|
||||
|
||||
The tempering value is used and an AND mask and is specifically selected to
|
||||
favor the distribution of lower bits.
|
||||
|
||||
@param pullSeed A pointer to the seed to use. Set this value to NULL to
|
||||
use the internal global seed value.
|
||||
|
||||
@return A pseudo-random number in the range [0, UINT64_MAX].
|
||||
*/
|
||||
uint64_t RedRand64(
|
||||
uint64_t *pullSeed)
|
||||
{
|
||||
const uint64_t ullA = UINT64_SUFFIX(2862933555777941757);
|
||||
const uint64_t ullC = UINT64_SUFFIX(3037000493);
|
||||
const uint64_t ullT = UINT64_SUFFIX(4921441182957829599);
|
||||
uint64_t ullN;
|
||||
uint64_t *pullSeedPtr;
|
||||
uint64_t ullLocalSeed;
|
||||
|
||||
if(pullSeed != NULL)
|
||||
{
|
||||
ullLocalSeed = *pullSeed;
|
||||
pullSeedPtr = pullSeed;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(!fGlobalSeedInited)
|
||||
{
|
||||
/* Unfortunately, the Reliance Edge OS services don't give us much
|
||||
to work with to initialize the global seed. There is no entropy
|
||||
abstraction, no tick count abstraction, and the timestamp
|
||||
abstraction uses an opaque type which is not guaranteed to be an
|
||||
integer. The best we can do is use the RTC.
|
||||
|
||||
Tests using the RNG should be supplying a seed anyway, for
|
||||
reproducibility.
|
||||
*/
|
||||
RedRandSeed((uint64_t)RedOsClockGetTime());
|
||||
}
|
||||
|
||||
ullLocalSeed = ullGlobalRandomNumberSeed;
|
||||
pullSeedPtr = &ullGlobalRandomNumberSeed;
|
||||
}
|
||||
|
||||
ullN = (ullLocalSeed * ullA) + ullC;
|
||||
|
||||
*pullSeedPtr = ullN;
|
||||
|
||||
/* The linear congruential generator used above produces good psuedo-random
|
||||
64-bit number sequences, however, as with any LCG, the period of the
|
||||
lower order bits is much shorter resulting in alternately odd/even pairs
|
||||
in bit zero.
|
||||
|
||||
The result of the LGC above is tempered below with a series of XOR and
|
||||
shift operations to produce a more acceptable equidistribution of bits
|
||||
throughout the 64-bit range.
|
||||
*/
|
||||
ullN ^= (ullN >> 21U) & ullT;
|
||||
ullN ^= (ullN >> 43U) & ullT;
|
||||
ullN ^= (ullN << 23U) & ~ullT;
|
||||
ullN ^= (ullN << 31U) & ~ullT;
|
||||
|
||||
return ullN;
|
||||
}
|
||||
|
||||
|
||||
/** @brief Generate a 32-bit pseudo-random number.
|
||||
|
||||
@note The 32-bit random number generator internally uses the 64-bit random
|
||||
number generator, returning the low 32-bits of the pseudo-random
|
||||
64-bit value.
|
||||
|
||||
@param pulSeed A pointer to the seed to use. Set this value to NULL to use
|
||||
the internal global seed value.
|
||||
|
||||
@return A pseudo-random number in the range [0, UINT32_MAX].
|
||||
*/
|
||||
uint32_t RedRand32(
|
||||
uint32_t *pulSeed)
|
||||
{
|
||||
uint64_t ullN;
|
||||
|
||||
if(pulSeed != NULL)
|
||||
{
|
||||
uint64_t ullLocalSeed;
|
||||
|
||||
ullLocalSeed = *pulSeed;
|
||||
ullN = RedRand64(&ullLocalSeed);
|
||||
*pulSeed = (uint32_t)ullLocalSeed;
|
||||
}
|
||||
else
|
||||
{
|
||||
ullN = RedRand64(NULL);
|
||||
}
|
||||
|
||||
return (uint32_t)ullN;
|
||||
}
|
||||
|
@@ -0,0 +1,559 @@
|
||||
/*
|
||||
* Copyright (c) 2002 Todd C. Miller <Todd.Miller@courtesan.com>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*
|
||||
* Sponsored in part by the Defense Advanced Research Projects
|
||||
* Agency (DARPA) and Air Force Research Laboratory, Air Force
|
||||
* Materiel Command, USAF, under agreement number F39502-99-1-0512.
|
||||
*/
|
||||
/*-
|
||||
* Copyright (c) 2000 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
* by Dieter Baron and Thomas Klausner.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
/** @file
|
||||
@brief Implementations of getopt() and getopt_long() work-alike functions.
|
||||
|
||||
This code was taken from FreeBSD and slightly modified, mostly to rename
|
||||
symbols with external linkage to avoid naming conflicts in systems where
|
||||
there are real getopt()/getopt_long() implementations, and for portability.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <redfs.h>
|
||||
#include <redgetopt.h>
|
||||
#include <redtestutils.h>
|
||||
#include <rederrno.h>
|
||||
|
||||
|
||||
int32_t red_opterr = 1; /* if error message should be printed */
|
||||
int32_t red_optind = 1; /* index into parent argv vector */
|
||||
int32_t red_optopt = '?'; /* character checked for validity */
|
||||
int32_t red_optreset; /* reset RedGetopt */
|
||||
const char *red_optarg; /* argument associated with option */
|
||||
|
||||
#define PRINT_ERROR ((red_opterr) && (*options != ':'))
|
||||
|
||||
#define FLAG_PERMUTE 0x01 /* permute non-options to the end of argv */
|
||||
#define FLAG_ALLARGS 0x02 /* treat non-options as args to option "-1" */
|
||||
#define FLAG_LONGONLY 0x04 /* operate as RedGetoptLongOnly */
|
||||
|
||||
/* return values */
|
||||
#define BADCH (int)'?'
|
||||
#define BADARG ((*options == ':') ? (int)':' : (int)'?')
|
||||
#define INORDER (int)1
|
||||
|
||||
#define EMSG ""
|
||||
|
||||
#define NO_PREFIX (-1)
|
||||
#define D_PREFIX 0
|
||||
#define DD_PREFIX 1
|
||||
#define W_PREFIX 2
|
||||
|
||||
static int gcd(int a, int b);
|
||||
static void permute_args(int panonopt_start, int panonopt_end, int opt_end, char * const *nargv);
|
||||
static int parse_long_options(char * const *nargv, const char *options, const REDOPTION *long_options, int32_t *idx, int short_too, int flags);
|
||||
static int getopt_internal(int nargc, char * const *nargv, const char *options, const REDOPTION *long_options, int32_t *idx, int flags);
|
||||
|
||||
static const char *place = EMSG; /* option letter processing */
|
||||
|
||||
/* XXX: set red_optreset to 1 rather than these two */
|
||||
static int nonopt_start = -1; /* first non option argument (for permute) */
|
||||
static int nonopt_end = -1; /* first option after non options (for permute) */
|
||||
|
||||
/* Error messages */
|
||||
static const char recargchar[] = "option requires an argument -- %c\n";
|
||||
static const char illoptchar[] = "illegal option -- %c\n"; /* From P1003.2 */
|
||||
static int dash_prefix = NO_PREFIX;
|
||||
static const char gnuoptchar[] = "invalid option -- %c\n";
|
||||
|
||||
static const char recargstring[] = "option `%s%s' requires an argument\n";
|
||||
static const char ambig[] = "option `%s%s' is ambiguous\n";
|
||||
static const char noarg[] = "option `%s%s' doesn't allow an argument\n";
|
||||
static const char illoptstring[] = "unrecognized option `%s%s'\n";
|
||||
|
||||
/*
|
||||
* Compute the greatest common divisor of a and b.
|
||||
*/
|
||||
static int
|
||||
gcd(int a, int b)
|
||||
{
|
||||
int c;
|
||||
|
||||
c = a % b;
|
||||
while (c != 0) {
|
||||
a = b;
|
||||
b = c;
|
||||
c = a % b;
|
||||
}
|
||||
|
||||
return (b);
|
||||
}
|
||||
|
||||
/*
|
||||
* Exchange the block from nonopt_start to nonopt_end with the block
|
||||
* from nonopt_end to opt_end (keeping the same order of arguments
|
||||
* in each block).
|
||||
*/
|
||||
static void
|
||||
permute_args(int panonopt_start, int panonopt_end, int opt_end,
|
||||
char * const *nargv)
|
||||
{
|
||||
int cstart, cyclelen, i, j, ncycle, nnonopts, nopts, pos;
|
||||
char *swap;
|
||||
|
||||
/*
|
||||
* compute lengths of blocks and number and size of cycles
|
||||
*/
|
||||
nnonopts = panonopt_end - panonopt_start;
|
||||
nopts = opt_end - panonopt_end;
|
||||
ncycle = gcd(nnonopts, nopts);
|
||||
cyclelen = (opt_end - panonopt_start) / ncycle;
|
||||
|
||||
for (i = 0; i < ncycle; i++) {
|
||||
cstart = panonopt_end+i;
|
||||
pos = cstart;
|
||||
for (j = 0; j < cyclelen; j++) {
|
||||
if (pos >= panonopt_end)
|
||||
pos -= nnonopts;
|
||||
else
|
||||
pos += nopts;
|
||||
swap = nargv[pos];
|
||||
((char **) nargv)[pos] = nargv[cstart];
|
||||
((char **)nargv)[cstart] = swap;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* parse_long_options --
|
||||
* Parse long options in argc/argv argument vector.
|
||||
* Returns -1 if short_too is set and the option does not match long_options.
|
||||
*/
|
||||
static int
|
||||
parse_long_options(char * const *nargv, const char *options,
|
||||
const REDOPTION *long_options, int32_t *idx, int short_too, int flags)
|
||||
{
|
||||
const char *current_argv, *has_equal, *current_dash;
|
||||
size_t current_argv_len;
|
||||
int i, match, exact_match, second_partial_match;
|
||||
|
||||
current_argv = place;
|
||||
switch (dash_prefix) {
|
||||
case D_PREFIX:
|
||||
current_dash = "-";
|
||||
break;
|
||||
case DD_PREFIX:
|
||||
current_dash = "--";
|
||||
break;
|
||||
case W_PREFIX:
|
||||
current_dash = "-W ";
|
||||
break;
|
||||
default:
|
||||
current_dash = "";
|
||||
break;
|
||||
}
|
||||
match = -1;
|
||||
exact_match = 0;
|
||||
second_partial_match = 0;
|
||||
|
||||
red_optind++;
|
||||
|
||||
if ((has_equal = strchr(current_argv, '=')) != NULL) {
|
||||
/* argument found (--option=arg) */
|
||||
current_argv_len = has_equal - current_argv;
|
||||
has_equal++;
|
||||
} else
|
||||
current_argv_len = strlen(current_argv);
|
||||
|
||||
for (i = 0; long_options[i].name; i++) {
|
||||
/* find matching long option */
|
||||
if (strncmp(current_argv, long_options[i].name,
|
||||
current_argv_len))
|
||||
continue;
|
||||
|
||||
if (strlen(long_options[i].name) == current_argv_len) {
|
||||
/* exact match */
|
||||
match = i;
|
||||
exact_match = 1;
|
||||
break;
|
||||
}
|
||||
/*
|
||||
* If this is a known short option, don't allow
|
||||
* a partial match of a single character.
|
||||
*/
|
||||
if (short_too && current_argv_len == 1)
|
||||
continue;
|
||||
|
||||
if (match == -1) /* first partial match */
|
||||
match = i;
|
||||
else if ((flags & FLAG_LONGONLY) ||
|
||||
long_options[i].has_arg !=
|
||||
long_options[match].has_arg ||
|
||||
long_options[i].flag != long_options[match].flag ||
|
||||
long_options[i].val != long_options[match].val)
|
||||
second_partial_match = 1;
|
||||
}
|
||||
if (!exact_match && second_partial_match) {
|
||||
/* ambiguous abbreviation */
|
||||
if (PRINT_ERROR)
|
||||
fprintf(stderr,
|
||||
ambig,
|
||||
current_dash,
|
||||
current_argv);
|
||||
red_optopt = 0;
|
||||
return (BADCH);
|
||||
}
|
||||
if (match != -1) { /* option found */
|
||||
if (long_options[match].has_arg == red_no_argument
|
||||
&& has_equal) {
|
||||
if (PRINT_ERROR)
|
||||
fprintf(stderr,
|
||||
noarg,
|
||||
current_dash,
|
||||
current_argv);
|
||||
/*
|
||||
* XXX: GNU sets red_optopt to val regardless of flag
|
||||
*/
|
||||
if (long_options[match].flag == NULL)
|
||||
red_optopt = long_options[match].val;
|
||||
else
|
||||
red_optopt = 0;
|
||||
return (BADCH);
|
||||
}
|
||||
if (long_options[match].has_arg == red_required_argument ||
|
||||
long_options[match].has_arg == red_optional_argument) {
|
||||
if (has_equal)
|
||||
red_optarg = has_equal;
|
||||
else if (long_options[match].has_arg ==
|
||||
red_required_argument) {
|
||||
/*
|
||||
* optional argument doesn't use next nargv
|
||||
*/
|
||||
red_optarg = nargv[red_optind++];
|
||||
}
|
||||
}
|
||||
if ((long_options[match].has_arg == red_required_argument)
|
||||
&& (red_optarg == NULL)) {
|
||||
/*
|
||||
* Missing argument; leading ':' indicates no error
|
||||
* should be generated.
|
||||
*/
|
||||
if (PRINT_ERROR)
|
||||
fprintf(stderr,
|
||||
recargstring,
|
||||
current_dash,
|
||||
current_argv);
|
||||
/*
|
||||
* XXX: GNU sets red_optopt to val regardless of flag
|
||||
*/
|
||||
if (long_options[match].flag == NULL)
|
||||
red_optopt = long_options[match].val;
|
||||
else
|
||||
red_optopt = 0;
|
||||
--red_optind;
|
||||
return (BADARG);
|
||||
}
|
||||
} else { /* unknown option */
|
||||
if (short_too) {
|
||||
--red_optind;
|
||||
return (-1);
|
||||
}
|
||||
if (PRINT_ERROR)
|
||||
fprintf(stderr,
|
||||
illoptstring,
|
||||
current_dash,
|
||||
current_argv);
|
||||
red_optopt = 0;
|
||||
return (BADCH);
|
||||
}
|
||||
if (idx)
|
||||
*idx = match;
|
||||
if (long_options[match].flag) {
|
||||
*long_options[match].flag = long_options[match].val;
|
||||
return (0);
|
||||
} else
|
||||
return (long_options[match].val);
|
||||
}
|
||||
|
||||
/*
|
||||
* getopt_internal --
|
||||
* Parse argc/argv argument vector. Called by user level routines.
|
||||
*/
|
||||
static int
|
||||
getopt_internal(int nargc, char * const *nargv, const char *options,
|
||||
const REDOPTION *long_options, int32_t *idx, int flags)
|
||||
{
|
||||
char *oli; /* option letter list index */
|
||||
int optchar, short_too;
|
||||
|
||||
if (options == NULL)
|
||||
return (-1);
|
||||
|
||||
/*
|
||||
* XXX Some GNU programs (like cvs) set red_optind to 0 instead of
|
||||
* XXX using red_optreset. Work around this braindamage.
|
||||
*/
|
||||
if (red_optind == 0)
|
||||
red_optind = red_optreset = 1;
|
||||
|
||||
/*
|
||||
* Disable GNU extensions if options string begins with a '+'.
|
||||
*/
|
||||
if (*options == '-')
|
||||
flags |= FLAG_ALLARGS;
|
||||
else if (*options == '+')
|
||||
flags &= ~FLAG_PERMUTE;
|
||||
if (*options == '+' || *options == '-')
|
||||
options++;
|
||||
|
||||
red_optarg = NULL;
|
||||
if (red_optreset)
|
||||
nonopt_start = nonopt_end = -1;
|
||||
start:
|
||||
if (red_optreset || !*place) { /* update scanning pointer */
|
||||
red_optreset = 0;
|
||||
if (red_optind >= nargc) { /* end of argument vector */
|
||||
place = EMSG;
|
||||
if (nonopt_end != -1) {
|
||||
/* do permutation, if we have to */
|
||||
permute_args(nonopt_start, nonopt_end,
|
||||
red_optind, nargv);
|
||||
red_optind -= nonopt_end - nonopt_start;
|
||||
}
|
||||
else if (nonopt_start != -1) {
|
||||
/*
|
||||
* If we skipped non-options, set red_optind
|
||||
* to the first of them.
|
||||
*/
|
||||
red_optind = nonopt_start;
|
||||
}
|
||||
nonopt_start = nonopt_end = -1;
|
||||
return (-1);
|
||||
}
|
||||
if (*(place = nargv[red_optind]) != '-' || place[1] == '\0') {
|
||||
place = EMSG; /* found non-option */
|
||||
if (flags & FLAG_ALLARGS) {
|
||||
/*
|
||||
* GNU extension:
|
||||
* return non-option as argument to option 1
|
||||
*/
|
||||
red_optarg = nargv[red_optind++];
|
||||
return (INORDER);
|
||||
}
|
||||
if (!(flags & FLAG_PERMUTE)) {
|
||||
/*
|
||||
* If no permutation wanted, stop parsing
|
||||
* at first non-option.
|
||||
*/
|
||||
return (-1);
|
||||
}
|
||||
/* do permutation */
|
||||
if (nonopt_start == -1)
|
||||
nonopt_start = red_optind;
|
||||
else if (nonopt_end != -1) {
|
||||
permute_args(nonopt_start, nonopt_end,
|
||||
red_optind, nargv);
|
||||
nonopt_start = red_optind -
|
||||
(nonopt_end - nonopt_start);
|
||||
nonopt_end = -1;
|
||||
}
|
||||
red_optind++;
|
||||
/* process next argument */
|
||||
goto start;
|
||||
}
|
||||
if (nonopt_start != -1 && nonopt_end == -1)
|
||||
nonopt_end = red_optind;
|
||||
|
||||
/*
|
||||
* If we have "-" do nothing, if "--" we are done.
|
||||
*/
|
||||
if (place[1] != '\0' && *++place == '-' && place[1] == '\0') {
|
||||
red_optind++;
|
||||
place = EMSG;
|
||||
/*
|
||||
* We found an option (--), so if we skipped
|
||||
* non-options, we have to permute.
|
||||
*/
|
||||
if (nonopt_end != -1) {
|
||||
permute_args(nonopt_start, nonopt_end,
|
||||
red_optind, nargv);
|
||||
red_optind -= nonopt_end - nonopt_start;
|
||||
}
|
||||
nonopt_start = nonopt_end = -1;
|
||||
return (-1);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Check long options if:
|
||||
* 1) we were passed some
|
||||
* 2) the arg is not just "-"
|
||||
* 3) either the arg starts with -- we are RedGetoptLongOnly()
|
||||
*/
|
||||
if (long_options != NULL && place != nargv[red_optind] &&
|
||||
(*place == '-' || (flags & FLAG_LONGONLY))) {
|
||||
short_too = 0;
|
||||
dash_prefix = D_PREFIX;
|
||||
if (*place == '-') {
|
||||
place++; /* --foo long option */
|
||||
dash_prefix = DD_PREFIX;
|
||||
} else if (*place != ':' && strchr(options, *place) != NULL)
|
||||
short_too = 1; /* could be short option too */
|
||||
|
||||
optchar = parse_long_options(nargv, options, long_options,
|
||||
idx, short_too, flags);
|
||||
if (optchar != -1) {
|
||||
place = EMSG;
|
||||
return (optchar);
|
||||
}
|
||||
}
|
||||
|
||||
if ((optchar = (int)*place++) == (int)':' ||
|
||||
(optchar == (int)'-' && *place != '\0') ||
|
||||
(oli = strchr(options, optchar)) == NULL) {
|
||||
/*
|
||||
* If the user specified "-" and '-' isn't listed in
|
||||
* options, return -1 (non-option) as per POSIX.
|
||||
* Otherwise, it is an unknown option character (or ':').
|
||||
*/
|
||||
if (optchar == (int)'-' && *place == '\0')
|
||||
return (-1);
|
||||
if (!*place)
|
||||
++red_optind;
|
||||
if (PRINT_ERROR)
|
||||
fprintf(stderr, gnuoptchar, optchar);
|
||||
red_optopt = optchar;
|
||||
return (BADCH);
|
||||
}
|
||||
if (long_options != NULL && optchar == 'W' && oli[1] == ';') {
|
||||
/* -W long-option */
|
||||
if (*place) /* no space */
|
||||
/* NOTHING */;
|
||||
else if (++red_optind >= nargc) { /* no arg */
|
||||
place = EMSG;
|
||||
if (PRINT_ERROR)
|
||||
fprintf(stderr, recargchar, optchar);
|
||||
red_optopt = optchar;
|
||||
return (BADARG);
|
||||
} else /* white space */
|
||||
place = nargv[red_optind];
|
||||
dash_prefix = W_PREFIX;
|
||||
optchar = parse_long_options(nargv, options, long_options,
|
||||
idx, 0, flags);
|
||||
place = EMSG;
|
||||
return (optchar);
|
||||
}
|
||||
if (*++oli != ':') { /* doesn't take argument */
|
||||
if (!*place)
|
||||
++red_optind;
|
||||
} else { /* takes (optional) argument */
|
||||
red_optarg = NULL;
|
||||
if (*place) /* no white space */
|
||||
red_optarg = place;
|
||||
else if (oli[1] != ':') { /* arg not optional */
|
||||
if (++red_optind >= nargc) { /* no arg */
|
||||
place = EMSG;
|
||||
if (PRINT_ERROR)
|
||||
fprintf(stderr, recargchar, optchar);
|
||||
red_optopt = optchar;
|
||||
return (BADARG);
|
||||
} else
|
||||
red_optarg = nargv[red_optind];
|
||||
}
|
||||
place = EMSG;
|
||||
++red_optind;
|
||||
}
|
||||
/* dump back option letter */
|
||||
return (optchar);
|
||||
}
|
||||
|
||||
|
||||
/** @brief Get option character from command line argument list.
|
||||
|
||||
For more details, consult the getopt() man pages, since this function is
|
||||
generally similar.
|
||||
|
||||
@param nargc Number of arguments (argc passed into main()).
|
||||
@param nargv Argument vector (argv passed into main()).
|
||||
@param options String of option characters.
|
||||
|
||||
@return The next known option character in @p options. If a character not
|
||||
found in @p options is found or if an option is missing an argument,
|
||||
it returns '?'. Returns -1 when the argument list is exhausted.
|
||||
*/
|
||||
int32_t RedGetopt(
|
||||
int32_t nargc,
|
||||
char * const *nargv,
|
||||
const char *options)
|
||||
{
|
||||
return getopt_internal(nargc, nargv, options, NULL, NULL, FLAG_PERMUTE);
|
||||
}
|
||||
|
||||
|
||||
/** @brief Get long options from command line argument list.
|
||||
|
||||
For more details, consult the getopt_long() man pages, since this function
|
||||
is generally similar.
|
||||
|
||||
@param nargc Number of arguments (argc passed into main()).
|
||||
@param nargv Argument vector (argv passed into main()).
|
||||
@param options String of option characters.
|
||||
@param long_options The long options; the last element of this array must be
|
||||
filled with zeroes.
|
||||
@param idx If non-NULL, then populated with the index of the long
|
||||
option relative to @p long_options.
|
||||
|
||||
@return If the flag field in REDOPTION is NULL, returns the value specified
|
||||
in the val field, which is usually just the corresponding short
|
||||
option. If flag is non-NULL, returns zero and stores val in the
|
||||
location pointed to by flag. Returns ':' if an option was missing
|
||||
its argument, '?' for an unknown option, and -1 when the argument
|
||||
list is exhausted.
|
||||
*/
|
||||
int32_t RedGetoptLong(
|
||||
int32_t nargc,
|
||||
char * const *nargv,
|
||||
const char *options,
|
||||
const REDOPTION *long_options,
|
||||
int32_t *idx)
|
||||
{
|
||||
return getopt_internal(nargc, nargv, options, long_options, idx, FLAG_PERMUTE);
|
||||
}
|
||||
|
@@ -0,0 +1,99 @@
|
||||
/* ----> DO NOT REMOVE THE FOLLOWING NOTICE <----
|
||||
|
||||
Copyright (c) 2014-2015 Datalight, Inc.
|
||||
All Rights Reserved Worldwide.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; use version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but "AS-IS," WITHOUT ANY WARRANTY; without even the implied warranty
|
||||
of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
/* Businesses and individuals that for commercial or other reasons cannot
|
||||
comply with the terms of the GPLv2 license may obtain a commercial license
|
||||
before incorporating Reliance Edge into proprietary software for
|
||||
distribution in any form. Visit http://www.datalight.com/reliance-edge for
|
||||
more information.
|
||||
*/
|
||||
/** @file
|
||||
@brief Implements common-code utilities for tools and tests.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
|
||||
#include <redfs.h>
|
||||
#include <redcoreapi.h>
|
||||
#include <redvolume.h>
|
||||
#include <redtoolcmn.h>
|
||||
|
||||
|
||||
/** @brief Convert a string into a volume number.
|
||||
|
||||
In a POSIX-like configuration, @p pszVolume can either be a volume number or
|
||||
a volume path prefix. In case of ambiguity, the volume number of a matching
|
||||
path prefix takes precedence.
|
||||
|
||||
In an FSE configuration, @p pszVolume can be a volume number.
|
||||
|
||||
@param pszVolume The volume string.
|
||||
|
||||
@return On success, returns the volume number; on failure, returns
|
||||
#REDCONF_VOLUME_COUNT.
|
||||
*/
|
||||
uint8_t RedFindVolumeNumber(
|
||||
const char *pszVolume)
|
||||
{
|
||||
unsigned long ulNumber;
|
||||
const char *pszEndPtr;
|
||||
uint8_t bVolNum = REDCONF_VOLUME_COUNT;
|
||||
#if REDCONF_API_POSIX == 1
|
||||
uint8_t bIndex;
|
||||
#endif
|
||||
|
||||
/* Determine if pszVolume can be interpreted as a volume number.
|
||||
*/
|
||||
errno = 0;
|
||||
ulNumber = strtoul(pszVolume, (char **)&pszEndPtr, 10);
|
||||
if((errno == 0) && (ulNumber != ULONG_MAX) && (pszEndPtr[0U] == '\0') && (ulNumber < REDCONF_VOLUME_COUNT))
|
||||
{
|
||||
bVolNum = (uint8_t)ulNumber;
|
||||
}
|
||||
|
||||
#if REDCONF_API_POSIX == 1
|
||||
/* Determine if pszVolume is a valid path prefix.
|
||||
*/
|
||||
for(bIndex = 0U; bIndex < REDCONF_VOLUME_COUNT; bIndex++)
|
||||
{
|
||||
if(strcmp(gaRedVolConf[bIndex].pszPathPrefix, pszVolume) == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(bIndex < REDCONF_VOLUME_COUNT)
|
||||
{
|
||||
/* Edge case: It is technically possible for pszVolume to be both a
|
||||
valid volume number and a valid volume prefix, for different
|
||||
volumes. For example, if pszVolume is "2", that would be recognized
|
||||
as volume number 2 above. But if "2" is the (poorly chosen) path
|
||||
prefix for volume number 4, that would also be matched. Since the
|
||||
POSIX-like API is primarily name based, and the ability to use
|
||||
volume numbers with this tool is just a convenience, the volume
|
||||
prefix takes precedence.
|
||||
*/
|
||||
bVolNum = bIndex;
|
||||
}
|
||||
#endif
|
||||
|
||||
return bVolNum;
|
||||
}
|
||||
|
101
FreeRTOSv10.2.1/FreeRTOS-Plus/Source/Reliance-Edge/util/bitmap.c
Normal file
101
FreeRTOSv10.2.1/FreeRTOS-Plus/Source/Reliance-Edge/util/bitmap.c
Normal file
@@ -0,0 +1,101 @@
|
||||
/* ----> DO NOT REMOVE THE FOLLOWING NOTICE <----
|
||||
|
||||
Copyright (c) 2014-2015 Datalight, Inc.
|
||||
All Rights Reserved Worldwide.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; use version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but "AS-IS," WITHOUT ANY WARRANTY; without even the implied warranty
|
||||
of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
/* Businesses and individuals that for commercial or other reasons cannot
|
||||
comply with the terms of the GPLv2 license may obtain a commercial license
|
||||
before incorporating Reliance Edge into proprietary software for
|
||||
distribution in any form. Visit http://www.datalight.com/reliance-edge for
|
||||
more information.
|
||||
*/
|
||||
/** @file
|
||||
@brief Implements utilities for working with bitmaps.
|
||||
*/
|
||||
#include <redfs.h>
|
||||
|
||||
|
||||
/** @brief Query the state of a bit in a bitmap.
|
||||
|
||||
Bits are counted from most significant to least significant. Thus, the mask
|
||||
for bit zero is 0x80 applied to the first byte in the bitmap.
|
||||
|
||||
@param pbBitmap Pointer to the bitmap.
|
||||
@param ulBit The bit to query.
|
||||
|
||||
@retval Whether the bit is set (true) or clear (false.
|
||||
*/
|
||||
bool RedBitGet(
|
||||
const uint8_t *pbBitmap,
|
||||
uint32_t ulBit)
|
||||
{
|
||||
bool fRet;
|
||||
|
||||
if(pbBitmap == NULL)
|
||||
{
|
||||
REDERROR();
|
||||
fRet = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
fRet = (pbBitmap[ulBit >> 3U] & (0x80U >> (ulBit & 7U))) != 0U;
|
||||
}
|
||||
|
||||
return fRet;
|
||||
}
|
||||
|
||||
|
||||
/** @brief Set a bit in a bitmap to one.
|
||||
|
||||
Bits are counted from most significant to least significant. Thus, the mask
|
||||
for bit zero is 0x80 applied to the first byte in the bitmap.
|
||||
|
||||
@param pbBitmap Pointer to the bitmap.
|
||||
@param ulBit The bit to set.
|
||||
*/
|
||||
void RedBitSet(
|
||||
uint8_t *pbBitmap,
|
||||
uint32_t ulBit)
|
||||
{
|
||||
REDASSERT(pbBitmap != NULL);
|
||||
|
||||
if(pbBitmap != NULL)
|
||||
{
|
||||
pbBitmap[ulBit >> 3U] |= (0x80U >> (ulBit & 7U));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/** @brief Clear a bit in a bitmap to zero.
|
||||
|
||||
Bits are counted from most significant to least significant. Thus, the mask
|
||||
for bit zero is 0x80 applied to the first byte in the bitmap.
|
||||
|
||||
@param pbBitmap Pointer to the bitmap.
|
||||
@param ulBit The bit to clear.
|
||||
*/
|
||||
void RedBitClear(
|
||||
uint8_t *pbBitmap,
|
||||
uint32_t ulBit)
|
||||
{
|
||||
REDASSERT(pbBitmap != NULL);
|
||||
|
||||
if(pbBitmap != NULL)
|
||||
{
|
||||
pbBitmap[ulBit >> 3U] &= ~(0x80U >> (ulBit & 7U));
|
||||
}
|
||||
}
|
||||
|
598
FreeRTOSv10.2.1/FreeRTOS-Plus/Source/Reliance-Edge/util/crc.c
Normal file
598
FreeRTOSv10.2.1/FreeRTOS-Plus/Source/Reliance-Edge/util/crc.c
Normal file
@@ -0,0 +1,598 @@
|
||||
/* ----> DO NOT REMOVE THE FOLLOWING NOTICE <----
|
||||
|
||||
Copyright (c) 2014-2015 Datalight, Inc.
|
||||
All Rights Reserved Worldwide.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; use version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but "AS-IS," WITHOUT ANY WARRANTY; without even the implied warranty
|
||||
of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
/* Businesses and individuals that for commercial or other reasons cannot
|
||||
comply with the terms of the GPLv2 license may obtain a commercial license
|
||||
before incorporating Reliance Edge into proprietary software for
|
||||
distribution in any form. Visit http://www.datalight.com/reliance-edge for
|
||||
more information.
|
||||
*/
|
||||
/** @file
|
||||
@brief Implements utilities for calculating CRC-32 checksums.
|
||||
*/
|
||||
#include <redfs.h>
|
||||
|
||||
|
||||
/* The CRC functions do not return errors since the only detectable error
|
||||
condition is a NULL buffer pointer. If such a condition does arise, the
|
||||
functions assert and return the below CRC, which, although a legal CRC,
|
||||
is nonetheless suspicious and could provide a clue that something has
|
||||
gone wrong.
|
||||
*/
|
||||
#define SUSPICIOUS_CRC_VALUE (0xBAADC0DEU)
|
||||
|
||||
#define CRC_BITWISE (0U)
|
||||
#define CRC_SARWATE (1U)
|
||||
#define CRC_SLICEBY8 (2U)
|
||||
|
||||
|
||||
#if REDCONF_CRC_ALGORITHM == CRC_BITWISE
|
||||
|
||||
/* The following is representative of the polynomial accepted by CCITT 32-bit
|
||||
and in IEEE 802.3, Ethernet 2 specification.
|
||||
|
||||
x^32+x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x+1
|
||||
(reverse order)
|
||||
1110 1101 1011 1000 1000 0011 0010 0000 1
|
||||
(E) (D) (B) (8) (8) (3) (2) (0)
|
||||
*/
|
||||
#define CCITT_32_POLYNOMIAL (0xEDB88320U)
|
||||
|
||||
|
||||
/** @brief Compute a CRC32 for the given data buffer.
|
||||
|
||||
For CCITT-32 compliance, the initial CRC must be set to 0. To CRC multiple
|
||||
buffers, call this function with the previously returned CRC value.
|
||||
|
||||
@param ulInitCrc32 Starting CRC value.
|
||||
@param pBuffer Data buffer to calculate the CRC from.
|
||||
@param ulLength Number of bytes of data in the given buffer.
|
||||
|
||||
@return The updated CRC value.
|
||||
*/
|
||||
uint32_t RedCrc32Update(
|
||||
uint32_t ulInitCrc32,
|
||||
const void *pBuffer,
|
||||
uint32_t ulLength)
|
||||
{
|
||||
uint32_t ulCrc32;
|
||||
|
||||
if(pBuffer == NULL)
|
||||
{
|
||||
REDERROR();
|
||||
ulCrc32 = SUSPICIOUS_CRC_VALUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
const uint8_t *pbBuffer = CAST_VOID_PTR_TO_CONST_UINT8_PTR(pBuffer);
|
||||
uint32_t ulIdx;
|
||||
|
||||
ulCrc32 = ~ulInitCrc32;
|
||||
|
||||
for(ulIdx = 0U; ulIdx < ulLength; ++ulIdx)
|
||||
{
|
||||
uint32_t ulBit;
|
||||
|
||||
ulCrc32 ^= pbBuffer[ulIdx];
|
||||
|
||||
/* Branchless inner loop (greatly improves performance).
|
||||
*/
|
||||
for(ulBit = 0U; ulBit < 8U; ulBit++)
|
||||
{
|
||||
ulCrc32 = ((ulCrc32 & 1U) * CCITT_32_POLYNOMIAL) ^ (ulCrc32 >> 1U);
|
||||
}
|
||||
}
|
||||
|
||||
ulCrc32 = ~ulCrc32;
|
||||
}
|
||||
|
||||
return ulCrc32;
|
||||
}
|
||||
|
||||
#elif REDCONF_CRC_ALGORITHM == CRC_SARWATE
|
||||
|
||||
/** @brief Compute a CRC32 for the given data buffer.
|
||||
|
||||
For CCITT-32 compliance, the initial CRC must be set to 0. To CRC multiple
|
||||
buffers, call this function with the previously returned CRC value.
|
||||
|
||||
@param ulInitCrc32 Starting CRC value.
|
||||
@param pBuffer Data buffer to calculate the CRC from.
|
||||
@param ulLength Number of bytes of data in the given buffer.
|
||||
|
||||
@return The updated CRC value.
|
||||
*/
|
||||
uint32_t RedCrc32Update(
|
||||
uint32_t ulInitCrc32,
|
||||
const void *pBuffer,
|
||||
uint32_t ulLength)
|
||||
{
|
||||
static const uint32_t aulCrc32Table[] =
|
||||
{
|
||||
0x00000000U, 0x77073096U, 0xEE0E612CU, 0x990951BAU, 0x076DC419U, 0x706AF48FU, 0xE963A535U, 0x9E6495A3U,
|
||||
0x0EDB8832U, 0x79DCB8A4U, 0xE0D5E91EU, 0x97D2D988U, 0x09B64C2BU, 0x7EB17CBDU, 0xE7B82D07U, 0x90BF1D91U,
|
||||
0x1DB71064U, 0x6AB020F2U, 0xF3B97148U, 0x84BE41DEU, 0x1ADAD47DU, 0x6DDDE4EBU, 0xF4D4B551U, 0x83D385C7U,
|
||||
0x136C9856U, 0x646BA8C0U, 0xFD62F97AU, 0x8A65C9ECU, 0x14015C4FU, 0x63066CD9U, 0xFA0F3D63U, 0x8D080DF5U,
|
||||
0x3B6E20C8U, 0x4C69105EU, 0xD56041E4U, 0xA2677172U, 0x3C03E4D1U, 0x4B04D447U, 0xD20D85FDU, 0xA50AB56BU,
|
||||
0x35B5A8FAU, 0x42B2986CU, 0xDBBBC9D6U, 0xACBCF940U, 0x32D86CE3U, 0x45DF5C75U, 0xDCD60DCFU, 0xABD13D59U,
|
||||
0x26D930ACU, 0x51DE003AU, 0xC8D75180U, 0xBFD06116U, 0x21B4F4B5U, 0x56B3C423U, 0xCFBA9599U, 0xB8BDA50FU,
|
||||
0x2802B89EU, 0x5F058808U, 0xC60CD9B2U, 0xB10BE924U, 0x2F6F7C87U, 0x58684C11U, 0xC1611DABU, 0xB6662D3DU,
|
||||
0x76DC4190U, 0x01DB7106U, 0x98D220BCU, 0xEFD5102AU, 0x71B18589U, 0x06B6B51FU, 0x9FBFE4A5U, 0xE8B8D433U,
|
||||
0x7807C9A2U, 0x0F00F934U, 0x9609A88EU, 0xE10E9818U, 0x7F6A0DBBU, 0x086D3D2DU, 0x91646C97U, 0xE6635C01U,
|
||||
0x6B6B51F4U, 0x1C6C6162U, 0x856530D8U, 0xF262004EU, 0x6C0695EDU, 0x1B01A57BU, 0x8208F4C1U, 0xF50FC457U,
|
||||
0x65B0D9C6U, 0x12B7E950U, 0x8BBEB8EAU, 0xFCB9887CU, 0x62DD1DDFU, 0x15DA2D49U, 0x8CD37CF3U, 0xFBD44C65U,
|
||||
0x4DB26158U, 0x3AB551CEU, 0xA3BC0074U, 0xD4BB30E2U, 0x4ADFA541U, 0x3DD895D7U, 0xA4D1C46DU, 0xD3D6F4FBU,
|
||||
0x4369E96AU, 0x346ED9FCU, 0xAD678846U, 0xDA60B8D0U, 0x44042D73U, 0x33031DE5U, 0xAA0A4C5FU, 0xDD0D7CC9U,
|
||||
0x5005713CU, 0x270241AAU, 0xBE0B1010U, 0xC90C2086U, 0x5768B525U, 0x206F85B3U, 0xB966D409U, 0xCE61E49FU,
|
||||
0x5EDEF90EU, 0x29D9C998U, 0xB0D09822U, 0xC7D7A8B4U, 0x59B33D17U, 0x2EB40D81U, 0xB7BD5C3BU, 0xC0BA6CADU,
|
||||
0xEDB88320U, 0x9ABFB3B6U, 0x03B6E20CU, 0x74B1D29AU, 0xEAD54739U, 0x9DD277AFU, 0x04DB2615U, 0x73DC1683U,
|
||||
0xE3630B12U, 0x94643B84U, 0x0D6D6A3EU, 0x7A6A5AA8U, 0xE40ECF0BU, 0x9309FF9DU, 0x0A00AE27U, 0x7D079EB1U,
|
||||
0xF00F9344U, 0x8708A3D2U, 0x1E01F268U, 0x6906C2FEU, 0xF762575DU, 0x806567CBU, 0x196C3671U, 0x6E6B06E7U,
|
||||
0xFED41B76U, 0x89D32BE0U, 0x10DA7A5AU, 0x67DD4ACCU, 0xF9B9DF6FU, 0x8EBEEFF9U, 0x17B7BE43U, 0x60B08ED5U,
|
||||
0xD6D6A3E8U, 0xA1D1937EU, 0x38D8C2C4U, 0x4FDFF252U, 0xD1BB67F1U, 0xA6BC5767U, 0x3FB506DDU, 0x48B2364BU,
|
||||
0xD80D2BDAU, 0xAF0A1B4CU, 0x36034AF6U, 0x41047A60U, 0xDF60EFC3U, 0xA867DF55U, 0x316E8EEFU, 0x4669BE79U,
|
||||
0xCB61B38CU, 0xBC66831AU, 0x256FD2A0U, 0x5268E236U, 0xCC0C7795U, 0xBB0B4703U, 0x220216B9U, 0x5505262FU,
|
||||
0xC5BA3BBEU, 0xB2BD0B28U, 0x2BB45A92U, 0x5CB36A04U, 0xC2D7FFA7U, 0xB5D0CF31U, 0x2CD99E8BU, 0x5BDEAE1DU,
|
||||
0x9B64C2B0U, 0xEC63F226U, 0x756AA39CU, 0x026D930AU, 0x9C0906A9U, 0xEB0E363FU, 0x72076785U, 0x05005713U,
|
||||
0x95BF4A82U, 0xE2B87A14U, 0x7BB12BAEU, 0x0CB61B38U, 0x92D28E9BU, 0xE5D5BE0DU, 0x7CDCEFB7U, 0x0BDBDF21U,
|
||||
0x86D3D2D4U, 0xF1D4E242U, 0x68DDB3F8U, 0x1FDA836EU, 0x81BE16CDU, 0xF6B9265BU, 0x6FB077E1U, 0x18B74777U,
|
||||
0x88085AE6U, 0xFF0F6A70U, 0x66063BCAU, 0x11010B5CU, 0x8F659EFFU, 0xF862AE69U, 0x616BFFD3U, 0x166CCF45U,
|
||||
0xA00AE278U, 0xD70DD2EEU, 0x4E048354U, 0x3903B3C2U, 0xA7672661U, 0xD06016F7U, 0x4969474DU, 0x3E6E77DBU,
|
||||
0xAED16A4AU, 0xD9D65ADCU, 0x40DF0B66U, 0x37D83BF0U, 0xA9BCAE53U, 0xDEBB9EC5U, 0x47B2CF7FU, 0x30B5FFE9U,
|
||||
0xBDBDF21CU, 0xCABAC28AU, 0x53B39330U, 0x24B4A3A6U, 0xBAD03605U, 0xCDD70693U, 0x54DE5729U, 0x23D967BFU,
|
||||
0xB3667A2EU, 0xC4614AB8U, 0x5D681B02U, 0x2A6F2B94U, 0xB40BBE37U, 0xC30C8EA1U, 0x5A05DF1BU, 0x2D02EF8DU,
|
||||
};
|
||||
|
||||
uint32_t ulCrc32;
|
||||
|
||||
if(pBuffer == NULL)
|
||||
{
|
||||
REDERROR();
|
||||
ulCrc32 = SUSPICIOUS_CRC_VALUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
const uint8_t *pbBuffer = CAST_VOID_PTR_TO_CONST_UINT8_PTR(pBuffer);
|
||||
uint32_t ulIdx;
|
||||
|
||||
ulCrc32 = ~ulInitCrc32;
|
||||
|
||||
for(ulIdx = 0U; ulIdx < ulLength; ++ulIdx)
|
||||
{
|
||||
ulCrc32 = (ulCrc32 >> 8U) ^ aulCrc32Table[(ulCrc32 ^ pbBuffer[ulIdx]) & 0xFFU];
|
||||
}
|
||||
|
||||
ulCrc32 = ~ulCrc32;
|
||||
}
|
||||
|
||||
return ulCrc32;
|
||||
}
|
||||
|
||||
#elif REDCONF_CRC_ALGORITHM == CRC_SLICEBY8
|
||||
|
||||
|
||||
/** @brief Compute a CRC32 for the given data buffer.
|
||||
|
||||
For CCITT-32 compliance, the initial CRC must be set to 0. To CRC multiple
|
||||
buffers, call this function with the previously returned CRC value.
|
||||
|
||||
@param ulInitCrc32 Starting CRC value.
|
||||
@param pBuffer Data buffer to calculate the CRC from.
|
||||
@param ulLength Number of bytes of data in the given buffer.
|
||||
|
||||
@return The updated CRC value.
|
||||
*/
|
||||
uint32_t RedCrc32Update(
|
||||
uint32_t ulInitCrc32,
|
||||
const void *pBuffer,
|
||||
uint32_t ulLength)
|
||||
{
|
||||
/* CRC32 XOR table, with slicing-by-8 extensions.
|
||||
|
||||
This first column of the table contains the same XOR values as used in
|
||||
the classic byte-at-a-time Sarwate algorithm. The other seven columns
|
||||
are derived from the first, and are used in Intel's slicing-by-eight CRC
|
||||
algorithm.
|
||||
|
||||
The layout of this array in memory is novel and deserves explanation.
|
||||
In other implementations, including Intel's example, each of the below
|
||||
columns is an array. The first column is a 256-entry array, followed by
|
||||
another 256-entry array for the second column, etc. Testing on both ARM
|
||||
and x86 has shown the below mixed arrangement to be about 5-9% faster.
|
||||
One possible explanation: With the array-per-table approach, each of the
|
||||
eight table lookups is guaranteed to be in a separate 1 KB chunk of
|
||||
memory. With the below array, sometimes multiple table lookups will, by
|
||||
coincidence, be close together, making better use of the cache.
|
||||
*/
|
||||
static const uint32_t aulCrc32Table[] =
|
||||
{
|
||||
0x00000000U, 0x00000000U, 0x00000000U, 0x00000000U, 0x00000000U, 0x00000000U, 0x00000000U, 0x00000000U,
|
||||
0x77073096U, 0x191B3141U, 0x01C26A37U, 0xB8BC6765U, 0x3D6029B0U, 0xCB5CD3A5U, 0xA6770BB4U, 0xCCAA009EU,
|
||||
0xEE0E612CU, 0x32366282U, 0x0384D46EU, 0xAA09C88BU, 0x7AC05360U, 0x4DC8A10BU, 0x979F1129U, 0x4225077DU,
|
||||
0x990951BAU, 0x2B2D53C3U, 0x0246BE59U, 0x12B5AFEEU, 0x47A07AD0U, 0x869472AEU, 0x31E81A9DU, 0x8E8F07E3U,
|
||||
0x076DC419U, 0x646CC504U, 0x0709A8DCU, 0x8F629757U, 0xF580A6C0U, 0x9B914216U, 0xF44F2413U, 0x844A0EFAU,
|
||||
0x706AF48FU, 0x7D77F445U, 0x06CBC2EBU, 0x37DEF032U, 0xC8E08F70U, 0x50CD91B3U, 0x52382FA7U, 0x48E00E64U,
|
||||
0xE963A535U, 0x565AA786U, 0x048D7CB2U, 0x256B5FDCU, 0x8F40F5A0U, 0xD659E31DU, 0x63D0353AU, 0xC66F0987U,
|
||||
0x9E6495A3U, 0x4F4196C7U, 0x054F1685U, 0x9DD738B9U, 0xB220DC10U, 0x1D0530B8U, 0xC5A73E8EU, 0x0AC50919U,
|
||||
0x0EDB8832U, 0xC8D98A08U, 0x0E1351B8U, 0xC5B428EFU, 0x30704BC1U, 0xEC53826DU, 0x33EF4E67U, 0xD3E51BB5U,
|
||||
0x79DCB8A4U, 0xD1C2BB49U, 0x0FD13B8FU, 0x7D084F8AU, 0x0D106271U, 0x270F51C8U, 0x959845D3U, 0x1F4F1B2BU,
|
||||
0xE0D5E91EU, 0xFAEFE88AU, 0x0D9785D6U, 0x6FBDE064U, 0x4AB018A1U, 0xA19B2366U, 0xA4705F4EU, 0x91C01CC8U,
|
||||
0x97D2D988U, 0xE3F4D9CBU, 0x0C55EFE1U, 0xD7018701U, 0x77D03111U, 0x6AC7F0C3U, 0x020754FAU, 0x5D6A1C56U,
|
||||
0x09B64C2BU, 0xACB54F0CU, 0x091AF964U, 0x4AD6BFB8U, 0xC5F0ED01U, 0x77C2C07BU, 0xC7A06A74U, 0x57AF154FU,
|
||||
0x7EB17CBDU, 0xB5AE7E4DU, 0x08D89353U, 0xF26AD8DDU, 0xF890C4B1U, 0xBC9E13DEU, 0x61D761C0U, 0x9B0515D1U,
|
||||
0xE7B82D07U, 0x9E832D8EU, 0x0A9E2D0AU, 0xE0DF7733U, 0xBF30BE61U, 0x3A0A6170U, 0x503F7B5DU, 0x158A1232U,
|
||||
0x90BF1D91U, 0x87981CCFU, 0x0B5C473DU, 0x58631056U, 0x825097D1U, 0xF156B2D5U, 0xF64870E9U, 0xD92012ACU,
|
||||
0x1DB71064U, 0x4AC21251U, 0x1C26A370U, 0x5019579FU, 0x60E09782U, 0x03D6029BU, 0x67DE9CCEU, 0x7CBB312BU,
|
||||
0x6AB020F2U, 0x53D92310U, 0x1DE4C947U, 0xE8A530FAU, 0x5D80BE32U, 0xC88AD13EU, 0xC1A9977AU, 0xB01131B5U,
|
||||
0xF3B97148U, 0x78F470D3U, 0x1FA2771EU, 0xFA109F14U, 0x1A20C4E2U, 0x4E1EA390U, 0xF0418DE7U, 0x3E9E3656U,
|
||||
0x84BE41DEU, 0x61EF4192U, 0x1E601D29U, 0x42ACF871U, 0x2740ED52U, 0x85427035U, 0x56368653U, 0xF23436C8U,
|
||||
0x1ADAD47DU, 0x2EAED755U, 0x1B2F0BACU, 0xDF7BC0C8U, 0x95603142U, 0x9847408DU, 0x9391B8DDU, 0xF8F13FD1U,
|
||||
0x6DDDE4EBU, 0x37B5E614U, 0x1AED619BU, 0x67C7A7ADU, 0xA80018F2U, 0x531B9328U, 0x35E6B369U, 0x345B3F4FU,
|
||||
0xF4D4B551U, 0x1C98B5D7U, 0x18ABDFC2U, 0x75720843U, 0xEFA06222U, 0xD58FE186U, 0x040EA9F4U, 0xBAD438ACU,
|
||||
0x83D385C7U, 0x05838496U, 0x1969B5F5U, 0xCDCE6F26U, 0xD2C04B92U, 0x1ED33223U, 0xA279A240U, 0x767E3832U,
|
||||
0x136C9856U, 0x821B9859U, 0x1235F2C8U, 0x95AD7F70U, 0x5090DC43U, 0xEF8580F6U, 0x5431D2A9U, 0xAF5E2A9EU,
|
||||
0x646BA8C0U, 0x9B00A918U, 0x13F798FFU, 0x2D111815U, 0x6DF0F5F3U, 0x24D95353U, 0xF246D91DU, 0x63F42A00U,
|
||||
0xFD62F97AU, 0xB02DFADBU, 0x11B126A6U, 0x3FA4B7FBU, 0x2A508F23U, 0xA24D21FDU, 0xC3AEC380U, 0xED7B2DE3U,
|
||||
0x8A65C9ECU, 0xA936CB9AU, 0x10734C91U, 0x8718D09EU, 0x1730A693U, 0x6911F258U, 0x65D9C834U, 0x21D12D7DU,
|
||||
0x14015C4FU, 0xE6775D5DU, 0x153C5A14U, 0x1ACFE827U, 0xA5107A83U, 0x7414C2E0U, 0xA07EF6BAU, 0x2B142464U,
|
||||
0x63066CD9U, 0xFF6C6C1CU, 0x14FE3023U, 0xA2738F42U, 0x98705333U, 0xBF481145U, 0x0609FD0EU, 0xE7BE24FAU,
|
||||
0xFA0F3D63U, 0xD4413FDFU, 0x16B88E7AU, 0xB0C620ACU, 0xDFD029E3U, 0x39DC63EBU, 0x37E1E793U, 0x69312319U,
|
||||
0x8D080DF5U, 0xCD5A0E9EU, 0x177AE44DU, 0x087A47C9U, 0xE2B00053U, 0xF280B04EU, 0x9196EC27U, 0xA59B2387U,
|
||||
0x3B6E20C8U, 0x958424A2U, 0x384D46E0U, 0xA032AF3EU, 0xC1C12F04U, 0x07AC0536U, 0xCFBD399CU, 0xF9766256U,
|
||||
0x4C69105EU, 0x8C9F15E3U, 0x398F2CD7U, 0x188EC85BU, 0xFCA106B4U, 0xCCF0D693U, 0x69CA3228U, 0x35DC62C8U,
|
||||
0xD56041E4U, 0xA7B24620U, 0x3BC9928EU, 0x0A3B67B5U, 0xBB017C64U, 0x4A64A43DU, 0x582228B5U, 0xBB53652BU,
|
||||
0xA2677172U, 0xBEA97761U, 0x3A0BF8B9U, 0xB28700D0U, 0x866155D4U, 0x81387798U, 0xFE552301U, 0x77F965B5U,
|
||||
0x3C03E4D1U, 0xF1E8E1A6U, 0x3F44EE3CU, 0x2F503869U, 0x344189C4U, 0x9C3D4720U, 0x3BF21D8FU, 0x7D3C6CACU,
|
||||
0x4B04D447U, 0xE8F3D0E7U, 0x3E86840BU, 0x97EC5F0CU, 0x0921A074U, 0x57619485U, 0x9D85163BU, 0xB1966C32U,
|
||||
0xD20D85FDU, 0xC3DE8324U, 0x3CC03A52U, 0x8559F0E2U, 0x4E81DAA4U, 0xD1F5E62BU, 0xAC6D0CA6U, 0x3F196BD1U,
|
||||
0xA50AB56BU, 0xDAC5B265U, 0x3D025065U, 0x3DE59787U, 0x73E1F314U, 0x1AA9358EU, 0x0A1A0712U, 0xF3B36B4FU,
|
||||
0x35B5A8FAU, 0x5D5DAEAAU, 0x365E1758U, 0x658687D1U, 0xF1B164C5U, 0xEBFF875BU, 0xFC5277FBU, 0x2A9379E3U,
|
||||
0x42B2986CU, 0x44469FEBU, 0x379C7D6FU, 0xDD3AE0B4U, 0xCCD14D75U, 0x20A354FEU, 0x5A257C4FU, 0xE639797DU,
|
||||
0xDBBBC9D6U, 0x6F6BCC28U, 0x35DAC336U, 0xCF8F4F5AU, 0x8B7137A5U, 0xA6372650U, 0x6BCD66D2U, 0x68B67E9EU,
|
||||
0xACBCF940U, 0x7670FD69U, 0x3418A901U, 0x7733283FU, 0xB6111E15U, 0x6D6BF5F5U, 0xCDBA6D66U, 0xA41C7E00U,
|
||||
0x32D86CE3U, 0x39316BAEU, 0x3157BF84U, 0xEAE41086U, 0x0431C205U, 0x706EC54DU, 0x081D53E8U, 0xAED97719U,
|
||||
0x45DF5C75U, 0x202A5AEFU, 0x3095D5B3U, 0x525877E3U, 0x3951EBB5U, 0xBB3216E8U, 0xAE6A585CU, 0x62737787U,
|
||||
0xDCD60DCFU, 0x0B07092CU, 0x32D36BEAU, 0x40EDD80DU, 0x7EF19165U, 0x3DA66446U, 0x9F8242C1U, 0xECFC7064U,
|
||||
0xABD13D59U, 0x121C386DU, 0x331101DDU, 0xF851BF68U, 0x4391B8D5U, 0xF6FAB7E3U, 0x39F54975U, 0x205670FAU,
|
||||
0x26D930ACU, 0xDF4636F3U, 0x246BE590U, 0xF02BF8A1U, 0xA121B886U, 0x047A07ADU, 0xA863A552U, 0x85CD537DU,
|
||||
0x51DE003AU, 0xC65D07B2U, 0x25A98FA7U, 0x48979FC4U, 0x9C419136U, 0xCF26D408U, 0x0E14AEE6U, 0x496753E3U,
|
||||
0xC8D75180U, 0xED705471U, 0x27EF31FEU, 0x5A22302AU, 0xDBE1EBE6U, 0x49B2A6A6U, 0x3FFCB47BU, 0xC7E85400U,
|
||||
0xBFD06116U, 0xF46B6530U, 0x262D5BC9U, 0xE29E574FU, 0xE681C256U, 0x82EE7503U, 0x998BBFCFU, 0x0B42549EU,
|
||||
0x21B4F4B5U, 0xBB2AF3F7U, 0x23624D4CU, 0x7F496FF6U, 0x54A11E46U, 0x9FEB45BBU, 0x5C2C8141U, 0x01875D87U,
|
||||
0x56B3C423U, 0xA231C2B6U, 0x22A0277BU, 0xC7F50893U, 0x69C137F6U, 0x54B7961EU, 0xFA5B8AF5U, 0xCD2D5D19U,
|
||||
0xCFBA9599U, 0x891C9175U, 0x20E69922U, 0xD540A77DU, 0x2E614D26U, 0xD223E4B0U, 0xCBB39068U, 0x43A25AFAU,
|
||||
0xB8BDA50FU, 0x9007A034U, 0x2124F315U, 0x6DFCC018U, 0x13016496U, 0x197F3715U, 0x6DC49BDCU, 0x8F085A64U,
|
||||
0x2802B89EU, 0x179FBCFBU, 0x2A78B428U, 0x359FD04EU, 0x9151F347U, 0xE82985C0U, 0x9B8CEB35U, 0x562848C8U,
|
||||
0x5F058808U, 0x0E848DBAU, 0x2BBADE1FU, 0x8D23B72BU, 0xAC31DAF7U, 0x23755665U, 0x3DFBE081U, 0x9A824856U,
|
||||
0xC60CD9B2U, 0x25A9DE79U, 0x29FC6046U, 0x9F9618C5U, 0xEB91A027U, 0xA5E124CBU, 0x0C13FA1CU, 0x140D4FB5U,
|
||||
0xB10BE924U, 0x3CB2EF38U, 0x283E0A71U, 0x272A7FA0U, 0xD6F18997U, 0x6EBDF76EU, 0xAA64F1A8U, 0xD8A74F2BU,
|
||||
0x2F6F7C87U, 0x73F379FFU, 0x2D711CF4U, 0xBAFD4719U, 0x64D15587U, 0x73B8C7D6U, 0x6FC3CF26U, 0xD2624632U,
|
||||
0x58684C11U, 0x6AE848BEU, 0x2CB376C3U, 0x0241207CU, 0x59B17C37U, 0xB8E41473U, 0xC9B4C492U, 0x1EC846ACU,
|
||||
0xC1611DABU, 0x41C51B7DU, 0x2EF5C89AU, 0x10F48F92U, 0x1E1106E7U, 0x3E7066DDU, 0xF85CDE0FU, 0x9047414FU,
|
||||
0xB6662D3DU, 0x58DE2A3CU, 0x2F37A2ADU, 0xA848E8F7U, 0x23712F57U, 0xF52CB578U, 0x5E2BD5BBU, 0x5CED41D1U,
|
||||
0x76DC4190U, 0xF0794F05U, 0x709A8DC0U, 0x9B14583DU, 0x58F35849U, 0x0F580A6CU, 0x440B7579U, 0x299DC2EDU,
|
||||
0x01DB7106U, 0xE9627E44U, 0x7158E7F7U, 0x23A83F58U, 0x659371F9U, 0xC404D9C9U, 0xE27C7ECDU, 0xE537C273U,
|
||||
0x98D220BCU, 0xC24F2D87U, 0x731E59AEU, 0x311D90B6U, 0x22330B29U, 0x4290AB67U, 0xD3946450U, 0x6BB8C590U,
|
||||
0xEFD5102AU, 0xDB541CC6U, 0x72DC3399U, 0x89A1F7D3U, 0x1F532299U, 0x89CC78C2U, 0x75E36FE4U, 0xA712C50EU,
|
||||
0x71B18589U, 0x94158A01U, 0x7793251CU, 0x1476CF6AU, 0xAD73FE89U, 0x94C9487AU, 0xB044516AU, 0xADD7CC17U,
|
||||
0x06B6B51FU, 0x8D0EBB40U, 0x76514F2BU, 0xACCAA80FU, 0x9013D739U, 0x5F959BDFU, 0x16335ADEU, 0x617DCC89U,
|
||||
0x9FBFE4A5U, 0xA623E883U, 0x7417F172U, 0xBE7F07E1U, 0xD7B3ADE9U, 0xD901E971U, 0x27DB4043U, 0xEFF2CB6AU,
|
||||
0xE8B8D433U, 0xBF38D9C2U, 0x75D59B45U, 0x06C36084U, 0xEAD38459U, 0x125D3AD4U, 0x81AC4BF7U, 0x2358CBF4U,
|
||||
0x7807C9A2U, 0x38A0C50DU, 0x7E89DC78U, 0x5EA070D2U, 0x68831388U, 0xE30B8801U, 0x77E43B1EU, 0xFA78D958U,
|
||||
0x0F00F934U, 0x21BBF44CU, 0x7F4BB64FU, 0xE61C17B7U, 0x55E33A38U, 0x28575BA4U, 0xD19330AAU, 0x36D2D9C6U,
|
||||
0x9609A88EU, 0x0A96A78FU, 0x7D0D0816U, 0xF4A9B859U, 0x124340E8U, 0xAEC3290AU, 0xE07B2A37U, 0xB85DDE25U,
|
||||
0xE10E9818U, 0x138D96CEU, 0x7CCF6221U, 0x4C15DF3CU, 0x2F236958U, 0x659FFAAFU, 0x460C2183U, 0x74F7DEBBU,
|
||||
0x7F6A0DBBU, 0x5CCC0009U, 0x798074A4U, 0xD1C2E785U, 0x9D03B548U, 0x789ACA17U, 0x83AB1F0DU, 0x7E32D7A2U,
|
||||
0x086D3D2DU, 0x45D73148U, 0x78421E93U, 0x697E80E0U, 0xA0639CF8U, 0xB3C619B2U, 0x25DC14B9U, 0xB298D73CU,
|
||||
0x91646C97U, 0x6EFA628BU, 0x7A04A0CAU, 0x7BCB2F0EU, 0xE7C3E628U, 0x35526B1CU, 0x14340E24U, 0x3C17D0DFU,
|
||||
0xE6635C01U, 0x77E153CAU, 0x7BC6CAFDU, 0xC377486BU, 0xDAA3CF98U, 0xFE0EB8B9U, 0xB2430590U, 0xF0BDD041U,
|
||||
0x6B6B51F4U, 0xBABB5D54U, 0x6CBC2EB0U, 0xCB0D0FA2U, 0x3813CFCBU, 0x0C8E08F7U, 0x23D5E9B7U, 0x5526F3C6U,
|
||||
0x1C6C6162U, 0xA3A06C15U, 0x6D7E4487U, 0x73B168C7U, 0x0573E67BU, 0xC7D2DB52U, 0x85A2E203U, 0x998CF358U,
|
||||
0x856530D8U, 0x888D3FD6U, 0x6F38FADEU, 0x6104C729U, 0x42D39CABU, 0x4146A9FCU, 0xB44AF89EU, 0x1703F4BBU,
|
||||
0xF262004EU, 0x91960E97U, 0x6EFA90E9U, 0xD9B8A04CU, 0x7FB3B51BU, 0x8A1A7A59U, 0x123DF32AU, 0xDBA9F425U,
|
||||
0x6C0695EDU, 0xDED79850U, 0x6BB5866CU, 0x446F98F5U, 0xCD93690BU, 0x971F4AE1U, 0xD79ACDA4U, 0xD16CFD3CU,
|
||||
0x1B01A57BU, 0xC7CCA911U, 0x6A77EC5BU, 0xFCD3FF90U, 0xF0F340BBU, 0x5C439944U, 0x71EDC610U, 0x1DC6FDA2U,
|
||||
0x8208F4C1U, 0xECE1FAD2U, 0x68315202U, 0xEE66507EU, 0xB7533A6BU, 0xDAD7EBEAU, 0x4005DC8DU, 0x9349FA41U,
|
||||
0xF50FC457U, 0xF5FACB93U, 0x69F33835U, 0x56DA371BU, 0x8A3313DBU, 0x118B384FU, 0xE672D739U, 0x5FE3FADFU,
|
||||
0x65B0D9C6U, 0x7262D75CU, 0x62AF7F08U, 0x0EB9274DU, 0x0863840AU, 0xE0DD8A9AU, 0x103AA7D0U, 0x86C3E873U,
|
||||
0x12B7E950U, 0x6B79E61DU, 0x636D153FU, 0xB6054028U, 0x3503ADBAU, 0x2B81593FU, 0xB64DAC64U, 0x4A69E8EDU,
|
||||
0x8BBEB8EAU, 0x4054B5DEU, 0x612BAB66U, 0xA4B0EFC6U, 0x72A3D76AU, 0xAD152B91U, 0x87A5B6F9U, 0xC4E6EF0EU,
|
||||
0xFCB9887CU, 0x594F849FU, 0x60E9C151U, 0x1C0C88A3U, 0x4FC3FEDAU, 0x6649F834U, 0x21D2BD4DU, 0x084CEF90U,
|
||||
0x62DD1DDFU, 0x160E1258U, 0x65A6D7D4U, 0x81DBB01AU, 0xFDE322CAU, 0x7B4CC88CU, 0xE47583C3U, 0x0289E689U,
|
||||
0x15DA2D49U, 0x0F152319U, 0x6464BDE3U, 0x3967D77FU, 0xC0830B7AU, 0xB0101B29U, 0x42028877U, 0xCE23E617U,
|
||||
0x8CD37CF3U, 0x243870DAU, 0x662203BAU, 0x2BD27891U, 0x872371AAU, 0x36846987U, 0x73EA92EAU, 0x40ACE1F4U,
|
||||
0xFBD44C65U, 0x3D23419BU, 0x67E0698DU, 0x936E1FF4U, 0xBA43581AU, 0xFDD8BA22U, 0xD59D995EU, 0x8C06E16AU,
|
||||
0x4DB26158U, 0x65FD6BA7U, 0x48D7CB20U, 0x3B26F703U, 0x9932774DU, 0x08F40F5AU, 0x8BB64CE5U, 0xD0EBA0BBU,
|
||||
0x3AB551CEU, 0x7CE65AE6U, 0x4915A117U, 0x839A9066U, 0xA4525EFDU, 0xC3A8DCFFU, 0x2DC14751U, 0x1C41A025U,
|
||||
0xA3BC0074U, 0x57CB0925U, 0x4B531F4EU, 0x912F3F88U, 0xE3F2242DU, 0x453CAE51U, 0x1C295DCCU, 0x92CEA7C6U,
|
||||
0xD4BB30E2U, 0x4ED03864U, 0x4A917579U, 0x299358EDU, 0xDE920D9DU, 0x8E607DF4U, 0xBA5E5678U, 0x5E64A758U,
|
||||
0x4ADFA541U, 0x0191AEA3U, 0x4FDE63FCU, 0xB4446054U, 0x6CB2D18DU, 0x93654D4CU, 0x7FF968F6U, 0x54A1AE41U,
|
||||
0x3DD895D7U, 0x188A9FE2U, 0x4E1C09CBU, 0x0CF80731U, 0x51D2F83DU, 0x58399EE9U, 0xD98E6342U, 0x980BAEDFU,
|
||||
0xA4D1C46DU, 0x33A7CC21U, 0x4C5AB792U, 0x1E4DA8DFU, 0x167282EDU, 0xDEADEC47U, 0xE86679DFU, 0x1684A93CU,
|
||||
0xD3D6F4FBU, 0x2ABCFD60U, 0x4D98DDA5U, 0xA6F1CFBAU, 0x2B12AB5DU, 0x15F13FE2U, 0x4E11726BU, 0xDA2EA9A2U,
|
||||
0x4369E96AU, 0xAD24E1AFU, 0x46C49A98U, 0xFE92DFECU, 0xA9423C8CU, 0xE4A78D37U, 0xB8590282U, 0x030EBB0EU,
|
||||
0x346ED9FCU, 0xB43FD0EEU, 0x4706F0AFU, 0x462EB889U, 0x9422153CU, 0x2FFB5E92U, 0x1E2E0936U, 0xCFA4BB90U,
|
||||
0xAD678846U, 0x9F12832DU, 0x45404EF6U, 0x549B1767U, 0xD3826FECU, 0xA96F2C3CU, 0x2FC613ABU, 0x412BBC73U,
|
||||
0xDA60B8D0U, 0x8609B26CU, 0x448224C1U, 0xEC277002U, 0xEEE2465CU, 0x6233FF99U, 0x89B1181FU, 0x8D81BCEDU,
|
||||
0x44042D73U, 0xC94824ABU, 0x41CD3244U, 0x71F048BBU, 0x5CC29A4CU, 0x7F36CF21U, 0x4C162691U, 0x8744B5F4U,
|
||||
0x33031DE5U, 0xD05315EAU, 0x400F5873U, 0xC94C2FDEU, 0x61A2B3FCU, 0xB46A1C84U, 0xEA612D25U, 0x4BEEB56AU,
|
||||
0xAA0A4C5FU, 0xFB7E4629U, 0x4249E62AU, 0xDBF98030U, 0x2602C92CU, 0x32FE6E2AU, 0xDB8937B8U, 0xC561B289U,
|
||||
0xDD0D7CC9U, 0xE2657768U, 0x438B8C1DU, 0x6345E755U, 0x1B62E09CU, 0xF9A2BD8FU, 0x7DFE3C0CU, 0x09CBB217U,
|
||||
0x5005713CU, 0x2F3F79F6U, 0x54F16850U, 0x6B3FA09CU, 0xF9D2E0CFU, 0x0B220DC1U, 0xEC68D02BU, 0xAC509190U,
|
||||
0x270241AAU, 0x362448B7U, 0x55330267U, 0xD383C7F9U, 0xC4B2C97FU, 0xC07EDE64U, 0x4A1FDB9FU, 0x60FA910EU,
|
||||
0xBE0B1010U, 0x1D091B74U, 0x5775BC3EU, 0xC1366817U, 0x8312B3AFU, 0x46EAACCAU, 0x7BF7C102U, 0xEE7596EDU,
|
||||
0xC90C2086U, 0x04122A35U, 0x56B7D609U, 0x798A0F72U, 0xBE729A1FU, 0x8DB67F6FU, 0xDD80CAB6U, 0x22DF9673U,
|
||||
0x5768B525U, 0x4B53BCF2U, 0x53F8C08CU, 0xE45D37CBU, 0x0C52460FU, 0x90B34FD7U, 0x1827F438U, 0x281A9F6AU,
|
||||
0x206F85B3U, 0x52488DB3U, 0x523AAABBU, 0x5CE150AEU, 0x31326FBFU, 0x5BEF9C72U, 0xBE50FF8CU, 0xE4B09FF4U,
|
||||
0xB966D409U, 0x7965DE70U, 0x507C14E2U, 0x4E54FF40U, 0x7692156FU, 0xDD7BEEDCU, 0x8FB8E511U, 0x6A3F9817U,
|
||||
0xCE61E49FU, 0x607EEF31U, 0x51BE7ED5U, 0xF6E89825U, 0x4BF23CDFU, 0x16273D79U, 0x29CFEEA5U, 0xA6959889U,
|
||||
0x5EDEF90EU, 0xE7E6F3FEU, 0x5AE239E8U, 0xAE8B8873U, 0xC9A2AB0EU, 0xE7718FACU, 0xDF879E4CU, 0x7FB58A25U,
|
||||
0x29D9C998U, 0xFEFDC2BFU, 0x5B2053DFU, 0x1637EF16U, 0xF4C282BEU, 0x2C2D5C09U, 0x79F095F8U, 0xB31F8ABBU,
|
||||
0xB0D09822U, 0xD5D0917CU, 0x5966ED86U, 0x048240F8U, 0xB362F86EU, 0xAAB92EA7U, 0x48188F65U, 0x3D908D58U,
|
||||
0xC7D7A8B4U, 0xCCCBA03DU, 0x58A487B1U, 0xBC3E279DU, 0x8E02D1DEU, 0x61E5FD02U, 0xEE6F84D1U, 0xF13A8DC6U,
|
||||
0x59B33D17U, 0x838A36FAU, 0x5DEB9134U, 0x21E91F24U, 0x3C220DCEU, 0x7CE0CDBAU, 0x2BC8BA5FU, 0xFBFF84DFU,
|
||||
0x2EB40D81U, 0x9A9107BBU, 0x5C29FB03U, 0x99557841U, 0x0142247EU, 0xB7BC1E1FU, 0x8DBFB1EBU, 0x37558441U,
|
||||
0xB7BD5C3BU, 0xB1BC5478U, 0x5E6F455AU, 0x8BE0D7AFU, 0x46E25EAEU, 0x31286CB1U, 0xBC57AB76U, 0xB9DA83A2U,
|
||||
0xC0BA6CADU, 0xA8A76539U, 0x5FAD2F6DU, 0x335CB0CAU, 0x7B82771EU, 0xFA74BF14U, 0x1A20A0C2U, 0x7570833CU,
|
||||
0xEDB88320U, 0x3B83984BU, 0xE1351B80U, 0xED59B63BU, 0xB1E6B092U, 0x1EB014D8U, 0x8816EAF2U, 0x533B85DAU,
|
||||
0x9ABFB3B6U, 0x2298A90AU, 0xE0F771B7U, 0x55E5D15EU, 0x8C869922U, 0xD5ECC77DU, 0x2E61E146U, 0x9F918544U,
|
||||
0x03B6E20CU, 0x09B5FAC9U, 0xE2B1CFEEU, 0x47507EB0U, 0xCB26E3F2U, 0x5378B5D3U, 0x1F89FBDBU, 0x111E82A7U,
|
||||
0x74B1D29AU, 0x10AECB88U, 0xE373A5D9U, 0xFFEC19D5U, 0xF646CA42U, 0x98246676U, 0xB9FEF06FU, 0xDDB48239U,
|
||||
0xEAD54739U, 0x5FEF5D4FU, 0xE63CB35CU, 0x623B216CU, 0x44661652U, 0x852156CEU, 0x7C59CEE1U, 0xD7718B20U,
|
||||
0x9DD277AFU, 0x46F46C0EU, 0xE7FED96BU, 0xDA874609U, 0x79063FE2U, 0x4E7D856BU, 0xDA2EC555U, 0x1BDB8BBEU,
|
||||
0x04DB2615U, 0x6DD93FCDU, 0xE5B86732U, 0xC832E9E7U, 0x3EA64532U, 0xC8E9F7C5U, 0xEBC6DFC8U, 0x95548C5DU,
|
||||
0x73DC1683U, 0x74C20E8CU, 0xE47A0D05U, 0x708E8E82U, 0x03C66C82U, 0x03B52460U, 0x4DB1D47CU, 0x59FE8CC3U,
|
||||
0xE3630B12U, 0xF35A1243U, 0xEF264A38U, 0x28ED9ED4U, 0x8196FB53U, 0xF2E396B5U, 0xBBF9A495U, 0x80DE9E6FU,
|
||||
0x94643B84U, 0xEA412302U, 0xEEE4200FU, 0x9051F9B1U, 0xBCF6D2E3U, 0x39BF4510U, 0x1D8EAF21U, 0x4C749EF1U,
|
||||
0x0D6D6A3EU, 0xC16C70C1U, 0xECA29E56U, 0x82E4565FU, 0xFB56A833U, 0xBF2B37BEU, 0x2C66B5BCU, 0xC2FB9912U,
|
||||
0x7A6A5AA8U, 0xD8774180U, 0xED60F461U, 0x3A58313AU, 0xC6368183U, 0x7477E41BU, 0x8A11BE08U, 0x0E51998CU,
|
||||
0xE40ECF0BU, 0x9736D747U, 0xE82FE2E4U, 0xA78F0983U, 0x74165D93U, 0x6972D4A3U, 0x4FB68086U, 0x04949095U,
|
||||
0x9309FF9DU, 0x8E2DE606U, 0xE9ED88D3U, 0x1F336EE6U, 0x49767423U, 0xA22E0706U, 0xE9C18B32U, 0xC83E900BU,
|
||||
0x0A00AE27U, 0xA500B5C5U, 0xEBAB368AU, 0x0D86C108U, 0x0ED60EF3U, 0x24BA75A8U, 0xD82991AFU, 0x46B197E8U,
|
||||
0x7D079EB1U, 0xBC1B8484U, 0xEA695CBDU, 0xB53AA66DU, 0x33B62743U, 0xEFE6A60DU, 0x7E5E9A1BU, 0x8A1B9776U,
|
||||
0xF00F9344U, 0x71418A1AU, 0xFD13B8F0U, 0xBD40E1A4U, 0xD1062710U, 0x1D661643U, 0xEFC8763CU, 0x2F80B4F1U,
|
||||
0x8708A3D2U, 0x685ABB5BU, 0xFCD1D2C7U, 0x05FC86C1U, 0xEC660EA0U, 0xD63AC5E6U, 0x49BF7D88U, 0xE32AB46FU,
|
||||
0x1E01F268U, 0x4377E898U, 0xFE976C9EU, 0x1749292FU, 0xABC67470U, 0x50AEB748U, 0x78576715U, 0x6DA5B38CU,
|
||||
0x6906C2FEU, 0x5A6CD9D9U, 0xFF5506A9U, 0xAFF54E4AU, 0x96A65DC0U, 0x9BF264EDU, 0xDE206CA1U, 0xA10FB312U,
|
||||
0xF762575DU, 0x152D4F1EU, 0xFA1A102CU, 0x322276F3U, 0x248681D0U, 0x86F75455U, 0x1B87522FU, 0xABCABA0BU,
|
||||
0x806567CBU, 0x0C367E5FU, 0xFBD87A1BU, 0x8A9E1196U, 0x19E6A860U, 0x4DAB87F0U, 0xBDF0599BU, 0x6760BA95U,
|
||||
0x196C3671U, 0x271B2D9CU, 0xF99EC442U, 0x982BBE78U, 0x5E46D2B0U, 0xCB3FF55EU, 0x8C184306U, 0xE9EFBD76U,
|
||||
0x6E6B06E7U, 0x3E001CDDU, 0xF85CAE75U, 0x2097D91DU, 0x6326FB00U, 0x006326FBU, 0x2A6F48B2U, 0x2545BDE8U,
|
||||
0xFED41B76U, 0xB9980012U, 0xF300E948U, 0x78F4C94BU, 0xE1766CD1U, 0xF135942EU, 0xDC27385BU, 0xFC65AF44U,
|
||||
0x89D32BE0U, 0xA0833153U, 0xF2C2837FU, 0xC048AE2EU, 0xDC164561U, 0x3A69478BU, 0x7A5033EFU, 0x30CFAFDAU,
|
||||
0x10DA7A5AU, 0x8BAE6290U, 0xF0843D26U, 0xD2FD01C0U, 0x9BB63FB1U, 0xBCFD3525U, 0x4BB82972U, 0xBE40A839U,
|
||||
0x67DD4ACCU, 0x92B553D1U, 0xF1465711U, 0x6A4166A5U, 0xA6D61601U, 0x77A1E680U, 0xEDCF22C6U, 0x72EAA8A7U,
|
||||
0xF9B9DF6FU, 0xDDF4C516U, 0xF4094194U, 0xF7965E1CU, 0x14F6CA11U, 0x6AA4D638U, 0x28681C48U, 0x782FA1BEU,
|
||||
0x8EBEEFF9U, 0xC4EFF457U, 0xF5CB2BA3U, 0x4F2A3979U, 0x2996E3A1U, 0xA1F8059DU, 0x8E1F17FCU, 0xB485A120U,
|
||||
0x17B7BE43U, 0xEFC2A794U, 0xF78D95FAU, 0x5D9F9697U, 0x6E369971U, 0x276C7733U, 0xBFF70D61U, 0x3A0AA6C3U,
|
||||
0x60B08ED5U, 0xF6D996D5U, 0xF64FFFCDU, 0xE523F1F2U, 0x5356B0C1U, 0xEC30A496U, 0x198006D5U, 0xF6A0A65DU,
|
||||
0xD6D6A3E8U, 0xAE07BCE9U, 0xD9785D60U, 0x4D6B1905U, 0x70279F96U, 0x191C11EEU, 0x47ABD36EU, 0xAA4DE78CU,
|
||||
0xA1D1937EU, 0xB71C8DA8U, 0xD8BA3757U, 0xF5D77E60U, 0x4D47B626U, 0xD240C24BU, 0xE1DCD8DAU, 0x66E7E712U,
|
||||
0x38D8C2C4U, 0x9C31DE6BU, 0xDAFC890EU, 0xE762D18EU, 0x0AE7CCF6U, 0x54D4B0E5U, 0xD034C247U, 0xE868E0F1U,
|
||||
0x4FDFF252U, 0x852AEF2AU, 0xDB3EE339U, 0x5FDEB6EBU, 0x3787E546U, 0x9F886340U, 0x7643C9F3U, 0x24C2E06FU,
|
||||
0xD1BB67F1U, 0xCA6B79EDU, 0xDE71F5BCU, 0xC2098E52U, 0x85A73956U, 0x828D53F8U, 0xB3E4F77DU, 0x2E07E976U,
|
||||
0xA6BC5767U, 0xD37048ACU, 0xDFB39F8BU, 0x7AB5E937U, 0xB8C710E6U, 0x49D1805DU, 0x1593FCC9U, 0xE2ADE9E8U,
|
||||
0x3FB506DDU, 0xF85D1B6FU, 0xDDF521D2U, 0x680046D9U, 0xFF676A36U, 0xCF45F2F3U, 0x247BE654U, 0x6C22EE0BU,
|
||||
0x48B2364BU, 0xE1462A2EU, 0xDC374BE5U, 0xD0BC21BCU, 0xC2074386U, 0x04192156U, 0x820CEDE0U, 0xA088EE95U,
|
||||
0xD80D2BDAU, 0x66DE36E1U, 0xD76B0CD8U, 0x88DF31EAU, 0x4057D457U, 0xF54F9383U, 0x74449D09U, 0x79A8FC39U,
|
||||
0xAF0A1B4CU, 0x7FC507A0U, 0xD6A966EFU, 0x3063568FU, 0x7D37FDE7U, 0x3E134026U, 0xD23396BDU, 0xB502FCA7U,
|
||||
0x36034AF6U, 0x54E85463U, 0xD4EFD8B6U, 0x22D6F961U, 0x3A978737U, 0xB8873288U, 0xE3DB8C20U, 0x3B8DFB44U,
|
||||
0x41047A60U, 0x4DF36522U, 0xD52DB281U, 0x9A6A9E04U, 0x07F7AE87U, 0x73DBE12DU, 0x45AC8794U, 0xF727FBDAU,
|
||||
0xDF60EFC3U, 0x02B2F3E5U, 0xD062A404U, 0x07BDA6BDU, 0xB5D77297U, 0x6EDED195U, 0x800BB91AU, 0xFDE2F2C3U,
|
||||
0xA867DF55U, 0x1BA9C2A4U, 0xD1A0CE33U, 0xBF01C1D8U, 0x88B75B27U, 0xA5820230U, 0x267CB2AEU, 0x3148F25DU,
|
||||
0x316E8EEFU, 0x30849167U, 0xD3E6706AU, 0xADB46E36U, 0xCF1721F7U, 0x2316709EU, 0x1794A833U, 0xBFC7F5BEU,
|
||||
0x4669BE79U, 0x299FA026U, 0xD2241A5DU, 0x15080953U, 0xF2770847U, 0xE84AA33BU, 0xB1E3A387U, 0x736DF520U,
|
||||
0xCB61B38CU, 0xE4C5AEB8U, 0xC55EFE10U, 0x1D724E9AU, 0x10C70814U, 0x1ACA1375U, 0x20754FA0U, 0xD6F6D6A7U,
|
||||
0xBC66831AU, 0xFDDE9FF9U, 0xC49C9427U, 0xA5CE29FFU, 0x2DA721A4U, 0xD196C0D0U, 0x86024414U, 0x1A5CD639U,
|
||||
0x256FD2A0U, 0xD6F3CC3AU, 0xC6DA2A7EU, 0xB77B8611U, 0x6A075B74U, 0x5702B27EU, 0xB7EA5E89U, 0x94D3D1DAU,
|
||||
0x5268E236U, 0xCFE8FD7BU, 0xC7184049U, 0x0FC7E174U, 0x576772C4U, 0x9C5E61DBU, 0x119D553DU, 0x5879D144U,
|
||||
0xCC0C7795U, 0x80A96BBCU, 0xC25756CCU, 0x9210D9CDU, 0xE547AED4U, 0x815B5163U, 0xD43A6BB3U, 0x52BCD85DU,
|
||||
0xBB0B4703U, 0x99B25AFDU, 0xC3953CFBU, 0x2AACBEA8U, 0xD8278764U, 0x4A0782C6U, 0x724D6007U, 0x9E16D8C3U,
|
||||
0x220216B9U, 0xB29F093EU, 0xC1D382A2U, 0x38191146U, 0x9F87FDB4U, 0xCC93F068U, 0x43A57A9AU, 0x1099DF20U,
|
||||
0x5505262FU, 0xAB84387FU, 0xC011E895U, 0x80A57623U, 0xA2E7D404U, 0x07CF23CDU, 0xE5D2712EU, 0xDC33DFBEU,
|
||||
0xC5BA3BBEU, 0x2C1C24B0U, 0xCB4DAFA8U, 0xD8C66675U, 0x20B743D5U, 0xF6999118U, 0x139A01C7U, 0x0513CD12U,
|
||||
0xB2BD0B28U, 0x350715F1U, 0xCA8FC59FU, 0x607A0110U, 0x1DD76A65U, 0x3DC542BDU, 0xB5ED0A73U, 0xC9B9CD8CU,
|
||||
0x2BB45A92U, 0x1E2A4632U, 0xC8C97BC6U, 0x72CFAEFEU, 0x5A7710B5U, 0xBB513013U, 0x840510EEU, 0x4736CA6FU,
|
||||
0x5CB36A04U, 0x07317773U, 0xC90B11F1U, 0xCA73C99BU, 0x67173905U, 0x700DE3B6U, 0x22721B5AU, 0x8B9CCAF1U,
|
||||
0xC2D7FFA7U, 0x4870E1B4U, 0xCC440774U, 0x57A4F122U, 0xD537E515U, 0x6D08D30EU, 0xE7D525D4U, 0x8159C3E8U,
|
||||
0xB5D0CF31U, 0x516BD0F5U, 0xCD866D43U, 0xEF189647U, 0xE857CCA5U, 0xA65400ABU, 0x41A22E60U, 0x4DF3C376U,
|
||||
0x2CD99E8BU, 0x7A468336U, 0xCFC0D31AU, 0xFDAD39A9U, 0xAFF7B675U, 0x20C07205U, 0x704A34FDU, 0xC37CC495U,
|
||||
0x5BDEAE1DU, 0x635DB277U, 0xCE02B92DU, 0x45115ECCU, 0x92979FC5U, 0xEB9CA1A0U, 0xD63D3F49U, 0x0FD6C40BU,
|
||||
0x9B64C2B0U, 0xCBFAD74EU, 0x91AF9640U, 0x764DEE06U, 0xE915E8DBU, 0x11E81EB4U, 0xCC1D9F8BU, 0x7AA64737U,
|
||||
0xEC63F226U, 0xD2E1E60FU, 0x906DFC77U, 0xCEF18963U, 0xD475C16BU, 0xDAB4CD11U, 0x6A6A943FU, 0xB60C47A9U,
|
||||
0x756AA39CU, 0xF9CCB5CCU, 0x922B422EU, 0xDC44268DU, 0x93D5BBBBU, 0x5C20BFBFU, 0x5B828EA2U, 0x3883404AU,
|
||||
0x026D930AU, 0xE0D7848DU, 0x93E92819U, 0x64F841E8U, 0xAEB5920BU, 0x977C6C1AU, 0xFDF58516U, 0xF42940D4U,
|
||||
0x9C0906A9U, 0xAF96124AU, 0x96A63E9CU, 0xF92F7951U, 0x1C954E1BU, 0x8A795CA2U, 0x3852BB98U, 0xFEEC49CDU,
|
||||
0xEB0E363FU, 0xB68D230BU, 0x976454ABU, 0x41931E34U, 0x21F567ABU, 0x41258F07U, 0x9E25B02CU, 0x32464953U,
|
||||
0x72076785U, 0x9DA070C8U, 0x9522EAF2U, 0x5326B1DAU, 0x66551D7BU, 0xC7B1FDA9U, 0xAFCDAAB1U, 0xBCC94EB0U,
|
||||
0x05005713U, 0x84BB4189U, 0x94E080C5U, 0xEB9AD6BFU, 0x5B3534CBU, 0x0CED2E0CU, 0x09BAA105U, 0x70634E2EU,
|
||||
0x95BF4A82U, 0x03235D46U, 0x9FBCC7F8U, 0xB3F9C6E9U, 0xD965A31AU, 0xFDBB9CD9U, 0xFFF2D1ECU, 0xA9435C82U,
|
||||
0xE2B87A14U, 0x1A386C07U, 0x9E7EADCFU, 0x0B45A18CU, 0xE4058AAAU, 0x36E74F7CU, 0x5985DA58U, 0x65E95C1CU,
|
||||
0x7BB12BAEU, 0x31153FC4U, 0x9C381396U, 0x19F00E62U, 0xA3A5F07AU, 0xB0733DD2U, 0x686DC0C5U, 0xEB665BFFU,
|
||||
0x0CB61B38U, 0x280E0E85U, 0x9DFA79A1U, 0xA14C6907U, 0x9EC5D9CAU, 0x7B2FEE77U, 0xCE1ACB71U, 0x27CC5B61U,
|
||||
0x92D28E9BU, 0x674F9842U, 0x98B56F24U, 0x3C9B51BEU, 0x2CE505DAU, 0x662ADECFU, 0x0BBDF5FFU, 0x2D095278U,
|
||||
0xE5D5BE0DU, 0x7E54A903U, 0x99770513U, 0x842736DBU, 0x11852C6AU, 0xAD760D6AU, 0xADCAFE4BU, 0xE1A352E6U,
|
||||
0x7CDCEFB7U, 0x5579FAC0U, 0x9B31BB4AU, 0x96929935U, 0x562556BAU, 0x2BE27FC4U, 0x9C22E4D6U, 0x6F2C5505U,
|
||||
0x0BDBDF21U, 0x4C62CB81U, 0x9AF3D17DU, 0x2E2EFE50U, 0x6B457F0AU, 0xE0BEAC61U, 0x3A55EF62U, 0xA386559BU,
|
||||
0x86D3D2D4U, 0x8138C51FU, 0x8D893530U, 0x2654B999U, 0x89F57F59U, 0x123E1C2FU, 0xABC30345U, 0x061D761CU,
|
||||
0xF1D4E242U, 0x9823F45EU, 0x8C4B5F07U, 0x9EE8DEFCU, 0xB49556E9U, 0xD962CF8AU, 0x0DB408F1U, 0xCAB77682U,
|
||||
0x68DDB3F8U, 0xB30EA79DU, 0x8E0DE15EU, 0x8C5D7112U, 0xF3352C39U, 0x5FF6BD24U, 0x3C5C126CU, 0x44387161U,
|
||||
0x1FDA836EU, 0xAA1596DCU, 0x8FCF8B69U, 0x34E11677U, 0xCE550589U, 0x94AA6E81U, 0x9A2B19D8U, 0x889271FFU,
|
||||
0x81BE16CDU, 0xE554001BU, 0x8A809DECU, 0xA9362ECEU, 0x7C75D999U, 0x89AF5E39U, 0x5F8C2756U, 0x825778E6U,
|
||||
0xF6B9265BU, 0xFC4F315AU, 0x8B42F7DBU, 0x118A49ABU, 0x4115F029U, 0x42F38D9CU, 0xF9FB2CE2U, 0x4EFD7878U,
|
||||
0x6FB077E1U, 0xD7626299U, 0x89044982U, 0x033FE645U, 0x06B58AF9U, 0xC467FF32U, 0xC813367FU, 0xC0727F9BU,
|
||||
0x18B74777U, 0xCE7953D8U, 0x88C623B5U, 0xBB838120U, 0x3BD5A349U, 0x0F3B2C97U, 0x6E643DCBU, 0x0CD87F05U,
|
||||
0x88085AE6U, 0x49E14F17U, 0x839A6488U, 0xE3E09176U, 0xB9853498U, 0xFE6D9E42U, 0x982C4D22U, 0xD5F86DA9U,
|
||||
0xFF0F6A70U, 0x50FA7E56U, 0x82580EBFU, 0x5B5CF613U, 0x84E51D28U, 0x35314DE7U, 0x3E5B4696U, 0x19526D37U,
|
||||
0x66063BCAU, 0x7BD72D95U, 0x801EB0E6U, 0x49E959FDU, 0xC34567F8U, 0xB3A53F49U, 0x0FB35C0BU, 0x97DD6AD4U,
|
||||
0x11010B5CU, 0x62CC1CD4U, 0x81DCDAD1U, 0xF1553E98U, 0xFE254E48U, 0x78F9ECECU, 0xA9C457BFU, 0x5B776A4AU,
|
||||
0x8F659EFFU, 0x2D8D8A13U, 0x8493CC54U, 0x6C820621U, 0x4C059258U, 0x65FCDC54U, 0x6C636931U, 0x51B26353U,
|
||||
0xF862AE69U, 0x3496BB52U, 0x8551A663U, 0xD43E6144U, 0x7165BBE8U, 0xAEA00FF1U, 0xCA146285U, 0x9D1863CDU,
|
||||
0x616BFFD3U, 0x1FBBE891U, 0x8717183AU, 0xC68BCEAAU, 0x36C5C138U, 0x28347D5FU, 0xFBFC7818U, 0x1397642EU,
|
||||
0x166CCF45U, 0x06A0D9D0U, 0x86D5720DU, 0x7E37A9CFU, 0x0BA5E888U, 0xE368AEFAU, 0x5D8B73ACU, 0xDF3D64B0U,
|
||||
0xA00AE278U, 0x5E7EF3ECU, 0xA9E2D0A0U, 0xD67F4138U, 0x28D4C7DFU, 0x16441B82U, 0x03A0A617U, 0x83D02561U,
|
||||
0xD70DD2EEU, 0x4765C2ADU, 0xA820BA97U, 0x6EC3265DU, 0x15B4EE6FU, 0xDD18C827U, 0xA5D7ADA3U, 0x4F7A25FFU,
|
||||
0x4E048354U, 0x6C48916EU, 0xAA6604CEU, 0x7C7689B3U, 0x521494BFU, 0x5B8CBA89U, 0x943FB73EU, 0xC1F5221CU,
|
||||
0x3903B3C2U, 0x7553A02FU, 0xABA46EF9U, 0xC4CAEED6U, 0x6F74BD0FU, 0x90D0692CU, 0x3248BC8AU, 0x0D5F2282U,
|
||||
0xA7672661U, 0x3A1236E8U, 0xAEEB787CU, 0x591DD66FU, 0xDD54611FU, 0x8DD55994U, 0xF7EF8204U, 0x079A2B9BU,
|
||||
0xD06016F7U, 0x230907A9U, 0xAF29124BU, 0xE1A1B10AU, 0xE03448AFU, 0x46898A31U, 0x519889B0U, 0xCB302B05U,
|
||||
0x4969474DU, 0x0824546AU, 0xAD6FAC12U, 0xF3141EE4U, 0xA794327FU, 0xC01DF89FU, 0x6070932DU, 0x45BF2CE6U,
|
||||
0x3E6E77DBU, 0x113F652BU, 0xACADC625U, 0x4BA87981U, 0x9AF41BCFU, 0x0B412B3AU, 0xC6079899U, 0x89152C78U,
|
||||
0xAED16A4AU, 0x96A779E4U, 0xA7F18118U, 0x13CB69D7U, 0x18A48C1EU, 0xFA1799EFU, 0x304FE870U, 0x50353ED4U,
|
||||
0xD9D65ADCU, 0x8FBC48A5U, 0xA633EB2FU, 0xAB770EB2U, 0x25C4A5AEU, 0x314B4A4AU, 0x9638E3C4U, 0x9C9F3E4AU,
|
||||
0x40DF0B66U, 0xA4911B66U, 0xA4755576U, 0xB9C2A15CU, 0x6264DF7EU, 0xB7DF38E4U, 0xA7D0F959U, 0x121039A9U,
|
||||
0x37D83BF0U, 0xBD8A2A27U, 0xA5B73F41U, 0x017EC639U, 0x5F04F6CEU, 0x7C83EB41U, 0x01A7F2EDU, 0xDEBA3937U,
|
||||
0xA9BCAE53U, 0xF2CBBCE0U, 0xA0F829C4U, 0x9CA9FE80U, 0xED242ADEU, 0x6186DBF9U, 0xC400CC63U, 0xD47F302EU,
|
||||
0xDEBB9EC5U, 0xEBD08DA1U, 0xA13A43F3U, 0x241599E5U, 0xD044036EU, 0xAADA085CU, 0x6277C7D7U, 0x18D530B0U,
|
||||
0x47B2CF7FU, 0xC0FDDE62U, 0xA37CFDAAU, 0x36A0360BU, 0x97E479BEU, 0x2C4E7AF2U, 0x539FDD4AU, 0x965A3753U,
|
||||
0x30B5FFE9U, 0xD9E6EF23U, 0xA2BE979DU, 0x8E1C516EU, 0xAA84500EU, 0xE712A957U, 0xF5E8D6FEU, 0x5AF037CDU,
|
||||
0xBDBDF21CU, 0x14BCE1BDU, 0xB5C473D0U, 0x866616A7U, 0x4834505DU, 0x15921919U, 0x647E3AD9U, 0xFF6B144AU,
|
||||
0xCABAC28AU, 0x0DA7D0FCU, 0xB40619E7U, 0x3EDA71C2U, 0x755479EDU, 0xDECECABCU, 0xC209316DU, 0x33C114D4U,
|
||||
0x53B39330U, 0x268A833FU, 0xB640A7BEU, 0x2C6FDE2CU, 0x32F4033DU, 0x585AB812U, 0xF3E12BF0U, 0xBD4E1337U,
|
||||
0x24B4A3A6U, 0x3F91B27EU, 0xB782CD89U, 0x94D3B949U, 0x0F942A8DU, 0x93066BB7U, 0x55962044U, 0x71E413A9U,
|
||||
0xBAD03605U, 0x70D024B9U, 0xB2CDDB0CU, 0x090481F0U, 0xBDB4F69DU, 0x8E035B0FU, 0x90311ECAU, 0x7B211AB0U,
|
||||
0xCDD70693U, 0x69CB15F8U, 0xB30FB13BU, 0xB1B8E695U, 0x80D4DF2DU, 0x455F88AAU, 0x3646157EU, 0xB78B1A2EU,
|
||||
0x54DE5729U, 0x42E6463BU, 0xB1490F62U, 0xA30D497BU, 0xC774A5FDU, 0xC3CBFA04U, 0x07AE0FE3U, 0x39041DCDU,
|
||||
0x23D967BFU, 0x5BFD777AU, 0xB08B6555U, 0x1BB12E1EU, 0xFA148C4DU, 0x089729A1U, 0xA1D90457U, 0xF5AE1D53U,
|
||||
0xB3667A2EU, 0xDC656BB5U, 0xBBD72268U, 0x43D23E48U, 0x78441B9CU, 0xF9C19B74U, 0x579174BEU, 0x2C8E0FFFU,
|
||||
0xC4614AB8U, 0xC57E5AF4U, 0xBA15485FU, 0xFB6E592DU, 0x4524322CU, 0x329D48D1U, 0xF1E67F0AU, 0xE0240F61U,
|
||||
0x5D681B02U, 0xEE530937U, 0xB853F606U, 0xE9DBF6C3U, 0x028448FCU, 0xB4093A7FU, 0xC00E6597U, 0x6EAB0882U,
|
||||
0x2A6F2B94U, 0xF7483876U, 0xB9919C31U, 0x516791A6U, 0x3FE4614CU, 0x7F55E9DAU, 0x66796E23U, 0xA201081CU,
|
||||
0xB40BBE37U, 0xB809AEB1U, 0xBCDE8AB4U, 0xCCB0A91FU, 0x8DC4BD5CU, 0x6250D962U, 0xA3DE50ADU, 0xA8C40105U,
|
||||
0xC30C8EA1U, 0xA1129FF0U, 0xBD1CE083U, 0x740CCE7AU, 0xB0A494ECU, 0xA90C0AC7U, 0x05A95B19U, 0x646E019BU,
|
||||
0x5A05DF1BU, 0x8A3FCC33U, 0xBF5A5EDAU, 0x66B96194U, 0xF704EE3CU, 0x2F987869U, 0x34414184U, 0xEAE10678U,
|
||||
0x2D02EF8DU, 0x9324FD72U, 0xBE9834EDU, 0xDE0506F1U, 0xCA64C78CU, 0xE4C4ABCCU, 0x92364A30U, 0x264B06E6U,
|
||||
};
|
||||
|
||||
uint32_t ulCrc32;
|
||||
|
||||
if(pBuffer == NULL)
|
||||
{
|
||||
REDERROR();
|
||||
ulCrc32 = SUSPICIOUS_CRC_VALUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
const uint8_t *pbBuffer = CAST_VOID_PTR_TO_CONST_UINT8_PTR(pBuffer);
|
||||
uint32_t ulIdx = 0U;
|
||||
const uint32_t *pulXorCrc0 = &aulCrc32Table[7U];
|
||||
const uint32_t *pulXorCrc1 = &aulCrc32Table[6U];
|
||||
const uint32_t *pulXorCrc2 = &aulCrc32Table[5U];
|
||||
const uint32_t *pulXorCrc3 = &aulCrc32Table[4U];
|
||||
const uint32_t *pulXorData4 = &aulCrc32Table[3U];
|
||||
const uint32_t *pulXorData5 = &aulCrc32Table[2U];
|
||||
const uint32_t *pulXorData6 = &aulCrc32Table[1U];
|
||||
const uint32_t *pulXorData7 = &aulCrc32Table[0U];
|
||||
uint32_t ulSliceLen;
|
||||
|
||||
ulCrc32 = ~ulInitCrc32;
|
||||
|
||||
/* Aligned memory access is used below. To avoid suboptimal
|
||||
performance and faults (depending on platform), handle the
|
||||
unaligned initial bytes (if any) using the Sarwate algorithm.
|
||||
*/
|
||||
while((ulIdx < ulLength) && !IS_ALIGNED_PTR(&pbBuffer[ulIdx]))
|
||||
{
|
||||
ulCrc32 = (ulCrc32 >> 8U) ^ aulCrc32Table[((ulCrc32 ^ pbBuffer[ulIdx]) & 0xFFU) << 3U];
|
||||
|
||||
ulIdx++;
|
||||
}
|
||||
|
||||
/* Round down the length to the nearest multiple of eight.
|
||||
*/
|
||||
ulSliceLen = (((ulLength - ulIdx) >> 3U) << 3U) + ulIdx;
|
||||
|
||||
/* Compute the CRC in eight byte "slices". Takes advantage of
|
||||
modern processors which can load in parallel from multiple
|
||||
memory locations.
|
||||
*/
|
||||
while(ulIdx < ulSliceLen)
|
||||
{
|
||||
#if REDCONF_ENDIAN_BIG == 1
|
||||
ulCrc32 ^= pbBuffer[ulIdx] | ((uint32_t)pbBuffer[ulIdx+1U] << 8U) |
|
||||
((uint32_t)pbBuffer[ulIdx+2U] << 16U) | ((uint32_t)pbBuffer[ulIdx+3U] << 24U);
|
||||
#else
|
||||
ulCrc32 ^= *CAST_CONST_UINT32_PTR(&pbBuffer[ulIdx]);
|
||||
#endif
|
||||
|
||||
ulCrc32 =
|
||||
pulXorCrc3[((ulCrc32 >> 24U) & 0xFFU) << 3U] ^
|
||||
pulXorCrc2[((ulCrc32 >> 16U) & 0xFFU) << 3U] ^
|
||||
pulXorCrc1[((ulCrc32 >> 8U) & 0xFFU) << 3U] ^
|
||||
pulXorCrc0[ (ulCrc32 & 0xFFU) << 3U] ^
|
||||
pulXorData7[pbBuffer[ulIdx+7U] << 3U] ^
|
||||
pulXorData6[pbBuffer[ulIdx+6U] << 3U] ^
|
||||
pulXorData5[pbBuffer[ulIdx+5U] << 3U] ^
|
||||
pulXorData4[pbBuffer[ulIdx+4U] << 3U];
|
||||
|
||||
ulIdx += 8U;
|
||||
}
|
||||
|
||||
/* Compute the remaining bytes with the Sarwate algorithm.
|
||||
*/
|
||||
while(ulIdx < ulLength)
|
||||
{
|
||||
ulCrc32 = (ulCrc32 >> 8U) ^ aulCrc32Table[((ulCrc32 ^ pbBuffer[ulIdx]) & 0xFFU) << 3U];
|
||||
|
||||
ulIdx++;
|
||||
}
|
||||
|
||||
ulCrc32 = ~ulCrc32;
|
||||
}
|
||||
|
||||
return ulCrc32;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
#error "REDCONF_CRC_ALGORITHM must be set to CRC_BITWISE, CRC_SARWATE, or CRC_SLICEBY8"
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/** @brief Compute a CRC32 for a metadata node buffer.
|
||||
|
||||
@param pBuffer The metadata node buffer for which to compute a CRC. Must
|
||||
be a block sized buffer.
|
||||
|
||||
@return The CRC of the buffer.
|
||||
*/
|
||||
uint32_t RedCrcNode(
|
||||
const void *pBuffer)
|
||||
{
|
||||
uint32_t ulCrc;
|
||||
|
||||
if(pBuffer == NULL)
|
||||
{
|
||||
REDERROR();
|
||||
ulCrc = SUSPICIOUS_CRC_VALUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
const uint8_t *pbBuffer = CAST_VOID_PTR_TO_CONST_UINT8_PTR(pBuffer);
|
||||
|
||||
/* The first eight bytes of a metadata node contain the signature and
|
||||
the CRC. There is little value in CRCing the signature, and the
|
||||
CRC cannot be CRC'd, so skip over that part of the buffer.
|
||||
*/
|
||||
ulCrc = RedCrc32Update(0U, &pbBuffer[8U], REDCONF_BLOCK_SIZE - 8U);
|
||||
}
|
||||
|
||||
return ulCrc;
|
||||
}
|
||||
|
@@ -0,0 +1,82 @@
|
||||
/* ----> DO NOT REMOVE THE FOLLOWING NOTICE <----
|
||||
|
||||
Copyright (c) 2014-2015 Datalight, Inc.
|
||||
All Rights Reserved Worldwide.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; use version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but "AS-IS," WITHOUT ANY WARRANTY; without even the implied warranty
|
||||
of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
/* Businesses and individuals that for commercial or other reasons cannot
|
||||
comply with the terms of the GPLv2 license may obtain a commercial license
|
||||
before incorporating Reliance Edge into proprietary software for
|
||||
distribution in any form. Visit http://www.datalight.com/reliance-edge for
|
||||
more information.
|
||||
*/
|
||||
/** @file
|
||||
@brief Implements utilities for performing endian swaps.
|
||||
*/
|
||||
#include <redfs.h>
|
||||
|
||||
|
||||
#ifdef REDCONF_ENDIAN_SWAP
|
||||
|
||||
/** @brief Reverse the byte order of a 64-bit number.
|
||||
|
||||
@param ullToRev Number whose bytes will be reversed
|
||||
|
||||
@retval @p ullToRev with its bytes reversed.
|
||||
*/
|
||||
uint64_t RedRev64(
|
||||
uint64_t ullToRev)
|
||||
{
|
||||
uint64_t ullRet = ullToRev;
|
||||
|
||||
ullRet = ((ullRet & UINT64_SUFFIX(0x00000000FFFFFFFF)) << 32U) | ((ullRet & UINT64_SUFFIX(0xFFFFFFFF00000000)) >> 32U);
|
||||
ullRet = ((ullRet & UINT64_SUFFIX(0x0000FFFF0000FFFF)) << 16U) | ((ullRet & UINT64_SUFFIX(0xFFFF0000FFFF0000)) >> 16U);
|
||||
ullRet = ((ullRet & UINT64_SUFFIX(0x00FF00FF00FF00FF)) << 8U) | ((ullRet & UINT64_SUFFIX(0xFF00FF00FF00FF00)) >> 8U);
|
||||
|
||||
return ullRet;
|
||||
}
|
||||
|
||||
|
||||
/** @brief Reverse the byte order of a 32-bit number.
|
||||
|
||||
@param ulToRev Number whose bytes will be reversed
|
||||
|
||||
@retval @p ulToRev with its bytes reversed.
|
||||
*/
|
||||
uint32_t RedRev32(
|
||||
uint32_t ulToRev)
|
||||
{
|
||||
return ((ulToRev & 0x000000FFU) << 24U)
|
||||
| ((ulToRev & 0x0000FF00U) << 8U)
|
||||
| ((ulToRev & 0x00FF0000U) >> 8U)
|
||||
| ((ulToRev & 0xFF000000U) >> 24U);
|
||||
}
|
||||
|
||||
|
||||
/** @brief Reverse the byte order of a 16-bit number.
|
||||
|
||||
@param uToRev Number whose bytes will be reversed
|
||||
|
||||
@retval @p uToRev with its bytes reversed.
|
||||
*/
|
||||
uint16_t RedRev16(
|
||||
uint16_t uToRev)
|
||||
{
|
||||
return ((uToRev & 0xFF00U) >> 8U)
|
||||
| ((uToRev & 0x00FFU) << 8U);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
301
FreeRTOSv10.2.1/FreeRTOS-Plus/Source/Reliance-Edge/util/memory.c
Normal file
301
FreeRTOSv10.2.1/FreeRTOS-Plus/Source/Reliance-Edge/util/memory.c
Normal file
@@ -0,0 +1,301 @@
|
||||
/* ----> DO NOT REMOVE THE FOLLOWING NOTICE <----
|
||||
|
||||
Copyright (c) 2014-2015 Datalight, Inc.
|
||||
All Rights Reserved Worldwide.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; use version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but "AS-IS," WITHOUT ANY WARRANTY; without even the implied warranty
|
||||
of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
/* Businesses and individuals that for commercial or other reasons cannot
|
||||
comply with the terms of the GPLv2 license may obtain a commercial license
|
||||
before incorporating Reliance Edge into proprietary software for
|
||||
distribution in any form. Visit http://www.datalight.com/reliance-edge for
|
||||
more information.
|
||||
*/
|
||||
/** @file
|
||||
@brief Default implementations of memory manipulation functions.
|
||||
|
||||
These implementations are intended to be small and simple, and thus forego
|
||||
all optimizations. If the C library is available, or if there are better
|
||||
third-party implementations available in the system, those can be used
|
||||
instead by defining the appropriate macros in redconf.h.
|
||||
|
||||
These functions are not intended to be completely 100% ANSI C compatible
|
||||
implementations, but rather are designed to meet the needs of Reliance Edge.
|
||||
The compatibility is close enough that ANSI C compatible implementations
|
||||
can be "dropped in" as replacements without difficulty.
|
||||
*/
|
||||
#include <redfs.h>
|
||||
|
||||
|
||||
#ifndef RedMemCpyUnchecked
|
||||
static void RedMemCpyUnchecked(void *pDest, const void *pSrc, uint32_t ulLen);
|
||||
#endif
|
||||
#ifndef RedMemMoveUnchecked
|
||||
static void RedMemMoveUnchecked(void *pDest, const void *pSrc, uint32_t ulLen);
|
||||
#endif
|
||||
#ifndef RedMemSetUnchecked
|
||||
static void RedMemSetUnchecked(void *pDest, uint8_t bVal, uint32_t ulLen);
|
||||
#endif
|
||||
#ifndef RedMemCmpUnchecked
|
||||
static int32_t RedMemCmpUnchecked(const void *pMem1, const void *pMem2, uint32_t ulLen);
|
||||
#endif
|
||||
|
||||
|
||||
/** @brief Copy memory from one address to another.
|
||||
|
||||
The source and destination memory buffers should not overlap. If the
|
||||
buffers overlap, use RedMemMove() instead.
|
||||
|
||||
@param pDest The destination buffer.
|
||||
@param pSrc The source buffer.
|
||||
@param ulLen The number of bytes to copy.
|
||||
*/
|
||||
void RedMemCpy(
|
||||
void *pDest,
|
||||
const void *pSrc,
|
||||
uint32_t ulLen)
|
||||
{
|
||||
if((pDest == NULL) || (pSrc == NULL))
|
||||
{
|
||||
REDERROR();
|
||||
}
|
||||
else
|
||||
{
|
||||
RedMemCpyUnchecked(pDest, pSrc, ulLen);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#ifndef RedMemCpyUnchecked
|
||||
/** @brief Copy memory from one address to another.
|
||||
|
||||
This function should only be called from RedMemCpy().
|
||||
|
||||
@param pDest The destination buffer.
|
||||
@param pSrc The source buffer.
|
||||
@param ulLen The number of bytes to copy.
|
||||
*/
|
||||
static void RedMemCpyUnchecked(
|
||||
void *pDest,
|
||||
const void *pSrc,
|
||||
uint32_t ulLen)
|
||||
{
|
||||
uint8_t *pbDest = CAST_VOID_PTR_TO_UINT8_PTR(pDest);
|
||||
const uint8_t *pbSrc = CAST_VOID_PTR_TO_CONST_UINT8_PTR(pSrc);
|
||||
uint32_t ulIdx;
|
||||
|
||||
for(ulIdx = 0U; ulIdx < ulLen; ulIdx++)
|
||||
{
|
||||
pbDest[ulIdx] = pbSrc[ulIdx];
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/** @brief Move memory from one address to another.
|
||||
|
||||
Supports overlapping memory regions. If memory regions do not overlap, it
|
||||
is generally better to use RedMemCpy() instead.
|
||||
|
||||
@param pDest The destination buffer.
|
||||
@param pSrc The source buffer.
|
||||
@param ulLen The number of bytes to copy.
|
||||
*/
|
||||
void RedMemMove(
|
||||
void *pDest,
|
||||
const void *pSrc,
|
||||
uint32_t ulLen)
|
||||
{
|
||||
if((pDest == NULL) || (pSrc == NULL))
|
||||
{
|
||||
REDERROR();
|
||||
}
|
||||
else
|
||||
{
|
||||
RedMemMoveUnchecked(pDest, pSrc, ulLen);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#ifndef RedMemMoveUnchecked
|
||||
/** @brief Move memory from one address to another.
|
||||
|
||||
This function should only be called from RedMemMove().
|
||||
|
||||
@param pDest The destination buffer.
|
||||
@param pSrc The source buffer.
|
||||
@param ulLen The number of bytes to copy.
|
||||
*/
|
||||
static void RedMemMoveUnchecked(
|
||||
void *pDest,
|
||||
const void *pSrc,
|
||||
uint32_t ulLen)
|
||||
{
|
||||
uint8_t *pbDest = CAST_VOID_PTR_TO_UINT8_PTR(pDest);
|
||||
const uint8_t *pbSrc = CAST_VOID_PTR_TO_CONST_UINT8_PTR(pSrc);
|
||||
uint32_t ulIdx;
|
||||
|
||||
if(MEMMOVE_MUST_COPY_FORWARD(pbDest, pbSrc))
|
||||
{
|
||||
/* If the destination is lower than the source with overlapping memory
|
||||
regions, we must copy from start to end in order to copy the memory
|
||||
correctly.
|
||||
|
||||
Don't use RedMemCpy() to do this. It is possible that RedMemCpy()
|
||||
has been replaced (even though this function has not been replaced)
|
||||
with an implementation that cannot handle any kind of buffer
|
||||
overlap.
|
||||
*/
|
||||
for(ulIdx = 0U; ulIdx < ulLen; ulIdx++)
|
||||
{
|
||||
pbDest[ulIdx] = pbSrc[ulIdx];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ulIdx = ulLen;
|
||||
|
||||
while(ulIdx > 0U)
|
||||
{
|
||||
ulIdx--;
|
||||
pbDest[ulIdx] = pbSrc[ulIdx];
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif /* RedMemMoveUnchecked */
|
||||
|
||||
|
||||
/** @brief Initialize a buffer with the specified byte value.
|
||||
|
||||
@param pDest The buffer to initialize.
|
||||
@param bVal The byte value with which to initialize @p pDest.
|
||||
@param ulLen The number of bytes to initialize.
|
||||
*/
|
||||
void RedMemSet(
|
||||
void *pDest,
|
||||
uint8_t bVal,
|
||||
uint32_t ulLen)
|
||||
{
|
||||
if(pDest == NULL)
|
||||
{
|
||||
REDERROR();
|
||||
}
|
||||
else
|
||||
{
|
||||
RedMemSetUnchecked(pDest, bVal, ulLen);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#ifndef RedMemSetUnchecked
|
||||
/** @brief Initialize a buffer with the specified byte value.
|
||||
|
||||
This function should only be called from RedMemSet().
|
||||
|
||||
@param pDest The buffer to initialize.
|
||||
@param bVal The byte value with which to initialize @p pDest.
|
||||
@param ulLen The number of bytes to initialize.
|
||||
*/
|
||||
static void RedMemSetUnchecked(
|
||||
void *pDest,
|
||||
uint8_t bVal,
|
||||
uint32_t ulLen)
|
||||
{
|
||||
uint8_t *pbDest = CAST_VOID_PTR_TO_UINT8_PTR(pDest);
|
||||
uint32_t ulIdx;
|
||||
|
||||
for(ulIdx = 0U; ulIdx < ulLen; ulIdx++)
|
||||
{
|
||||
pbDest[ulIdx] = bVal;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/** @brief Compare the contents of two buffers.
|
||||
|
||||
@param pMem1 The first buffer to compare.
|
||||
@param pMem2 The second buffer to compare.
|
||||
@param ulLen The length to compare.
|
||||
|
||||
@return Zero if the two buffers are the same, otherwise nonzero.
|
||||
|
||||
@retval 0 @p pMem1 and @p pMem2 are the same.
|
||||
@retval 1 @p pMem1 is greater than @p pMem2, as determined by the
|
||||
values of the first differing bytes.
|
||||
@retval -1 @p pMem2 is greater than @p pMem1, as determined by the
|
||||
values of the first differing bytes.
|
||||
*/
|
||||
int32_t RedMemCmp(
|
||||
const void *pMem1,
|
||||
const void *pMem2,
|
||||
uint32_t ulLen)
|
||||
{
|
||||
int32_t lResult;
|
||||
|
||||
if((pMem1 == NULL) || (pMem2 == NULL))
|
||||
{
|
||||
REDERROR();
|
||||
lResult = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
lResult = RedMemCmpUnchecked(pMem1, pMem2, ulLen);
|
||||
}
|
||||
|
||||
return lResult;
|
||||
}
|
||||
|
||||
|
||||
#ifndef RedMemCmpUnchecked
|
||||
/** @brief Compare the contents of two buffers.
|
||||
|
||||
@param pMem1 The first buffer to compare.
|
||||
@param pMem2 The second buffer to compare.
|
||||
@param ulLen The length to compare.
|
||||
|
||||
@return Zero if the two buffers are the same, otherwise nonzero.
|
||||
*/
|
||||
static int32_t RedMemCmpUnchecked(
|
||||
const void *pMem1,
|
||||
const void *pMem2,
|
||||
uint32_t ulLen)
|
||||
{
|
||||
const uint8_t *pbMem1 = CAST_VOID_PTR_TO_CONST_UINT8_PTR(pMem1);
|
||||
const uint8_t *pbMem2 = CAST_VOID_PTR_TO_CONST_UINT8_PTR(pMem2);
|
||||
uint32_t ulIdx = 0U;
|
||||
int32_t lResult;
|
||||
|
||||
while((ulIdx < ulLen) && (pbMem1[ulIdx] == pbMem2[ulIdx]))
|
||||
{
|
||||
ulIdx++;
|
||||
}
|
||||
|
||||
if(ulIdx == ulLen)
|
||||
{
|
||||
lResult = 0;
|
||||
}
|
||||
else if(pbMem1[ulIdx] > pbMem2[ulIdx])
|
||||
{
|
||||
lResult = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
lResult = -1;
|
||||
}
|
||||
|
||||
return lResult;
|
||||
}
|
||||
#endif
|
||||
|
@@ -0,0 +1,61 @@
|
||||
/* ----> DO NOT REMOVE THE FOLLOWING NOTICE <----
|
||||
|
||||
Copyright (c) 2014-2015 Datalight, Inc.
|
||||
All Rights Reserved Worldwide.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; use version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but "AS-IS," WITHOUT ANY WARRANTY; without even the implied warranty
|
||||
of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
/* Businesses and individuals that for commercial or other reasons cannot
|
||||
comply with the terms of the GPLv2 license may obtain a commercial license
|
||||
before incorporating Reliance Edge into proprietary software for
|
||||
distribution in any form. Visit http://www.datalight.com/reliance-edge for
|
||||
more information.
|
||||
*/
|
||||
/** @file
|
||||
@brief Implements a utility to find the length of a name.
|
||||
*/
|
||||
#include <redfs.h>
|
||||
|
||||
#if REDCONF_API_POSIX == 1
|
||||
|
||||
|
||||
/** @brief Determine the length of a name, terminated either by a null or a path
|
||||
separator character.
|
||||
|
||||
@param pszName The name whose length is to be determined.
|
||||
|
||||
@return The length of the name.
|
||||
*/
|
||||
uint32_t RedNameLen(
|
||||
const char *pszName)
|
||||
{
|
||||
uint32_t ulIdx = 0U;
|
||||
|
||||
if(pszName == NULL)
|
||||
{
|
||||
REDERROR();
|
||||
}
|
||||
else
|
||||
{
|
||||
while((pszName[ulIdx] != '\0') && (pszName[ulIdx] != REDCONF_PATH_SEPARATOR))
|
||||
{
|
||||
ulIdx++;
|
||||
}
|
||||
}
|
||||
|
||||
return ulIdx;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@@ -0,0 +1,63 @@
|
||||
/* ----> DO NOT REMOVE THE FOLLOWING NOTICE <----
|
||||
|
||||
Copyright (c) 2014-2015 Datalight, Inc.
|
||||
All Rights Reserved Worldwide.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; use version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but "AS-IS," WITHOUT ANY WARRANTY; without even the implied warranty
|
||||
of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
/* Businesses and individuals that for commercial or other reasons cannot
|
||||
comply with the terms of the GPLv2 license may obtain a commercial license
|
||||
before incorporating Reliance Edge into proprietary software for
|
||||
distribution in any form. Visit http://www.datalight.com/reliance-edge for
|
||||
more information.
|
||||
*/
|
||||
/** @file
|
||||
@brief Implements a sign on message.
|
||||
*/
|
||||
#include <redfs.h>
|
||||
|
||||
|
||||
/** @brief Display the Reliance Edge signon message.
|
||||
*/
|
||||
void RedSignOn(void)
|
||||
{
|
||||
#if REDCONF_OUTPUT == 1
|
||||
|
||||
/* Use RedOsOutputString() instead of RedPrintf() to avoid using variadic
|
||||
arguments, since this function is called from the driver and cannot use
|
||||
functions that violate MISRA-C:2012.
|
||||
*/
|
||||
RedOsOutputString(RED_PRODUCT_NAME "\n");
|
||||
RedOsOutputString(RED_PRODUCT_EDITION "\n");
|
||||
RedOsOutputString(RED_PRODUCT_LEGAL "\n");
|
||||
RedOsOutputString(RED_PRODUCT_PATENT "\n");
|
||||
|
||||
#else
|
||||
|
||||
/* Always embed the copyright into the program data. Use "volatile" to try
|
||||
to avoid the compiler removing the variables.
|
||||
*/
|
||||
static volatile const char szVersion[] = RED_PRODUCT_NAME;
|
||||
static volatile const char szEdition[] = RED_PRODUCT_EDITION;
|
||||
static volatile const char szCopyright[] = RED_PRODUCT_LEGAL;
|
||||
static volatile const char szPatent[] = RED_PRODUCT_PATENT;
|
||||
|
||||
(void)szVersion;
|
||||
(void)szEdition;
|
||||
(void)szCopyright;
|
||||
(void)szPatent;
|
||||
|
||||
#endif
|
||||
}
|
||||
|
329
FreeRTOSv10.2.1/FreeRTOS-Plus/Source/Reliance-Edge/util/string.c
Normal file
329
FreeRTOSv10.2.1/FreeRTOS-Plus/Source/Reliance-Edge/util/string.c
Normal file
@@ -0,0 +1,329 @@
|
||||
/* ----> DO NOT REMOVE THE FOLLOWING NOTICE <----
|
||||
|
||||
Copyright (c) 2014-2015 Datalight, Inc.
|
||||
All Rights Reserved Worldwide.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; use version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but "AS-IS," WITHOUT ANY WARRANTY; without even the implied warranty
|
||||
of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
/* Businesses and individuals that for commercial or other reasons cannot
|
||||
comply with the terms of the GPLv2 license may obtain a commercial license
|
||||
before incorporating Reliance Edge into proprietary software for
|
||||
distribution in any form. Visit http://www.datalight.com/reliance-edge for
|
||||
more information.
|
||||
*/
|
||||
/** @file
|
||||
@brief Default implementations of string manipulation functions.
|
||||
|
||||
These implementations are intended to be small and simple, and thus forego
|
||||
all optimizations. If the C library is available, or if there are better
|
||||
third-party implementations available in the system, those can be used
|
||||
instead by defining the appropriate macros in redconf.h.
|
||||
|
||||
These functions are not intended to be completely 100% ANSI C compatible
|
||||
implementations, but rather are designed to meet the needs of Reliance Edge.
|
||||
The compatibility is close enough that ANSI C compatible implementations
|
||||
can be "dropped in" as replacements without difficulty.
|
||||
*/
|
||||
#include <redfs.h>
|
||||
|
||||
|
||||
#ifndef RedStrLenUnchecked
|
||||
static uint32_t RedStrLenUnchecked(const char *pszStr);
|
||||
#endif
|
||||
#ifndef RedStrCmpUnchecked
|
||||
static int32_t RedStrCmpUnchecked(const char *pszStr1, const char *pszStr2);
|
||||
#endif
|
||||
#ifndef RedStrNCmpUnchecked
|
||||
static int32_t RedStrNCmpUnchecked(const char *pszStr1, const char *pszStr2, uint32_t ulLen);
|
||||
#endif
|
||||
#ifndef RedStrNCpyUnchecked
|
||||
static void RedStrNCpyUnchecked(char *pszDst, const char *pszSrc, uint32_t ulLen);
|
||||
#endif
|
||||
|
||||
|
||||
/** @brief Determine the length (in bytes) of a null terminated string.
|
||||
|
||||
The length does not include the null terminator byte.
|
||||
|
||||
@param pszStr The null terminated string whose length is to be determined.
|
||||
|
||||
@return The length of the @p pszStr string.
|
||||
*/
|
||||
uint32_t RedStrLen(
|
||||
const char *pszStr)
|
||||
{
|
||||
uint32_t ulLen;
|
||||
|
||||
if(pszStr == NULL)
|
||||
{
|
||||
REDERROR();
|
||||
ulLen = 0U;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Cast the result to uint32_t, since RedStrLenUnchecked() might be
|
||||
strlen(), which returns size_t, which is possibly a 64-bit value.
|
||||
*/
|
||||
ulLen = (uint32_t)RedStrLenUnchecked(pszStr);
|
||||
}
|
||||
|
||||
return ulLen;
|
||||
}
|
||||
|
||||
|
||||
#ifndef RedStrLenUnchecked
|
||||
/** @brief Determine the length (in bytes) of a null terminated string.
|
||||
|
||||
@param pszStr The null terminated string whose length is to be determined.
|
||||
|
||||
@return The length of the @p pszStr string.
|
||||
*/
|
||||
static uint32_t RedStrLenUnchecked(
|
||||
const char *pszStr)
|
||||
{
|
||||
uint32_t ulLen = 0U;
|
||||
|
||||
while(pszStr[ulLen] != '\0')
|
||||
{
|
||||
ulLen++;
|
||||
}
|
||||
|
||||
return ulLen;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/** @brief Compare two null terminated strings.
|
||||
|
||||
@param pszStr1 The first string to compare.
|
||||
@param pszStr2 The second string to compare.
|
||||
|
||||
@return Zero if the two strings are the same, otherwise nonzero.
|
||||
|
||||
@retval 0 @p pszStr1 and @p pszStr2 are the same.
|
||||
@retval 1 @p pszStr1 is greater than @p pszStr2, as determined by the
|
||||
values of the first differing bytes.
|
||||
@retval -1 @p pszStr2 is greater than @p pszStr1, as determined by the
|
||||
values of the first differing bytes.
|
||||
*/
|
||||
int32_t RedStrCmp(
|
||||
const char *pszStr1,
|
||||
const char *pszStr2)
|
||||
{
|
||||
int32_t lResult;
|
||||
|
||||
if((pszStr1 == NULL) || (pszStr2 == NULL))
|
||||
{
|
||||
REDERROR();
|
||||
lResult = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
lResult = RedStrCmpUnchecked(pszStr1, pszStr2);
|
||||
}
|
||||
|
||||
return lResult;
|
||||
}
|
||||
|
||||
|
||||
#ifndef RedStrCmpUnchecked
|
||||
/** @brief Compare two null terminated strings.
|
||||
|
||||
@param pszStr1 The first string to compare.
|
||||
@param pszStr2 The second string to compare.
|
||||
|
||||
@return Zero if the two strings are the same, otherwise nonzero.
|
||||
*/
|
||||
static int32_t RedStrCmpUnchecked(
|
||||
const char *pszStr1,
|
||||
const char *pszStr2)
|
||||
{
|
||||
int32_t lResult;
|
||||
uint32_t ulIdx = 0U;
|
||||
|
||||
while((pszStr1[ulIdx] == pszStr2[ulIdx]) && (pszStr1[ulIdx] != '\0'))
|
||||
{
|
||||
ulIdx++;
|
||||
}
|
||||
|
||||
/* "The sign of a non-zero return value is determined by the sign of the
|
||||
difference between the values of the first pair of bytes (both
|
||||
interpreted as type unsigned char) that differ in the strings being
|
||||
compared." Use uint8_t instead of unsigned char to avoid MISRA C
|
||||
deviations.
|
||||
*/
|
||||
if((uint8_t)pszStr1[ulIdx] > (uint8_t)pszStr2[ulIdx])
|
||||
{
|
||||
lResult = 1;
|
||||
}
|
||||
else if((uint8_t)pszStr1[ulIdx] < (uint8_t)pszStr2[ulIdx])
|
||||
{
|
||||
lResult = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
lResult = 0;
|
||||
}
|
||||
|
||||
return lResult;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/** @brief Compare the first @p ulLen characters of two null terminated strings.
|
||||
|
||||
@param pszStr1 The first string to compare.
|
||||
@param pszStr2 The second string to compare.
|
||||
@param ulLen The maximum length to compare. The comparison stops when
|
||||
either of the strings end or when @p ulLen bytes have been
|
||||
compared.
|
||||
|
||||
@return Zero if the two strings are the same, otherwise nonzero.
|
||||
|
||||
@retval 0 @p pszStr1 and @p pszStr2 are the same.
|
||||
@retval 1 @p pszStr1 is greater than @p pszStr2, as determined by the
|
||||
values of the first differing bytes.
|
||||
@retval -1 @p pszStr2 is greater than @p pszStr1, as determined by the
|
||||
values of the first differing bytes.
|
||||
*/
|
||||
int32_t RedStrNCmp(
|
||||
const char *pszStr1,
|
||||
const char *pszStr2,
|
||||
uint32_t ulLen)
|
||||
{
|
||||
int32_t lResult;
|
||||
|
||||
if((pszStr1 == NULL) || (pszStr2 == NULL))
|
||||
{
|
||||
REDERROR();
|
||||
lResult = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
lResult = RedStrNCmpUnchecked(pszStr1, pszStr2, ulLen);
|
||||
}
|
||||
|
||||
return lResult;
|
||||
}
|
||||
|
||||
|
||||
#ifndef RedStrNCmpUnchecked
|
||||
/** @brief Compare the first @p ulLen characters of two null terminated strings.
|
||||
|
||||
@param pszStr1 The first string to compare.
|
||||
@param pszStr2 The second string to compare.
|
||||
@param ulLen The maximum length to compare. The comparison stops when
|
||||
either of the strings end or when @p ulLen bytes have been
|
||||
compared.
|
||||
|
||||
@return Zero if the two strings are the same, otherwise nonzero.
|
||||
*/
|
||||
static int32_t RedStrNCmpUnchecked(
|
||||
const char *pszStr1,
|
||||
const char *pszStr2,
|
||||
uint32_t ulLen)
|
||||
{
|
||||
int32_t lResult = 0;
|
||||
uint32_t ulIdx;
|
||||
|
||||
for(ulIdx = 0U; ulIdx < ulLen; ulIdx++)
|
||||
{
|
||||
if(pszStr1[ulIdx] != pszStr2[ulIdx])
|
||||
{
|
||||
/* "The sign of a non-zero return value is determined by the sign
|
||||
of the difference between the values of the first pair of bytes
|
||||
(both interpreted as type unsigned char) that differ in the
|
||||
strings being compared." Use uint8_t instead of unsigned char
|
||||
to avoid MISRA C deviations.
|
||||
*/
|
||||
if((uint8_t)pszStr1[ulIdx] > (uint8_t)pszStr2[ulIdx])
|
||||
{
|
||||
lResult = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
lResult = -1;
|
||||
}
|
||||
}
|
||||
|
||||
if((lResult != 0) || (pszStr1[ulIdx] == '\0'))
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return lResult;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/** @brief Copy a string.
|
||||
|
||||
Copy up to @p ulLen bytes of a null-terminated string (@p pszSrc) to a
|
||||
destination buffer (@p pszDst). The result will not be null-terminated if
|
||||
@p pszSrc is longer than @p ulLen - 1 bytes.
|
||||
|
||||
If @p pszSrc is shorter than @p ulLen - 1 bytes, the remainder of @p pszDst
|
||||
will be filled with null bytes.
|
||||
|
||||
@param pszDst The destination buffer, which is at least @p ulLen bytes
|
||||
in size.
|
||||
@param pszSrc The null-terminated string to copy.
|
||||
@param ulLen The maximum number of characters to copy.
|
||||
*/
|
||||
void RedStrNCpy(
|
||||
char *pszDst,
|
||||
const char *pszSrc,
|
||||
uint32_t ulLen)
|
||||
{
|
||||
if((pszDst == NULL) || (pszSrc == NULL))
|
||||
{
|
||||
REDERROR();
|
||||
}
|
||||
else
|
||||
{
|
||||
RedStrNCpyUnchecked(pszDst, pszSrc, ulLen);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#ifndef RedStrNCpyUnchecked
|
||||
/** @brief Copy a string.
|
||||
|
||||
@param pszDst The destination buffer, which is at least @p ulLen bytes
|
||||
in size.
|
||||
@param pszSrc The null-terminated string to copy.
|
||||
@param ulLen The maximum number of characters to copy.
|
||||
*/
|
||||
static void RedStrNCpyUnchecked(
|
||||
char *pszDst,
|
||||
const char *pszSrc,
|
||||
uint32_t ulLen)
|
||||
{
|
||||
uint32_t ulIdx = 0U;
|
||||
|
||||
while((ulIdx < ulLen) && (pszSrc[ulIdx] != '\0'))
|
||||
{
|
||||
pszDst[ulIdx] = pszSrc[ulIdx];
|
||||
ulIdx++;
|
||||
}
|
||||
|
||||
while(ulIdx < ulLen)
|
||||
{
|
||||
pszDst[ulIdx] = '\0';
|
||||
ulIdx++;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
Reference in New Issue
Block a user