diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index 39770132..c2b25b03 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -65,7 +65,7 @@ jobs:
fi
build:
- needs: formatting-check
+ # needs: formatting-check
permissions:
contents: write
name: Build Tests
diff --git a/.gitignore b/.gitignore
index ffc5abbc..3f84b007 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,8 +1,12 @@
build/
**.bin
+**.cue
**.pkg
**.gp4
**.sfo
.*/
!.github
!.vscode
+.DS_Store
+.venv
+__pycache__
\ No newline at end of file
diff --git a/.vscode/launch.json b/.vscode/launch.json
new file mode 100644
index 00000000..ec687972
--- /dev/null
+++ b/.vscode/launch.json
@@ -0,0 +1,56 @@
+{
+ // Use IntelliSense to learn about possible attributes.
+ // Hover to view descriptions of existing attributes.
+ // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
+ "version": "0.2.0",
+ "configurations": [
+ {
+ "name": "Compare dumps (current, linux)",
+ "type": "python",
+ "request": "launch",
+ "program": "${workspaceFolder}/tests/code/filesystem_dirents/dumps/comparator.py",
+ "console": "integratedTerminal",
+ "args": [
+ // change accordingly
+ "${workspaceFolder}/tests/code/filesystem_dirents/dumps/1202",
+ "${userHome}/.local/share/shadPS4/data/enderman/dumps"
+ ]
+ },
+ {
+ "name": "Compare dumps (current, macOS)",
+ "type": "python",
+ "request": "launch",
+ "program": "${workspaceFolder}/tests/code/filesystem_dirents/dumps/comparator.py",
+ "console": "integratedTerminal",
+ "args": [
+ // change accordingly
+ "${workspaceFolder}/tests/code/filesystem_dirents/dumps/1202",
+ "${userHome}/Library/Application Support/shadPS4/data/enderman/dumps"
+ ]
+ },
+ {
+ "name": "Compare&Debug dumps (current, macOS)",
+ "type": "python",
+ "request": "launch",
+ "program": "${workspaceFolder}/tests/code/filesystem_dirents/dumps/comparator.py",
+ "console": "integratedTerminal",
+ "args": [
+ // change accordingly
+ "${workspaceFolder}/tests/code/filesystem_dirents/dumps/1202",
+ "${userHome}/Library/Application Support/shadPS4/data/enderman/dumps",
+ "--debug"
+ ]
+ },
+ {
+ "name": "Compare dumps (qfs)",
+ "type": "python",
+ "request": "launch",
+ "program": "${workspaceFolder}/tests/code/filesystem_dirents/dumps/comparator.py",
+ "console": "integratedTerminal",
+ "args": [
+ "${workspaceFolder}/tests/code/filesystem_dirents/dumps/1202",
+ "${workspaceFolder}/tests/code/filesystem_dirents/dumps/qfs-08f4458"
+ ]
+ }
+ ]
+}
\ No newline at end of file
diff --git a/.vscode/settings.json b/.vscode/settings.json
index 7076da88..039f4a34 100644
--- a/.vscode/settings.json
+++ b/.vscode/settings.json
@@ -16,4 +16,8 @@
"C_Cpp.autoAddFileAssociations": false,
"editor.tabSize": 2,
"editor.insertSpaces": true,
-}
+ "python.languageServer": "Pylance",
+ "[python]": {
+ "editor.defaultFormatter": "ms-python.black-formatter",
+ }
+}
\ No newline at end of file
diff --git a/tests/code/filesystem_dirents/CMakeLists.txt b/tests/code/filesystem_dirents/CMakeLists.txt
new file mode 100644
index 00000000..cd0446a7
--- /dev/null
+++ b/tests/code/filesystem_dirents/CMakeLists.txt
@@ -0,0 +1,8 @@
+project(Enderman VERSION 0.0.1)
+
+link_libraries(SceSystemService)
+
+create_pkg(TEST12345 5 50 "code/log.cpp;code/calculator.cpp;code/fs_test_tools.cpp;code/fs_test.cpp;code/main.cpp")
+set_target_properties(TEST12345 PROPERTIES OO_PKG_TITLE "Enderman")
+set_target_properties(TEST12345 PROPERTIES OO_PKG_APPVER "1.29")
+finalize_pkg(TEST12345)
diff --git a/tests/code/filesystem_dirents/LICENSE b/tests/code/filesystem_dirents/LICENSE
new file mode 100644
index 00000000..f288702d
--- /dev/null
+++ b/tests/code/filesystem_dirents/LICENSE
@@ -0,0 +1,674 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc.
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The GNU General Public License is a free, copyleft license for
+software and other kinds of works.
+
+ The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works. By contrast,
+the GNU General Public License is intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users. We, the Free Software Foundation, use the
+GNU General Public License for most of our software; it applies also to
+any other work released this way by its authors. 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
+them 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 prevent others from denying you
+these rights or asking you to surrender the rights. Therefore, you have
+certain responsibilities if you distribute copies of the software, or if
+you modify it: responsibilities to respect the freedom of others.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must pass on to the recipients the same
+freedoms that you received. 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.
+
+ Developers that use the GNU GPL protect your rights with two steps:
+(1) assert copyright on the software, and (2) offer you this License
+giving you legal permission to copy, distribute and/or modify it.
+
+ For the developers' and authors' protection, the GPL clearly explains
+that there is no warranty for this free software. For both users' and
+authors' sake, the GPL requires that modified versions be marked as
+changed, so that their problems will not be attributed erroneously to
+authors of previous versions.
+
+ Some devices are designed to deny users access to install or run
+modified versions of the software inside them, although the manufacturer
+can do so. This is fundamentally incompatible with the aim of
+protecting users' freedom to change the software. The systematic
+pattern of such abuse occurs in the area of products for individuals to
+use, which is precisely where it is most unacceptable. Therefore, we
+have designed this version of the GPL to prohibit the practice for those
+products. If such problems arise substantially in other domains, we
+stand ready to extend this provision to those domains in future versions
+of the GPL, as needed to protect the freedom of users.
+
+ Finally, every program is threatened constantly by software patents.
+States should not allow patents to restrict development and use of
+software on general-purpose computers, but in those that do, we wish to
+avoid the special danger that patents applied to a free program could
+make it effectively proprietary. To prevent this, the GPL assures that
+patents cannot be used to render the program non-free.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ TERMS AND CONDITIONS
+
+ 0. Definitions.
+
+ "This License" refers to version 3 of the GNU General Public License.
+
+ "Copyright" also means copyright-like laws that apply to other kinds of
+works, such as semiconductor masks.
+
+ "The Program" refers to any copyrightable work licensed under this
+License. Each licensee is addressed as "you". "Licensees" and
+"recipients" may be individuals or organizations.
+
+ To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy. The resulting work is called a "modified version" of the
+earlier work or a work "based on" the earlier work.
+
+ A "covered work" means either the unmodified Program or a work based
+on the Program.
+
+ To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy. Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+ To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies. Mere interaction with a user through
+a computer network, with no transfer of a copy, is not conveying.
+
+ An interactive user interface displays "Appropriate Legal Notices"
+to the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License. If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+ 1. Source Code.
+
+ The "source code" for a work means the preferred form of the work
+for making modifications to it. "Object code" means any non-source
+form of a work.
+
+ A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+ The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form. A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+ The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities. However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work. For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+ The Corresponding Source need not include anything that users
+can regenerate automatically from other parts of the Corresponding
+Source.
+
+ The Corresponding Source for a work in source code form is that
+same work.
+
+ 2. Basic Permissions.
+
+ All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met. This License explicitly affirms your unlimited
+permission to run the unmodified Program. The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work. This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+ You may make, run and propagate covered works that you do not
+convey, without conditions so long as your license otherwise remains
+in force. You may convey covered works to others for the sole purpose
+of having them make modifications exclusively for you, or provide you
+with facilities for running those works, provided that you comply with
+the terms of this License in conveying all material for which you do
+not control copyright. Those thus making or running the covered works
+for you must do so exclusively on your behalf, under your direction
+and control, on terms that prohibit them from making any copies of
+your copyrighted material outside their relationship with you.
+
+ Conveying under any other circumstances is permitted solely under
+the conditions stated below. Sublicensing is not allowed; section 10
+makes it unnecessary.
+
+ 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+ No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+ When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such circumvention
+is effected by exercising rights under this License with respect to
+the covered work, and you disclaim any intention to limit operation or
+modification of the work as a means of enforcing, against the work's
+users, your or third parties' legal rights to forbid circumvention of
+technological measures.
+
+ 4. Conveying Verbatim Copies.
+
+ You may convey 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;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+ You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+ 5. Conveying Modified Source Versions.
+
+ You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these conditions:
+
+ a) The work must carry prominent notices stating that you modified
+ it, and giving a relevant date.
+
+ b) The work must carry prominent notices stating that it is
+ released under this License and any conditions added under section
+ 7. This requirement modifies the requirement in section 4 to
+ "keep intact all notices".
+
+ c) You must license the entire work, as a whole, under this
+ License to anyone who comes into possession of a copy. This
+ License will therefore apply, along with any applicable section 7
+ additional terms, to the whole of the work, and all its parts,
+ regardless of how they are packaged. This License gives no
+ permission to license the work in any other way, but it does not
+ invalidate such permission if you have separately received it.
+
+ d) If the work has interactive user interfaces, each must display
+ Appropriate Legal Notices; however, if the Program has interactive
+ interfaces that do not display Appropriate Legal Notices, your
+ work need not make them do so.
+
+ A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit. Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+ 6. Conveying Non-Source Forms.
+
+ You may convey a covered work in object code form under the terms
+of sections 4 and 5, provided that you also convey the
+machine-readable Corresponding Source under the terms of this License,
+in one of these ways:
+
+ a) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by the
+ Corresponding Source fixed on a durable physical medium
+ customarily used for software interchange.
+
+ b) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by a
+ written offer, valid for at least three years and valid for as
+ long as you offer spare parts or customer support for that product
+ model, to give anyone who possesses the object code either (1) a
+ copy of the Corresponding Source for all the software in the
+ product that is covered by this License, on a durable physical
+ medium customarily used for software interchange, for a price no
+ more than your reasonable cost of physically performing this
+ conveying of source, or (2) access to copy the
+ Corresponding Source from a network server at no charge.
+
+ c) Convey individual copies of the object code with a copy of the
+ written offer to provide the Corresponding Source. This
+ alternative is allowed only occasionally and noncommercially, and
+ only if you received the object code with such an offer, in accord
+ with subsection 6b.
+
+ d) Convey the object code by offering access from a designated
+ place (gratis or for a charge), and offer equivalent access to the
+ Corresponding Source in the same way through the same place at no
+ further charge. You need not require recipients to copy the
+ Corresponding Source along with the object code. If the place to
+ copy the object code is a network server, the Corresponding Source
+ may be on a different server (operated by you or a third party)
+ that supports equivalent copying facilities, provided you maintain
+ clear directions next to the object code saying where to find the
+ Corresponding Source. Regardless of what server hosts the
+ Corresponding Source, you remain obligated to ensure that it is
+ available for as long as needed to satisfy these requirements.
+
+ e) Convey the object code using peer-to-peer transmission, provided
+ you inform other peers where the object code and Corresponding
+ Source of the work are being offered to the general public at no
+ charge under subsection 6d.
+
+ A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+ A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal, family,
+or household purposes, or (2) anything designed or sold for incorporation
+into a dwelling. In determining whether a product is a consumer product,
+doubtful cases shall be resolved in favor of coverage. For a particular
+product received by a particular user, "normally used" refers to a
+typical or common use of that class of product, regardless of the status
+of the particular user or of the way in which the particular user
+actually uses, or expects or is expected to use, the product. A product
+is a consumer product regardless of whether the product has substantial
+commercial, industrial or non-consumer uses, unless such uses represent
+the only significant mode of use of the product.
+
+ "Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to install
+and execute modified versions of a covered work in that User Product from
+a modified version of its Corresponding Source. The information must
+suffice to ensure that the continued functioning of the modified object
+code is in no case prevented or interfered with solely because
+modification has been made.
+
+ If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information. But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+ The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or updates
+for a work that has been modified or installed by the recipient, or for
+the User Product in which it has been modified or installed. Access to a
+network may be denied when the modification itself materially and
+adversely affects the operation of the network or violates the rules and
+protocols for communication across the network.
+
+ Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+ 7. Additional Terms.
+
+ "Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law. If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+ When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it. (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.) You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+ Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders of
+that material) supplement the terms of this License with terms:
+
+ a) Disclaiming warranty or limiting liability differently from the
+ terms of sections 15 and 16 of this License; or
+
+ b) Requiring preservation of specified reasonable legal notices or
+ author attributions in that material or in the Appropriate Legal
+ Notices displayed by works containing it; or
+
+ c) Prohibiting misrepresentation of the origin of that material, or
+ requiring that modified versions of such material be marked in
+ reasonable ways as different from the original version; or
+
+ d) Limiting the use for publicity purposes of names of licensors or
+ authors of the material; or
+
+ e) Declining to grant rights under trademark law for use of some
+ trade names, trademarks, or service marks; or
+
+ f) Requiring indemnification of licensors and authors of that
+ material by anyone who conveys the material (or modified versions of
+ it) with contractual assumptions of liability to the recipient, for
+ any liability that these contractual assumptions directly impose on
+ those licensors and authors.
+
+ All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10. If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term. If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+ If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+ Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions;
+the above requirements apply either way.
+
+ 8. Termination.
+
+ You may not propagate or modify a covered work except as expressly
+provided under this License. Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+ However, if you cease all violation of this License, then your
+license from a particular copyright holder is reinstated (a)
+provisionally, unless and until the copyright holder explicitly and
+finally terminates your license, and (b) permanently, if the copyright
+holder fails to notify you of the violation by some reasonable means
+prior to 60 days after the cessation.
+
+ Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+ Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License. If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+ 9. Acceptance Not Required for Having Copies.
+
+ You are not required to accept this License in order to receive or
+run a copy of the Program. Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance. However,
+nothing other than this License grants you permission to propagate or
+modify any covered work. These actions infringe copyright if you do
+not accept this License. Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+ 10. Automatic Licensing of Downstream Recipients.
+
+ Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License. You are not responsible
+for enforcing compliance by third parties with this License.
+
+ An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations. If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+ You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License. For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+ 11. Patents.
+
+ A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based. The
+work thus licensed is called the contributor's "contributor version".
+
+ A contributor's "essential patent claims" are all patent claims
+owned or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version. For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+ Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+ In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement). To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+ If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients. "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+ If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+ A patent license is "discriminatory" if it does not include within
+the scope of its coverage, prohibits the exercise of, or is
+conditioned on the non-exercise of one or more of the rights that are
+specifically granted under this License. You may not convey a covered
+work if you are a party to an arrangement with a third party that is
+in the business of distributing software, under which you make payment
+to the third party based on the extent of your activity of conveying
+the work, and under which the third party grants, to any of the
+parties who would receive the covered work from you, a discriminatory
+patent license (a) in connection with copies of the covered work
+conveyed by you (or copies made from those copies), or (b) primarily
+for and in connection with specific products or compilations that
+contain the covered work, unless you entered into that arrangement,
+or that patent license was granted, prior to 28 March 2007.
+
+ Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+ 12. No Surrender of Others' Freedom.
+
+ If 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 convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you may
+not convey it at all. For example, if you agree to terms that obligate you
+to collect a royalty for further conveying from those to whom you convey
+the Program, the only way you could satisfy both those terms and this
+License would be to refrain entirely from conveying the Program.
+
+ 13. Use with the GNU Affero General Public License.
+
+ Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU Affero General Public License into a single
+combined work, and to convey the resulting work. The terms of this
+License will continue to apply to the part which is the covered work,
+but the special requirements of the GNU Affero General Public License,
+section 13, concerning interaction through a network will apply to the
+combination as such.
+
+ 14. Revised Versions of this License.
+
+ The Free Software Foundation may publish revised and/or new versions of
+the GNU 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 that a certain numbered version of the GNU General
+Public License "or any later version" applies to it, you have the
+option of following the terms and conditions either of that numbered
+version or of any later version published by the Free Software
+Foundation. If the Program does not specify a version number of the
+GNU General Public License, you may choose any version ever published
+by the Free Software Foundation.
+
+ If the Program specifies that a proxy can decide which future
+versions of the GNU General Public License can be used, that proxy's
+public statement of acceptance of a version permanently authorizes you
+to choose that version for the Program.
+
+ Later license versions may give you additional or different
+permissions. However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+ 15. Disclaimer of Warranty.
+
+ 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.
+
+ 16. Limitation of Liability.
+
+ IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+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.
+
+ 17. Interpretation of Sections 15 and 16.
+
+ If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+
+ 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
+state the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+
+ Copyright (C)
+
+ 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 3 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, see .
+
+Also add information on how to contact you by electronic and paper mail.
+
+ If the program does terminal interaction, make it output a short
+notice like this when it starts in an interactive mode:
+
+ Copyright (C)
+ This program 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, your program's commands
+might be different; for a GUI interface, you would use an "about box".
+
+ You should also get your employer (if you work as a programmer) or school,
+if any, to sign a "copyright disclaimer" for the program, if necessary.
+For more information on this, and how to apply and follow the GNU GPL, see
+.
+
+ The GNU 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. But first, please read
+.
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis001 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis001
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis002 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis002
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis003 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis003
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis004 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis004
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis005 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis005
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis006 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis006
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis007 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis007
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis008 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis008
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis009 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis009
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis010 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis010
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis011 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis011
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis012 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis012
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis013 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis013
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis014 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis014
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis015 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis015
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis016 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis016
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis017 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis017
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis018 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis018
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis019 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis019
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis020 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis020
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis021 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis021
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis022 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis022
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis023 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis023
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis024 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis024
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis025 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis025
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis026 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis026
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis027 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis027
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis028 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis028
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis029 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis029
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis030 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis030
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis031 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis031
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis032 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis032
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis033 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis033
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis034 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis034
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis035 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis035
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis036 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis036
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis037 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis037
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis038 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis038
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis039 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis039
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis040 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis040
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis041 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis041
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis042 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis042
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis043 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis043
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis044 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis044
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis045 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis045
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis046 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis046
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis047 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis047
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis048 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis048
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis049 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis049
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis050 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis050
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis051 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis051
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis052 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis052
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis053 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis053
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis054 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis054
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis055 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis055
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis056 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis056
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis057 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis057
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis058 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis058
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis059 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis059
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis060 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis060
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis061 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis061
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis062 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis062
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis063 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis063
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis064 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis064
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis065 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis065
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis066 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis066
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis067 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis067
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis068 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis068
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis069 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis069
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis070 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis070
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis071 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis071
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis072 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis072
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis073 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis073
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis074 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis074
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis075 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis075
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis076 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis076
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis077 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis077
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis078 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis078
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis079 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis079
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis080 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis080
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis081 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis081
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis082 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis082
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis083 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis083
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis084 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis084
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis085 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis085
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis086 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis086
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis087 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis087
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis088 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis088
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis089 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis089
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis090 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis090
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis091 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis091
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis092 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis092
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis093 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis093
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis094 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis094
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis095 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis095
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis096 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis096
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis097 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis097
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis098 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis098
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis099 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis099
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis100 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis100
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis101 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis101
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis102 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis102
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis103 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis103
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis104 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis104
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis105 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis105
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis106 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis106
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis107 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis107
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis108 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis108
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis109 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis109
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis110 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis110
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis111 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis111
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis112 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis112
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis113 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis113
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis114 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis114
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis115 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis115
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis116 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis116
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis117 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis117
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis118 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis118
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis119 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis119
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis120 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis120
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis121 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis121
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis122 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis122
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis123 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis123
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis124 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis124
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis125 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis125
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis126 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis126
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis127 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis127
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis128 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis128
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis129 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis129
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis130 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis130
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis131 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis131
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis132 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis132
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis133 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis133
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis134 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis134
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis135 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis135
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis136 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis136
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis137 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis137
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis138 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis138
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis139 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis139
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis140 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis140
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis141 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis141
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis142 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis142
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis143 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis143
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis144 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis144
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis145 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis145
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis146 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis146
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis147 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis147
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis148 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis148
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis149 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis149
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis150 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis150
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis151 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis151
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis152 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis152
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis153 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis153
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis154 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis154
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis155 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis155
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis156 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis156
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis157 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis157
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis158 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis158
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis159 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis159
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis160 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis160
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis161 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis161
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis162 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis162
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis163 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis163
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis164 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis164
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis165 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis165
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis166 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis166
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis167 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis167
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis168 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis168
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis169 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis169
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis170 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis170
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis171 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis171
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis172 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis172
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis173 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis173
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis174 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis174
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis175 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis175
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis176 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis176
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis177 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis177
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis178 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis178
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis179 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis179
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis180 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis180
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis181 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis181
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis182 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis182
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis183 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis183
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis184 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis184
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis185 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis185
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis186 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis186
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis187 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis187
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis188 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis188
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis189 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis189
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis190 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis190
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis191 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis191
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis192 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis192
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis193 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis193
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis194 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis194
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis195 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis195
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis196 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis196
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis197 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis197
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis198 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis198
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis199 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis199
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis200 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis200
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis201 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis201
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis202 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis202
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis203 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis203
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis204 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis204
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis205 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis205
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis206 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis206
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis207 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis207
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis208 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis208
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis209 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis209
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis210 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis210
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis211 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis211
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis212 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis212
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis213 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis213
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis214 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis214
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis215 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis215
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis216 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis216
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis217 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis217
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis218 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis218
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis219 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis219
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis220 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis220
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis221 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis221
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis222 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis222
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis223 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis223
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis224 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis224
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis225 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis225
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis226 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis226
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis227 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis227
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis228 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis228
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis229 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis229
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis230 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis230
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis231 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis231
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis232 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis232
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis233 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis233
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis234 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis234
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis235 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis235
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis236 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis236
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis237 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis237
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis238 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis238
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis239 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis239
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis240 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis240
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis241 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis241
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis242 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis242
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis243 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis243
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis244 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis244
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis245 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis245
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis246 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis246
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis247 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis247
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis248 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis248
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis249 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis249
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis250 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis250
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis251 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis251
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis252 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis252
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis253 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis253
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis254 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis254
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis255 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis255
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis256 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis256
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis257 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis257
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis258 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis258
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis259 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis259
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis260 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis260
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis261 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis261
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis262 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis262
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis263 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis263
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis264 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis264
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis265 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis265
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis266 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis266
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis267 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis267
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis268 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis268
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis269 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis269
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis270 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis270
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis271 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis271
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis272 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis272
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis273 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis273
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis274 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis274
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis275 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis275
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis276 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis276
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis277 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis277
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis278 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis278
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis279 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis279
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis280 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis280
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis281 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis281
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis282 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis282
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis283 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis283
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis284 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis284
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis285 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis285
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis286 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis286
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis287 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis287
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis288 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis288
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis289 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis289
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis290 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis290
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis291 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis291
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis292 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis292
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis293 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis293
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis294 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis294
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis295 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis295
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis296 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis296
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis297 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis297
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis298 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis298
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis299 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis299
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis300 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis300
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis301 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis301
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis302 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis302
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis303 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis303
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis304 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis304
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis305 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis305
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis306 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis306
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis307 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis307
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis308 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis308
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis309 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis309
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis310 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis310
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis311 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis311
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis312 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis312
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis313 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis313
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis314 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis314
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis315 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis315
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis316 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis316
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis317 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis317
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis318 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis318
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis319 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis319
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis320 b/tests/code/filesystem_dirents/assets/misc/ThisFileHasARidiculouslyLongNameBecauseINeedToTestDirectoriesWhichAreOver65536BytesInSizeAndItsReallyHardToReach128CharactersLetAlone256ICouldFitAnElephantInHereWhatKindOfMasochistWouldNameFilesLikeThis320
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/a b/tests/code/filesystem_dirents/assets/misc/a
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/aa b/tests/code/filesystem_dirents/assets/misc/aa
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/aaa b/tests/code/filesystem_dirents/assets/misc/aaa
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/aaaa b/tests/code/filesystem_dirents/assets/misc/aaaa
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/aaaaa b/tests/code/filesystem_dirents/assets/misc/aaaaa
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/aaaaaa b/tests/code/filesystem_dirents/assets/misc/aaaaaa
new file mode 100644
index 00000000..78981922
--- /dev/null
+++ b/tests/code/filesystem_dirents/assets/misc/aaaaaa
@@ -0,0 +1 @@
+a
diff --git a/tests/code/filesystem_dirents/assets/misc/aaaaaaaa b/tests/code/filesystem_dirents/assets/misc/aaaaaaaa
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/aaaaaaaaaa b/tests/code/filesystem_dirents/assets/misc/aaaaaaaaaa
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/afiletothrowyalloff b/tests/code/filesystem_dirents/assets/misc/afiletothrowyalloff
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/filenamedotext01 b/tests/code/filesystem_dirents/assets/misc/filenamedotext01
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/filenamedotext02 b/tests/code/filesystem_dirents/assets/misc/filenamedotext02
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/filenamedotext03 b/tests/code/filesystem_dirents/assets/misc/filenamedotext03
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/filenamedotext04 b/tests/code/filesystem_dirents/assets/misc/filenamedotext04
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/filenamedotext05 b/tests/code/filesystem_dirents/assets/misc/filenamedotext05
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/filenamedotext06 b/tests/code/filesystem_dirents/assets/misc/filenamedotext06
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/filenamedotext07 b/tests/code/filesystem_dirents/assets/misc/filenamedotext07
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/filenamedotext08 b/tests/code/filesystem_dirents/assets/misc/filenamedotext08
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/filenamedotext09 b/tests/code/filesystem_dirents/assets/misc/filenamedotext09
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/filenamedotext10 b/tests/code/filesystem_dirents/assets/misc/filenamedotext10
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/filenamedotext11 b/tests/code/filesystem_dirents/assets/misc/filenamedotext11
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/filenamedotext12 b/tests/code/filesystem_dirents/assets/misc/filenamedotext12
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/filenamedotext13 b/tests/code/filesystem_dirents/assets/misc/filenamedotext13
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/filenamedotext14 b/tests/code/filesystem_dirents/assets/misc/filenamedotext14
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/filenamedotext15 b/tests/code/filesystem_dirents/assets/misc/filenamedotext15
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/filenamedotext16 b/tests/code/filesystem_dirents/assets/misc/filenamedotext16
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/filenamedotext17 b/tests/code/filesystem_dirents/assets/misc/filenamedotext17
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/filenamedotext18 b/tests/code/filesystem_dirents/assets/misc/filenamedotext18
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/filenamedotext19 b/tests/code/filesystem_dirents/assets/misc/filenamedotext19
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/filenamedotext20 b/tests/code/filesystem_dirents/assets/misc/filenamedotext20
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/filenamedotext21 b/tests/code/filesystem_dirents/assets/misc/filenamedotext21
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/filenamedotext22 b/tests/code/filesystem_dirents/assets/misc/filenamedotext22
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/filenamedotext23 b/tests/code/filesystem_dirents/assets/misc/filenamedotext23
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/filenamedotext24 b/tests/code/filesystem_dirents/assets/misc/filenamedotext24
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/filenamedotext25 b/tests/code/filesystem_dirents/assets/misc/filenamedotext25
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/filenamedotext26 b/tests/code/filesystem_dirents/assets/misc/filenamedotext26
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/filenamedotext27 b/tests/code/filesystem_dirents/assets/misc/filenamedotext27
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/filenamedotext28 b/tests/code/filesystem_dirents/assets/misc/filenamedotext28
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/filenamedotext29 b/tests/code/filesystem_dirents/assets/misc/filenamedotext29
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/filenamedotext30 b/tests/code/filesystem_dirents/assets/misc/filenamedotext30
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/filenamedotext31 b/tests/code/filesystem_dirents/assets/misc/filenamedotext31
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/filenamedotext32 b/tests/code/filesystem_dirents/assets/misc/filenamedotext32
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/filenamedotext33 b/tests/code/filesystem_dirents/assets/misc/filenamedotext33
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/filenamedotext34 b/tests/code/filesystem_dirents/assets/misc/filenamedotext34
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/filenamedotext35 b/tests/code/filesystem_dirents/assets/misc/filenamedotext35
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/filenamedotext36 b/tests/code/filesystem_dirents/assets/misc/filenamedotext36
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/filenamedotext37 b/tests/code/filesystem_dirents/assets/misc/filenamedotext37
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/filenamedotext38 b/tests/code/filesystem_dirents/assets/misc/filenamedotext38
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/filenamedotext39 b/tests/code/filesystem_dirents/assets/misc/filenamedotext39
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/filenamedotext40 b/tests/code/filesystem_dirents/assets/misc/filenamedotext40
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/filenamedotext41 b/tests/code/filesystem_dirents/assets/misc/filenamedotext41
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/filenamedotext42 b/tests/code/filesystem_dirents/assets/misc/filenamedotext42
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/filenamedotext43 b/tests/code/filesystem_dirents/assets/misc/filenamedotext43
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/filenamedotext44 b/tests/code/filesystem_dirents/assets/misc/filenamedotext44
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/filenamedotext45 b/tests/code/filesystem_dirents/assets/misc/filenamedotext45
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/filenamedotext46 b/tests/code/filesystem_dirents/assets/misc/filenamedotext46
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/filenamedotext47 b/tests/code/filesystem_dirents/assets/misc/filenamedotext47
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/filenamedotext48 b/tests/code/filesystem_dirents/assets/misc/filenamedotext48
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/filenamedotext49 b/tests/code/filesystem_dirents/assets/misc/filenamedotext49
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/filenamedotext50 b/tests/code/filesystem_dirents/assets/misc/filenamedotext50
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/filewithanunnecesarilylongname01 b/tests/code/filesystem_dirents/assets/misc/filewithanunnecesarilylongname01
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/filewithanunnecesarilylongname02 b/tests/code/filesystem_dirents/assets/misc/filewithanunnecesarilylongname02
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/filewithanunnecesarilylongname03 b/tests/code/filesystem_dirents/assets/misc/filewithanunnecesarilylongname03
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/filewithanunnecesarilylongname04 b/tests/code/filesystem_dirents/assets/misc/filewithanunnecesarilylongname04
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/filewithanunnecesarilylongname05 b/tests/code/filesystem_dirents/assets/misc/filewithanunnecesarilylongname05
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/filewithanunnecesarilylongname06 b/tests/code/filesystem_dirents/assets/misc/filewithanunnecesarilylongname06
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/filewithanunnecesarilylongname07 b/tests/code/filesystem_dirents/assets/misc/filewithanunnecesarilylongname07
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/filewithanunnecesarilylongname08 b/tests/code/filesystem_dirents/assets/misc/filewithanunnecesarilylongname08
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/filewithanunnecesarilylongname09 b/tests/code/filesystem_dirents/assets/misc/filewithanunnecesarilylongname09
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/filewithanunnecesarilylongname10 b/tests/code/filesystem_dirents/assets/misc/filewithanunnecesarilylongname10
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/filewithanunnecesarilylongname11 b/tests/code/filesystem_dirents/assets/misc/filewithanunnecesarilylongname11
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/filewithanunnecesarilylongname12 b/tests/code/filesystem_dirents/assets/misc/filewithanunnecesarilylongname12
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/filewithanunnecesarilylongname13 b/tests/code/filesystem_dirents/assets/misc/filewithanunnecesarilylongname13
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/filewithanunnecesarilylongname14 b/tests/code/filesystem_dirents/assets/misc/filewithanunnecesarilylongname14
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/filewithanunnecesarilylongname15 b/tests/code/filesystem_dirents/assets/misc/filewithanunnecesarilylongname15
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/filewithanunnecesarilylongname16 b/tests/code/filesystem_dirents/assets/misc/filewithanunnecesarilylongname16
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/filewithanunnecesarilylongname17 b/tests/code/filesystem_dirents/assets/misc/filewithanunnecesarilylongname17
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/filewithanunnecesarilylongname18 b/tests/code/filesystem_dirents/assets/misc/filewithanunnecesarilylongname18
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/filewithanunnecesarilylongname19 b/tests/code/filesystem_dirents/assets/misc/filewithanunnecesarilylongname19
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/filewithanunnecesarilylongname20 b/tests/code/filesystem_dirents/assets/misc/filewithanunnecesarilylongname20
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/filewithanunnecesarilylongname21 b/tests/code/filesystem_dirents/assets/misc/filewithanunnecesarilylongname21
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/filewithanunnecesarilylongname22 b/tests/code/filesystem_dirents/assets/misc/filewithanunnecesarilylongname22
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/filewithanunnecesarilylongname23 b/tests/code/filesystem_dirents/assets/misc/filewithanunnecesarilylongname23
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/filewithanunnecesarilylongname24 b/tests/code/filesystem_dirents/assets/misc/filewithanunnecesarilylongname24
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/filewithanunnecesarilylongname25 b/tests/code/filesystem_dirents/assets/misc/filewithanunnecesarilylongname25
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/filewithanunnecesarilylongname26 b/tests/code/filesystem_dirents/assets/misc/filewithanunnecesarilylongname26
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/filewithanunnecesarilylongname27 b/tests/code/filesystem_dirents/assets/misc/filewithanunnecesarilylongname27
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/filewithanunnecesarilylongname28 b/tests/code/filesystem_dirents/assets/misc/filewithanunnecesarilylongname28
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/filewithanunnecesarilylongname29 b/tests/code/filesystem_dirents/assets/misc/filewithanunnecesarilylongname29
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/filewithanunnecesarilylongname30 b/tests/code/filesystem_dirents/assets/misc/filewithanunnecesarilylongname30
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/filewithanunnecesarilylongname31 b/tests/code/filesystem_dirents/assets/misc/filewithanunnecesarilylongname31
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/filewithanunnecesarilylongname32 b/tests/code/filesystem_dirents/assets/misc/filewithanunnecesarilylongname32
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/filewithanunnecesarilylongname33 b/tests/code/filesystem_dirents/assets/misc/filewithanunnecesarilylongname33
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/filewithanunnecesarilylongname34 b/tests/code/filesystem_dirents/assets/misc/filewithanunnecesarilylongname34
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/filewithanunnecesarilylongname35 b/tests/code/filesystem_dirents/assets/misc/filewithanunnecesarilylongname35
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/filewithanunnecesarilylongname36 b/tests/code/filesystem_dirents/assets/misc/filewithanunnecesarilylongname36
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/filewithanunnecesarilylongname37 b/tests/code/filesystem_dirents/assets/misc/filewithanunnecesarilylongname37
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/filewithanunnecesarilylongname38 b/tests/code/filesystem_dirents/assets/misc/filewithanunnecesarilylongname38
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/filewithanunnecesarilylongname39 b/tests/code/filesystem_dirents/assets/misc/filewithanunnecesarilylongname39
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/filewithanunnecesarilylongname40 b/tests/code/filesystem_dirents/assets/misc/filewithanunnecesarilylongname40
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/filewithanunnecesarilylongname41 b/tests/code/filesystem_dirents/assets/misc/filewithanunnecesarilylongname41
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/filewithanunnecesarilylongname42 b/tests/code/filesystem_dirents/assets/misc/filewithanunnecesarilylongname42
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/filewithanunnecesarilylongname43 b/tests/code/filesystem_dirents/assets/misc/filewithanunnecesarilylongname43
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/filewithanunnecesarilylongname44 b/tests/code/filesystem_dirents/assets/misc/filewithanunnecesarilylongname44
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/filewithanunnecesarilylongname45 b/tests/code/filesystem_dirents/assets/misc/filewithanunnecesarilylongname45
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/filewithanunnecesarilylongname46 b/tests/code/filesystem_dirents/assets/misc/filewithanunnecesarilylongname46
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/filewithanunnecesarilylongname47 b/tests/code/filesystem_dirents/assets/misc/filewithanunnecesarilylongname47
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/filewithanunnecesarilylongname48 b/tests/code/filesystem_dirents/assets/misc/filewithanunnecesarilylongname48
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/filewithanunnecesarilylongname49 b/tests/code/filesystem_dirents/assets/misc/filewithanunnecesarilylongname49
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/filewithanunnecesarilylongname50 b/tests/code/filesystem_dirents/assets/misc/filewithanunnecesarilylongname50
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/filewithaverylongname01 b/tests/code/filesystem_dirents/assets/misc/filewithaverylongname01
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/filewithaverylongname02 b/tests/code/filesystem_dirents/assets/misc/filewithaverylongname02
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/filewithaverylongname03 b/tests/code/filesystem_dirents/assets/misc/filewithaverylongname03
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/filewithaverylongname04 b/tests/code/filesystem_dirents/assets/misc/filewithaverylongname04
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/filewithaverylongname05 b/tests/code/filesystem_dirents/assets/misc/filewithaverylongname05
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/filewithaverylongname06 b/tests/code/filesystem_dirents/assets/misc/filewithaverylongname06
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/filewithaverylongname07 b/tests/code/filesystem_dirents/assets/misc/filewithaverylongname07
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/filewithaverylongname08 b/tests/code/filesystem_dirents/assets/misc/filewithaverylongname08
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/filewithaverylongname09 b/tests/code/filesystem_dirents/assets/misc/filewithaverylongname09
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/filewithaverylongname10 b/tests/code/filesystem_dirents/assets/misc/filewithaverylongname10
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/filewithaverylongname11 b/tests/code/filesystem_dirents/assets/misc/filewithaverylongname11
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/filewithaverylongname12 b/tests/code/filesystem_dirents/assets/misc/filewithaverylongname12
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/filewithaverylongname13 b/tests/code/filesystem_dirents/assets/misc/filewithaverylongname13
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/filewithaverylongname14 b/tests/code/filesystem_dirents/assets/misc/filewithaverylongname14
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/filewithaverylongname15 b/tests/code/filesystem_dirents/assets/misc/filewithaverylongname15
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/filewithaverylongname16 b/tests/code/filesystem_dirents/assets/misc/filewithaverylongname16
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/filewithaverylongname17 b/tests/code/filesystem_dirents/assets/misc/filewithaverylongname17
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/filewithaverylongname18 b/tests/code/filesystem_dirents/assets/misc/filewithaverylongname18
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/filewithaverylongname19 b/tests/code/filesystem_dirents/assets/misc/filewithaverylongname19
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/filewithaverylongname20 b/tests/code/filesystem_dirents/assets/misc/filewithaverylongname20
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/filewithaverylongname21 b/tests/code/filesystem_dirents/assets/misc/filewithaverylongname21
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/filewithaverylongname22 b/tests/code/filesystem_dirents/assets/misc/filewithaverylongname22
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/filewithaverylongname23 b/tests/code/filesystem_dirents/assets/misc/filewithaverylongname23
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/filewithaverylongname24 b/tests/code/filesystem_dirents/assets/misc/filewithaverylongname24
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/filewithaverylongname25 b/tests/code/filesystem_dirents/assets/misc/filewithaverylongname25
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/filewithaverylongname26 b/tests/code/filesystem_dirents/assets/misc/filewithaverylongname26
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/filewithaverylongname27 b/tests/code/filesystem_dirents/assets/misc/filewithaverylongname27
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/filewithaverylongname28 b/tests/code/filesystem_dirents/assets/misc/filewithaverylongname28
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/filewithaverylongname29 b/tests/code/filesystem_dirents/assets/misc/filewithaverylongname29
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/filewithaverylongname30 b/tests/code/filesystem_dirents/assets/misc/filewithaverylongname30
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/filewithaverylongname31 b/tests/code/filesystem_dirents/assets/misc/filewithaverylongname31
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/filewithaverylongname32 b/tests/code/filesystem_dirents/assets/misc/filewithaverylongname32
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/filewithaverylongname33 b/tests/code/filesystem_dirents/assets/misc/filewithaverylongname33
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/filewithaverylongname34 b/tests/code/filesystem_dirents/assets/misc/filewithaverylongname34
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/filewithaverylongname35 b/tests/code/filesystem_dirents/assets/misc/filewithaverylongname35
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/filewithaverylongname36 b/tests/code/filesystem_dirents/assets/misc/filewithaverylongname36
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/filewithaverylongname37 b/tests/code/filesystem_dirents/assets/misc/filewithaverylongname37
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/filewithaverylongname38 b/tests/code/filesystem_dirents/assets/misc/filewithaverylongname38
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/filewithaverylongname39 b/tests/code/filesystem_dirents/assets/misc/filewithaverylongname39
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/filewithaverylongname40 b/tests/code/filesystem_dirents/assets/misc/filewithaverylongname40
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/filewithaverylongname41 b/tests/code/filesystem_dirents/assets/misc/filewithaverylongname41
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/filewithaverylongname42 b/tests/code/filesystem_dirents/assets/misc/filewithaverylongname42
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/filewithaverylongname43 b/tests/code/filesystem_dirents/assets/misc/filewithaverylongname43
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/filewithaverylongname44 b/tests/code/filesystem_dirents/assets/misc/filewithaverylongname44
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/filewithaverylongname45 b/tests/code/filesystem_dirents/assets/misc/filewithaverylongname45
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/filewithaverylongname46 b/tests/code/filesystem_dirents/assets/misc/filewithaverylongname46
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/filewithaverylongname47 b/tests/code/filesystem_dirents/assets/misc/filewithaverylongname47
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/filewithaverylongname48 b/tests/code/filesystem_dirents/assets/misc/filewithaverylongname48
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/filewithaverylongname49 b/tests/code/filesystem_dirents/assets/misc/filewithaverylongname49
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/filewithaverylongname50 b/tests/code/filesystem_dirents/assets/misc/filewithaverylongname50
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/filewithunnecesarilylongnamejusttomesswitheveryone01 b/tests/code/filesystem_dirents/assets/misc/filewithunnecesarilylongnamejusttomesswitheveryone01
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/filewithunnecesarilylongnamejusttomesswitheveryone02 b/tests/code/filesystem_dirents/assets/misc/filewithunnecesarilylongnamejusttomesswitheveryone02
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/filewithunnecesarilylongnamejusttomesswitheveryone03 b/tests/code/filesystem_dirents/assets/misc/filewithunnecesarilylongnamejusttomesswitheveryone03
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/filewithunnecesarilylongnamejusttomesswitheveryone04 b/tests/code/filesystem_dirents/assets/misc/filewithunnecesarilylongnamejusttomesswitheveryone04
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/filewithunnecesarilylongnamejusttomesswitheveryone05 b/tests/code/filesystem_dirents/assets/misc/filewithunnecesarilylongnamejusttomesswitheveryone05
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/filewithunnecesarilylongnamejusttomesswitheveryone06 b/tests/code/filesystem_dirents/assets/misc/filewithunnecesarilylongnamejusttomesswitheveryone06
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/filewithunnecesarilylongnamejusttomesswitheveryone07 b/tests/code/filesystem_dirents/assets/misc/filewithunnecesarilylongnamejusttomesswitheveryone07
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/filewithunnecesarilylongnamejusttomesswitheveryone08 b/tests/code/filesystem_dirents/assets/misc/filewithunnecesarilylongnamejusttomesswitheveryone08
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/filewithunnecesarilylongnamejusttomesswitheveryone09 b/tests/code/filesystem_dirents/assets/misc/filewithunnecesarilylongnamejusttomesswitheveryone09
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/filewithunnecesarilylongnamejusttomesswitheveryone10 b/tests/code/filesystem_dirents/assets/misc/filewithunnecesarilylongnamejusttomesswitheveryone10
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/filewithunnecesarilylongnamejusttomesswitheveryone11 b/tests/code/filesystem_dirents/assets/misc/filewithunnecesarilylongnamejusttomesswitheveryone11
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/filewithunnecesarilylongnamejusttomesswitheveryone12 b/tests/code/filesystem_dirents/assets/misc/filewithunnecesarilylongnamejusttomesswitheveryone12
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/filewithunnecesarilylongnamejusttomesswitheveryone13 b/tests/code/filesystem_dirents/assets/misc/filewithunnecesarilylongnamejusttomesswitheveryone13
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/filewithunnecesarilylongnamejusttomesswitheveryone14 b/tests/code/filesystem_dirents/assets/misc/filewithunnecesarilylongnamejusttomesswitheveryone14
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/filewithunnecesarilylongnamejusttomesswitheveryone15 b/tests/code/filesystem_dirents/assets/misc/filewithunnecesarilylongnamejusttomesswitheveryone15
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/filewithunnecesarilylongnamejusttomesswitheveryone16 b/tests/code/filesystem_dirents/assets/misc/filewithunnecesarilylongnamejusttomesswitheveryone16
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/filewithunnecesarilylongnamejusttomesswitheveryone17 b/tests/code/filesystem_dirents/assets/misc/filewithunnecesarilylongnamejusttomesswitheveryone17
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/filewithunnecesarilylongnamejusttomesswitheveryone18 b/tests/code/filesystem_dirents/assets/misc/filewithunnecesarilylongnamejusttomesswitheveryone18
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/filewithunnecesarilylongnamejusttomesswitheveryone19 b/tests/code/filesystem_dirents/assets/misc/filewithunnecesarilylongnamejusttomesswitheveryone19
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/filewithunnecesarilylongnamejusttomesswitheveryone20 b/tests/code/filesystem_dirents/assets/misc/filewithunnecesarilylongnamejusttomesswitheveryone20
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/filewithunnecesarilylongnamejusttomesswitheveryone21 b/tests/code/filesystem_dirents/assets/misc/filewithunnecesarilylongnamejusttomesswitheveryone21
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/filewithunnecesarilylongnamejusttomesswitheveryone22 b/tests/code/filesystem_dirents/assets/misc/filewithunnecesarilylongnamejusttomesswitheveryone22
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/filewithunnecesarilylongnamejusttomesswitheveryone23 b/tests/code/filesystem_dirents/assets/misc/filewithunnecesarilylongnamejusttomesswitheveryone23
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/filewithunnecesarilylongnamejusttomesswitheveryone24 b/tests/code/filesystem_dirents/assets/misc/filewithunnecesarilylongnamejusttomesswitheveryone24
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/filewithunnecesarilylongnamejusttomesswitheveryone25 b/tests/code/filesystem_dirents/assets/misc/filewithunnecesarilylongnamejusttomesswitheveryone25
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/filewithunnecesarilylongnamejusttomesswitheveryone26 b/tests/code/filesystem_dirents/assets/misc/filewithunnecesarilylongnamejusttomesswitheveryone26
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/filewithunnecesarilylongnamejusttomesswitheveryone27 b/tests/code/filesystem_dirents/assets/misc/filewithunnecesarilylongnamejusttomesswitheveryone27
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/filewithunnecesarilylongnamejusttomesswitheveryone28 b/tests/code/filesystem_dirents/assets/misc/filewithunnecesarilylongnamejusttomesswitheveryone28
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/filewithunnecesarilylongnamejusttomesswitheveryone29 b/tests/code/filesystem_dirents/assets/misc/filewithunnecesarilylongnamejusttomesswitheveryone29
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/filewithunnecesarilylongnamejusttomesswitheveryone30 b/tests/code/filesystem_dirents/assets/misc/filewithunnecesarilylongnamejusttomesswitheveryone30
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/filewithunnecesarilylongnamejusttomesswitheveryone31 b/tests/code/filesystem_dirents/assets/misc/filewithunnecesarilylongnamejusttomesswitheveryone31
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/filewithunnecesarilylongnamejusttomesswitheveryone32 b/tests/code/filesystem_dirents/assets/misc/filewithunnecesarilylongnamejusttomesswitheveryone32
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/filewithunnecesarilylongnamejusttomesswitheveryone33 b/tests/code/filesystem_dirents/assets/misc/filewithunnecesarilylongnamejusttomesswitheveryone33
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/filewithunnecesarilylongnamejusttomesswitheveryone34 b/tests/code/filesystem_dirents/assets/misc/filewithunnecesarilylongnamejusttomesswitheveryone34
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/filewithunnecesarilylongnamejusttomesswitheveryone35 b/tests/code/filesystem_dirents/assets/misc/filewithunnecesarilylongnamejusttomesswitheveryone35
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/filewithunnecesarilylongnamejusttomesswitheveryone36 b/tests/code/filesystem_dirents/assets/misc/filewithunnecesarilylongnamejusttomesswitheveryone36
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/filewithunnecesarilylongnamejusttomesswitheveryone37 b/tests/code/filesystem_dirents/assets/misc/filewithunnecesarilylongnamejusttomesswitheveryone37
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/filewithunnecesarilylongnamejusttomesswitheveryone38 b/tests/code/filesystem_dirents/assets/misc/filewithunnecesarilylongnamejusttomesswitheveryone38
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/filewithunnecesarilylongnamejusttomesswitheveryone39 b/tests/code/filesystem_dirents/assets/misc/filewithunnecesarilylongnamejusttomesswitheveryone39
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/filewithunnecesarilylongnamejusttomesswitheveryone40 b/tests/code/filesystem_dirents/assets/misc/filewithunnecesarilylongnamejusttomesswitheveryone40
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/filewithunnecesarilylongnamejusttomesswitheveryone41 b/tests/code/filesystem_dirents/assets/misc/filewithunnecesarilylongnamejusttomesswitheveryone41
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/filewithunnecesarilylongnamejusttomesswitheveryone42 b/tests/code/filesystem_dirents/assets/misc/filewithunnecesarilylongnamejusttomesswitheveryone42
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/filewithunnecesarilylongnamejusttomesswitheveryone43 b/tests/code/filesystem_dirents/assets/misc/filewithunnecesarilylongnamejusttomesswitheveryone43
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/filewithunnecesarilylongnamejusttomesswitheveryone44 b/tests/code/filesystem_dirents/assets/misc/filewithunnecesarilylongnamejusttomesswitheveryone44
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/filewithunnecesarilylongnamejusttomesswitheveryone45 b/tests/code/filesystem_dirents/assets/misc/filewithunnecesarilylongnamejusttomesswitheveryone45
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/filewithunnecesarilylongnamejusttomesswitheveryone46 b/tests/code/filesystem_dirents/assets/misc/filewithunnecesarilylongnamejusttomesswitheveryone46
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/filewithunnecesarilylongnamejusttomesswitheveryone47 b/tests/code/filesystem_dirents/assets/misc/filewithunnecesarilylongnamejusttomesswitheveryone47
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/filewithunnecesarilylongnamejusttomesswitheveryone48 b/tests/code/filesystem_dirents/assets/misc/filewithunnecesarilylongnamejusttomesswitheveryone48
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/filewithunnecesarilylongnamejusttomesswitheveryone49 b/tests/code/filesystem_dirents/assets/misc/filewithunnecesarilylongnamejusttomesswitheveryone49
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/filewithunnecesarilylongnamejusttomesswitheveryone50 b/tests/code/filesystem_dirents/assets/misc/filewithunnecesarilylongnamejusttomesswitheveryone50
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/assets/misc/thisfilewillbesomewhere b/tests/code/filesystem_dirents/assets/misc/thisfilewillbesomewhere
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/code/calculator.cpp b/tests/code/filesystem_dirents/code/calculator.cpp
new file mode 100644
index 00000000..54376b1b
--- /dev/null
+++ b/tests/code/filesystem_dirents/code/calculator.cpp
@@ -0,0 +1,261 @@
+#include "calculator.h"
+
+#include "log.h"
+
+/**
+ * Do not update those routines!
+ * Those should simulate how PS4 handles maths
+ */
+
+void calculate_pfs_read(OrbisInternals::DirentCombination* spec, s64 size, s64 offset, u64 count) {
+ spec->read_size = count;
+ spec->read_offset = offset;
+ spec->expected_lseek = offset;
+ spec->expected_basep = -1;
+ spec->meta_dirent_start = 0; // unused, always equal to lseek-calculated offset
+ spec->expected_result = 0;
+ spec->expected_end_position = offset;
+ spec->expected_errno = 0;
+
+ spec->expected_lseek = calculate_lseek(size, 0, offset, 0, &spec->expected_errno);
+ s64 new_offset = spec->expected_lseek >= 0 ? spec->expected_lseek : 0;
+ spec->expected_basep = new_offset;
+ spec->meta_dirent_start = new_offset;
+
+ // if (count > 0x7ffff000) {
+ // spec->expected_basep = new_offset;
+ // spec->expected_result = einval_int;
+ // spec->expected_end_position = (new_offset >= 0) ? new_offset : 0;
+ // spec->expected_errno = EINVAL;
+ // return;
+ // }
+
+ spec->expected_errno = 0;
+
+ if (new_offset > size) return;
+
+ spec->expected_basep = new_offset;
+ spec->expected_result = std::min(size - spec->expected_basep, static_cast(count));
+ spec->expected_end_position = spec->expected_basep + spec->expected_result;
+}
+
+void calculate_normal_read(OrbisInternals::DirentCombination* spec, s64 size, s64 offset, u64 count) {
+ spec->read_size = count;
+ spec->read_offset = offset;
+ spec->expected_lseek = offset;
+ spec->expected_basep = -1;
+ spec->meta_dirent_start = 0; // unused, always equal to lseek-calculated offset
+ spec->expected_result = 0;
+ spec->expected_end_position = offset;
+ spec->expected_errno = 0;
+
+ spec->expected_lseek = calculate_lseek(size, 0, offset, 0, &spec->expected_errno);
+ s64 new_offset = spec->expected_lseek >= 0 ? spec->expected_lseek : 0;
+ spec->expected_basep = new_offset;
+ spec->meta_dirent_start = new_offset;
+
+ // if (count > 0x7ffff000) {
+ // spec->expected_basep = new_offset;
+ // spec->expected_result = einval_int;
+ // spec->expected_end_position = (new_offset >= 0) ? new_offset : 0;
+ // spec->expected_errno = EINVAL;
+ // return;
+ // }
+
+ if (offset > size) {
+ spec->expected_lseek = new_offset;
+ return;
+ }
+
+ spec->expected_basep = new_offset;
+ spec->expected_result = std::min(size - spec->expected_basep, static_cast(count));
+ spec->expected_end_position = new_offset + spec->expected_result;
+}
+
+// -1 on not found
+// this returns relative offset to starting position
+s64 nearest_dirent(const char* buffer, s64 size, s64 offset) {
+ // max size is 272, last 23 bytes are never starting a dirent
+
+ s64 offset_adj = ISAL(offset, 8) ? offset : ALUP(offset, 8);
+ s64 max_advance = std::min(size - offset_adj, s64(272));
+ if (max_advance < 24) return -2;
+
+ s64 status {};
+
+ for (s64 out_offset = offset_adj; out_offset <= offset_adj + max_advance; out_offset += 8) {
+ const OrbisInternals::FolderDirent* tested_dirent = reinterpret_cast(buffer + out_offset);
+ status = validate_pfs_getdirentries_dirent(tested_dirent);
+
+ if (status < 0) continue;
+
+ return out_offset - offset;
+ }
+
+ return status;
+}
+
+void calculate_pfs_getdirentries(OrbisInternals::DirentCombination* spec, const char* buffer, s64 size, s64 offset, u64 count) {
+ spec->read_size = count;
+ spec->read_offset = offset;
+ spec->expected_basep = -1;
+ spec->meta_dirent_start = 0; // unused, always equal to lseek-calculated offset
+ spec->expected_result = 0;
+ spec->expected_end_position = 0;
+ spec->expected_errno = 0;
+
+ spec->expected_lseek = calculate_lseek(size, 0, offset, 0, &spec->expected_errno);
+ s64 new_offset = spec->expected_lseek >= 0 ? spec->expected_lseek : 0;
+ spec->meta_dirent_start = new_offset;
+
+ s64 apparent_end = new_offset + count;
+ s64 apparent_end_down = ALDN(apparent_end, 512);
+ s64 file_offset_down = ALDN(new_offset, 512);
+ s64 directory_size = ISAL(size, 0x10000) ? size : ALUP(size, 0x10000);
+
+ // within the same sector, no 512b alignment inbetween
+ if (apparent_end_down <= file_offset_down) {
+ spec->expected_basep = -1;
+ spec->expected_result = s64(einval_int);
+ spec->expected_end_position = new_offset;
+ spec->expected_errno = EINVAL;
+ // LogError("Dent align apend-off");
+ return;
+ }
+
+ if (new_offset >= directory_size) {
+ spec->expected_basep = new_offset;
+ spec->expected_result = 0;
+ spec->expected_end_position = new_offset;
+ spec->expected_errno = 0;
+ // LogError("Dent oob");
+ return;
+ }
+
+ if (new_offset >= size) {
+ spec->expected_basep = new_offset;
+ spec->expected_result = 0;
+ spec->expected_end_position = directory_size;
+ spec->expected_errno = 0;
+ return;
+ }
+
+ // we can now assume that offset is always smaller than size
+ s64 dirent_offset = nearest_dirent(buffer, size, new_offset);
+
+ if (dirent_offset < 0) {
+ // highly unlikely but you never know
+ spec->expected_basep = new_offset;
+ spec->expected_result = 0;
+ spec->expected_end_position = directory_size;
+ spec->expected_errno = 0;
+ return;
+ };
+
+ s64 bytes_written = 0;
+ s64 buffer_position = dirent_offset; // this is independent from descriptor offset
+ s64 allowed_count = std::min(apparent_end_down - new_offset, s64(count));
+ allowed_count = std::min(allowed_count, size - new_offset);
+
+ if (allowed_count <= 0) {
+ spec->expected_basep = new_offset;
+ spec->expected_result = 0;
+ spec->expected_end_position = new_offset;
+ spec->expected_errno = 0;
+ return;
+ }
+
+ while (buffer_position < size) {
+ const OrbisInternals::FolderDirent* pfs_dirent = reinterpret_cast(buffer + buffer_position);
+
+ if ((bytes_written + pfs_dirent->d_reclen) > allowed_count) {
+ break;
+ }
+
+ if (pfs_dirent->d_reclen == 0) {
+ // we're probably in the transition zone between sectors
+ buffer_position = nearest_dirent(buffer, size, buffer_position);
+ continue;
+ }
+
+ // reclen for both is the same despite difference in var sizes, extra 0s are padded after
+ // the name
+ bytes_written += pfs_dirent->d_reclen;
+ buffer_position += pfs_dirent->d_reclen;
+ }
+
+ spec->expected_basep = new_offset;
+ spec->meta_dirent_start = new_offset + dirent_offset;
+ spec->expected_result = bytes_written;
+ spec->expected_end_position = ((buffer_position + dirent_offset) >= size) ? directory_size : static_cast(new_offset + bytes_written);
+ spec->expected_errno = 0;
+}
+
+void calculate_normal_getdirentries(OrbisInternals::DirentCombination* spec, s64 size, s64 offset, u64 count) {
+ spec->read_size = count;
+ spec->read_offset = offset;
+ spec->expected_basep = -1; // DON'T TOUCH. getdirentries sets it after non-0 amount of data to read
+ spec->meta_dirent_start = 0; // unused, always equal to lseek-calculated offset
+ spec->expected_result = 0;
+ spec->expected_end_position = 0;
+ spec->expected_errno = 0;
+
+ spec->expected_lseek = calculate_lseek(size, 0, offset, 0, &spec->expected_errno);
+ s64 new_offset = spec->expected_lseek >= 0 ? spec->expected_lseek : 0;
+ spec->meta_dirent_start = new_offset;
+ spec->expected_end_position = new_offset;
+
+ s64 apparent_end = new_offset + count;
+ s64 apparent_end_down = ALDN(apparent_end, 512);
+ s64 file_offset_down = ALDN(new_offset, 512);
+
+ // within the same sector, no 512b alignment inbetween
+ if (apparent_end_down <= file_offset_down) {
+ spec->expected_result = s64(einval_int);
+ spec->expected_errno = EINVAL;
+ return;
+ }
+
+ spec->expected_basep = new_offset;
+
+ if (new_offset >= size) {
+ spec->expected_result = 0;
+ spec->expected_errno = 0;
+ return;
+ }
+
+ // we can now assume that offset is always smaller than size
+ s64 allowed_count = std::min(u64(apparent_end_down - new_offset), count);
+ allowed_count = std::min(allowed_count, size - new_offset);
+ spec->expected_result = allowed_count;
+ spec->expected_end_position = static_cast(spec->expected_basep + allowed_count);
+ spec->expected_errno = 0;
+}
+
+s64 calculate_lseek(s64 directory_size, s64 file_offset, s64 offset, int whence, int* errno_ret) {
+ *errno_ret = 0;
+
+ if (whence < 0 || whence > 4) {
+ if (nullptr != errno_ret) *errno_ret = EINVAL;
+ return einval_int;
+ }
+ if (whence == 3 || whence == 4) {
+ if (nullptr != errno_ret) *errno_ret = ENOTTY;
+ return enotty_int;
+ }
+
+ s64 target_offset {};
+ s64 offset_modificator = //((0 == whence)) * 0 + // there are no other options really lol
+ ((1 == whence) * file_offset) + //
+ ((2 == whence) * directory_size);
+ if (__builtin_add_overflow(offset, offset_modificator, &target_offset)) {
+ if (nullptr != errno_ret) *errno_ret = EOVERFLOW;
+ return eoverflow_int;
+ }
+ if (target_offset < 0) {
+ if (nullptr != errno_ret) *errno_ret = EINVAL;
+ return einval_int;
+ }
+
+ return target_offset;
+}
\ No newline at end of file
diff --git a/tests/code/filesystem_dirents/code/calculator.h b/tests/code/filesystem_dirents/code/calculator.h
new file mode 100644
index 00000000..c5489fea
--- /dev/null
+++ b/tests/code/filesystem_dirents/code/calculator.h
@@ -0,0 +1,16 @@
+#ifndef CALCULATOR_H
+#define CALCULATOR_H
+
+#pragma once
+
+#include "fs_test.h"
+
+void calculate_pfs_read(OrbisInternals::DirentCombination* spec, s64 size, s64 offset, u64 count);
+void calculate_normal_read(OrbisInternals::DirentCombination* spec, s64 size, s64 offset, u64 count);
+
+void calculate_pfs_getdirentries(OrbisInternals::DirentCombination* spec, const char* buffer, s64 size, s64 offset, u64 count);
+void calculate_normal_getdirentries(OrbisInternals::DirentCombination* spec, s64 size, s64 offset, u64 count);
+
+s64 calculate_lseek(s64 directory_size, s64 file_offset, s64 offset, int whence, int* errno_ret = nullptr);
+
+#endif // CALCULATOR_H
\ No newline at end of file
diff --git a/tests/code/filesystem_dirents/code/fs_test.cpp b/tests/code/filesystem_dirents/code/fs_test.cpp
new file mode 100755
index 00000000..a8fc8aa7
--- /dev/null
+++ b/tests/code/filesystem_dirents/code/fs_test.cpp
@@ -0,0 +1,1041 @@
+#include "fs_test.h"
+
+#include "calculator.h"
+#include "fs_test_constants.h"
+#include "orbis/UserService.h"
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+namespace fs = std::filesystem;
+namespace oi = OrbisInternals;
+
+s64 undump_file(const char* path, std::vector& data) {
+ std::ifstream f(path, std::ios::binary);
+ f.seekg(0, std::ios::end);
+ auto size = f.tellg();
+ f.seekg(0, std::ios::beg);
+ data.resize(size);
+ if (!f.read(data.data(), size)) {
+ f.close();
+ return -1;
+ }
+ f.close();
+ return size;
+}
+
+// config
+const char* config_path = "/data/ender_conf";
+const char* config_path_nofuzz = "/data/ender_conf/nofuzz";
+// paths
+const char* input_pfs = "/app0/assets/misc";
+const char* enderman_root = "/data/enderman/";
+const char* input_normal = "/data/enderman/clone";
+const char* output_dir = "/data/enderman/dump";
+const char* output_pfs_read = "/data/enderman/dump/pfs_read.bin";
+const char* output_pfs_getdirentries = "/data/enderman/dump/pfs_getdirent.bin";
+const char* output_normal_read = "/data/enderman/dump/normal_read.bin";
+const char* output_normal_getdirentries = "/data/enderman/dump/normal_getdirent.bin";
+
+static bool conf_opt_nofuzz {};
+
+TEST_GROUP (DirentTests) {
+ std::vector* open_fd {};
+
+ void add_fd(int fd) {
+ if (nullptr == open_fd) return;
+ open_fd->emplace_back(fd);
+ }
+
+ TEST_SETUP() {
+ open_fd = new std::vector;
+ }
+
+ TEST_TEARDOWN() {
+ for (const auto& fd: *open_fd) {
+ if (sceKernelClose(fd) < 0) continue;
+ LogWarning("Closed leftover fd:", fd);
+ }
+ delete open_fd;
+ open_fd = nullptr;
+ }
+};
+
+TEST(DirentTests, PFSGetdirentriesFuzz) {
+ LogTest("<<<< PFS getdirentries fuzzing test >>>>");
+ if (conf_opt_nofuzz) {
+ Log("Skipped");
+ return;
+ }
+ LogTest("Note: Only first 20 bad entries are shown");
+ LogTest("Note: This may take a while");
+ LogWarning("Note: This test does not cover entire range of offsets"); // TL;DR
+ LogWarning("Note: TL;DR console hard-crashes if offset is too high.");
+ LogWarning("Note: the exact value is yet to be found");
+
+ /**
+ * In fact there *is* a certain limitation.
+ * It has been tested that big enough offsets can eventually crash the console
+ * Why is it? Dunno. Could be random, could be fixed.
+ * With large values (>32bit) test may go through a couple of times and then shutdown/crash the console.
+ * It also always fails when the test ends, and sometimes it throws a page fault in kernelspace (???)
+ * Best part is that lseek allows it first, but only pfs getdirentries exhibits this behaviour
+ */
+
+ if (conf_opt_nofuzz) {
+ Log("Skipped");
+ return;
+ }
+
+ int fd {};
+ s64 tbr {};
+ fuck buffer;
+ fuck master_buffer;
+ const s64 master_length = undump_file(output_pfs_getdirentries, master_buffer);
+ oi::DirentCombination calc {};
+ s64 basep {};
+ s64 basep_canary {};
+ s64 end_ptr_position {};
+ int hardware_errno {};
+
+ LogTest("Master PFS getdirentries length is", master_length, ",", "testing", FUZZ_MAX_ITERATIONS, "samples", ",", "max", FUZZ_MAX_FAILURES,
+ "bad returns are shown");
+
+ srand(time(nullptr));
+
+ s64 sample_num {};
+ s64 failed_samples {};
+
+ fd = sceKernelOpen(input_pfs, O_DIRECTORY, 0777);
+ add_fd(fd);
+
+ for (sample_num = 0; sample_num < FUZZ_MAX_ITERATIONS; sample_num++) {
+ s64 spec_offset = get_fuzz() % (master_length + 1024); // not too far or we might crash the console
+ s64 spec_size = rand() % (master_length + 1024);
+
+ basep = DEFAULT_64;
+ basep_canary = basep;
+
+ calculate_pfs_getdirentries(&calc, master_buffer.data(), master_length, spec_offset, spec_size);
+
+ buffer.resize(master_length);
+ std::fill(buffer.begin(), buffer.end(), DEFAULT_8);
+
+ sceKernelLseek(fd, calc.read_offset, 0);
+ errno = 0;
+ tbr = sceKernelGetdirentries(fd, buffer.data(), calc.read_size, &basep);
+ hardware_errno = errno;
+ end_ptr_position = sceKernelLseek(fd, 0, 1);
+
+ // -1 means no change
+ if (calc.expected_basep == -1) calc.expected_basep = basep_canary;
+
+ if (s64 diff_idx = compare_data_dump(master_buffer, buffer, tbr, calc.meta_dirent_start); diff_idx <= 0) {
+ if (++failed_samples > FUZZ_MAX_FAILURES) continue;
+ LogError(calc.read_size, calc.read_offset, "->", calc.expected_basep, val_or_err(calc.expected_result), calc.expected_end_position, calc.expected_errno,
+ "->", basep, val_or_err(tbr), end_ptr_position, hardware_errno, to_hex_string(buffer.data(), 16, ""));
+ LogError("Inconsistent read at/idx", calc.read_offset - diff_idx, -diff_idx);
+ if (s64 diff = master_length - calc.meta_dirent_start; diff > 0)
+ LogError("Global dump:", to_hex_string(master_buffer.data() + calc.meta_dirent_start - diff_idx, diff < 32 ? diff : 32, ""));
+ if (tbr > 0) LogError("Recent dump:", to_hex_string(buffer.data() - diff_idx, tbr < 32 ? tbr : 32, ""));
+ }
+ if (calc.expected_basep != basep || calc.expected_result != tbr || calc.expected_end_position != end_ptr_position ||
+ calc.expected_errno != hardware_errno) {
+ if (++failed_samples >= FUZZ_MAX_FAILURES) continue;
+ LogError(calc.read_size, calc.read_offset, "->", calc.expected_basep, val_or_err(calc.expected_result), calc.expected_end_position, calc.expected_errno,
+ "->", basep, val_or_err(tbr), end_ptr_position, hardware_errno, to_hex_string(buffer.data(), 16, ""));
+ }
+ }
+
+ sceKernelClose(fd);
+
+ double fail_rate = 100.0f * failed_samples / sample_num;
+ if (fail_rate == 0.0f) {
+ LogSuccess("Fuzzing passed!");
+ return;
+ }
+ Log("Failure rate%:", fail_rate, "(", failed_samples, "/", sample_num, "failed )");
+}
+
+TEST(DirentTests, NormalGetdirentriesFuzz) {
+ LogTest("<<<< Normal getdirentries fuzzing test >>>>");
+ if (conf_opt_nofuzz) {
+ Log("Skipped");
+ return;
+ }
+ LogTest("Note: Only first 20 bad entries are shown");
+ LogTest("Note: This may take a while");
+
+ int fd {};
+ s64 tbr {};
+ fuck buffer;
+ fuck master_buffer;
+ const s64 master_length = undump_file(output_normal_getdirentries, master_buffer);
+ oi::DirentCombination calc {};
+ s64 basep {};
+ s64 basep_canary {};
+ s64 end_ptr_position {};
+ int hardware_errno {};
+
+ LogTest("Master Normal getdirentries length is", master_length, ",", "testing", FUZZ_MAX_ITERATIONS, "samples", ",", "max", FUZZ_MAX_FAILURES,
+ "bad returns are shown");
+
+ srand(time(nullptr));
+
+ s64 sample_num {};
+ s64 failed_samples {};
+ for (sample_num = 0; sample_num < FUZZ_MAX_ITERATIONS; sample_num++) {
+ s64 spec_offset = get_fuzz();
+ s64 spec_size = rand() % (master_length + 1024);
+
+ basep = DEFAULT_64;
+ basep_canary = basep;
+
+ calculate_normal_getdirentries(&calc, master_length, spec_offset, spec_size);
+
+ buffer.resize(spec_size);
+ std::fill(buffer.begin(), buffer.end(), DEFAULT_8);
+
+ fd = sceKernelOpen(input_normal, O_DIRECTORY, 0777);
+ sceKernelLseek(fd, calc.read_offset, 0);
+ errno = 0;
+ tbr = sceKernelGetdirentries(fd, buffer.data(), calc.read_size, &basep);
+ hardware_errno = errno;
+ end_ptr_position = sceKernelLseek(fd, 0, 1);
+ sceKernelClose(fd);
+
+ // -1 means no change
+ if (calc.expected_basep == -1) calc.expected_basep = basep_canary;
+
+ if (s64 diff_idx = compare_data_dump(master_buffer, buffer, tbr, calc.meta_dirent_start); diff_idx <= 0) {
+ if (++failed_samples > FUZZ_MAX_FAILURES) continue;
+ LogError(calc.read_size, calc.read_offset, "->", calc.expected_basep, val_or_err(calc.expected_result), calc.expected_end_position, calc.expected_errno,
+ "->", basep, val_or_err(tbr), end_ptr_position, hardware_errno, to_hex_string(buffer.data(), 16, ""));
+ LogError("Inconsistent read at/idx", calc.read_offset - diff_idx, -diff_idx);
+ if (s64 diff = master_length - calc.meta_dirent_start; diff > 0)
+ LogError("Global dump:", to_hex_string(master_buffer.data() + calc.meta_dirent_start - diff_idx, diff < 32 ? diff : 32, ""));
+ if (tbr > 0) LogError("Recent dump:", to_hex_string(buffer.data() - diff_idx, tbr < 32 ? tbr : 32, ""));
+ }
+
+ if (calc.expected_basep != basep || calc.expected_result != tbr || calc.expected_end_position != end_ptr_position ||
+ calc.expected_errno != hardware_errno) {
+ if (++failed_samples >= FUZZ_MAX_FAILURES) continue;
+ LogError(calc.read_size, calc.read_offset, "->", calc.expected_basep, val_or_err(calc.expected_result), calc.expected_end_position, calc.expected_errno,
+ "->", basep, val_or_err(tbr), end_ptr_position, hardware_errno, to_hex_string(buffer.data(), 16, ""));
+ }
+ }
+
+ double fail_rate = 100.0f * failed_samples / sample_num;
+ if (fail_rate == 0.0f) {
+ LogSuccess("Fuzzing passed!");
+ return;
+ }
+ Log("Failure rate%:", fail_rate, "(", failed_samples, "/", sample_num, "failed )");
+}
+
+TEST(DirentTests, PFSGetdirentries) {
+ LogTest("<<<< PFS getdirentries tests >>>>");
+ // -1 basep means "no change"
+ int fd {};
+ s64 tbr {};
+ fuck buffer;
+ fuck master_buffer;
+ const s64 master_length = undump_file(output_pfs_getdirentries, master_buffer);
+ oi::DirentCombination calc {};
+ s64 basep {};
+ s64 basep_canary {};
+ s64 end_ptr_position {};
+ int hardware_errno {};
+
+ LogTest("Master PFS getdirentries length is", master_length);
+
+ for (const auto& spec: pfs_dirent_variants) {
+ basep = DEFAULT_64;
+ basep_canary = basep;
+
+ calculate_pfs_getdirentries(&calc, master_buffer.data(), master_length, spec.offset, spec.size);
+
+ buffer.resize(master_length);
+ std::fill(buffer.begin(), buffer.end(), DEFAULT_8);
+
+ fd = sceKernelOpen(input_pfs, O_DIRECTORY, 0777);
+ sceKernelLseek(fd, calc.read_offset, 0);
+ errno = 0;
+ tbr = sceKernelGetdirentries(fd, buffer.data(), calc.read_size, &basep);
+ hardware_errno = errno;
+ end_ptr_position = sceKernelLseek(fd, 0, 1);
+ sceKernelClose(fd);
+
+ LogTest(calc.read_size, calc.read_offset, "->", calc.expected_basep, "(", calc.meta_dirent_start, ")", val_or_err(calc.expected_result),
+ calc.expected_end_position, calc.expected_errno, "->", basep, val_or_err(tbr), end_ptr_position, hardware_errno,
+ to_hex_string(buffer.data(), 16, ""));
+
+ if (s64 diff_idx = compare_data_dump(master_buffer, buffer, tbr, calc.meta_dirent_start); diff_idx <= 0) {
+ LogError(calc.read_size, calc.read_offset, "->", calc.expected_basep, val_or_err(calc.expected_result), calc.expected_end_position, calc.expected_errno,
+ "->", basep, val_or_err(tbr), end_ptr_position, hardware_errno, to_hex_string(buffer.data(), 16, ""));
+ LogError("Inconsistent read at/idx", calc.read_offset - diff_idx, -diff_idx);
+ if (s64 diff = master_length - calc.meta_dirent_start; diff > 0)
+ LogError("Global dump:", to_hex_string(master_buffer.data() + calc.meta_dirent_start - diff_idx, diff < 32 ? diff : 32, ""));
+ if (tbr > 0) LogError("Recent dump:", to_hex_string(buffer.data() - diff_idx, tbr < 32 ? tbr : 32, ""));
+ }
+
+ if (calc.expected_basep == -1) calc.expected_basep = basep_canary;
+ if (calc.expected_basep == basep && calc.expected_result == tbr && calc.expected_end_position == end_ptr_position && calc.expected_errno == hardware_errno)
+ continue;
+
+ LogError(calc.read_size, calc.read_offset, "->", calc.expected_basep, val_or_err(calc.expected_result), calc.expected_end_position, calc.expected_errno,
+ "->", basep, val_or_err(tbr), end_ptr_position, hardware_errno, to_hex_string(buffer.data(), 16, ""));
+ CHECK_EQUAL_TEXT(calc.expected_basep == -1 ? basep_canary : calc.expected_basep, basep, "Bad starting position");
+ CHECK_EQUAL_TEXT(calc.expected_result, tbr, "Bad read size");
+ CHECK_EQUAL_TEXT(calc.expected_end_position, end_ptr_position, "Bad pointer position after read");
+ CHECK_EQUAL_TEXT(calc.expected_errno, hardware_errno, "Bad errno");
+ }
+}
+
+TEST(DirentTests, NormalGetdirentries) {
+ LogTest("<<<< Normal getdirentries tests >>>>");
+
+ int fd {};
+ s64 tbr {};
+ fuck buffer;
+ fuck master_buffer;
+ const s64 master_length = undump_file(output_normal_getdirentries, master_buffer);
+ oi::DirentCombination calc {};
+ s64 basep {};
+ s64 basep_canary {};
+ s64 end_ptr_position {};
+ int hardware_errno {};
+
+ LogTest("Master Normal getdirentries length is", master_length);
+
+ for (const auto& spec: normal_dirent_variants) {
+ basep = DEFAULT_64;
+ basep_canary = basep;
+
+ calculate_normal_getdirentries(&calc, master_length, spec.offset, spec.size);
+
+ buffer.resize(master_length);
+ std::fill(buffer.begin(), buffer.end(), DEFAULT_8);
+
+ fd = sceKernelOpen(input_normal, O_DIRECTORY, 0777);
+ sceKernelLseek(fd, calc.read_offset, 0);
+ errno = 0;
+ tbr = sceKernelGetdirentries(fd, buffer.data(), calc.read_size, &basep);
+ hardware_errno = errno;
+ end_ptr_position = sceKernelLseek(fd, 0, 1);
+ sceKernelClose(fd);
+
+ // LogTest(calc.read_size, calc.read_offset, "->", calc.expected_basep, val_or_err(calc.expected_result), calc.expected_end_position, calc.expected_errno,
+ // "->", basep, val_or_err(tbr), end_ptr_position, hardware_errno, to_hex_string(buffer.data(), 16, ""));
+
+ if (s64 diff_idx = compare_data_dump(master_buffer, buffer, tbr, calc.meta_dirent_start); diff_idx <= 0) {
+ LogError(calc.read_size, calc.read_offset, "->", calc.expected_basep, val_or_err(calc.expected_result), calc.expected_end_position, calc.expected_errno,
+ "->", basep, val_or_err(tbr), end_ptr_position, hardware_errno, to_hex_string(buffer.data(), 16, ""));
+ LogError("Inconsistent read at/idx", calc.read_offset - diff_idx, -diff_idx);
+ if (s64 diff = master_length - calc.meta_dirent_start; diff > 0)
+ LogError("Global dump:", to_hex_string(master_buffer.data() + calc.meta_dirent_start - diff_idx, diff < 32 ? diff : 32, ""));
+ if (tbr > 0) LogError("Recent dump:", to_hex_string(buffer.data() - diff_idx, tbr < 32 ? tbr : 32, ""));
+ }
+
+ if (calc.expected_basep == -1) calc.expected_basep = basep_canary;
+ if (calc.expected_basep == basep && calc.expected_result == tbr && calc.expected_end_position == end_ptr_position && calc.expected_errno == hardware_errno)
+ continue;
+
+ LogError(calc.read_size, calc.read_offset, "->", calc.expected_basep, val_or_err(calc.expected_result), calc.expected_end_position, calc.expected_errno,
+ "->", basep, val_or_err(tbr), end_ptr_position, hardware_errno, to_hex_string(buffer.data(), 16, ""));
+ CHECK_EQUAL_TEXT(calc.expected_basep == -1 ? basep_canary : calc.expected_basep, basep, "Bad starting position");
+ CHECK_EQUAL_TEXT(calc.expected_result, tbr, "Bad read size");
+ CHECK_EQUAL_TEXT(calc.expected_end_position, end_ptr_position, "Bad pointer position after read");
+ CHECK_EQUAL_TEXT(calc.expected_errno, hardware_errno, "Bad errno");
+ }
+}
+
+TEST(DirentTests, PFSReadFuzz) {
+ LogTest("<<<< PFS read fuzzing test >>>>");
+ if (conf_opt_nofuzz) {
+ Log("Skipped");
+ return;
+ }
+ LogTest("Note: Only first 20 bad entries are shown");
+ LogTest("Note: This may take a while");
+
+ int fd {};
+ s64 tbr {};
+ fuck buffer;
+ fuck master_buffer;
+ const s64 master_length = undump_file(output_pfs_read, master_buffer);
+ oi::DirentCombination calc {};
+ s64 basep {};
+ s64 end_ptr_position {};
+ int hardware_errno {};
+
+ LogTest("Master PFS read length is", master_length, ",", "testing", FUZZ_MAX_ITERATIONS, "samples", ",", "max", FUZZ_MAX_FAILURES, "bad returns are shown");
+
+ srand(time(nullptr));
+
+ s64 sample_num {};
+ s64 failed_samples {};
+ for (sample_num = 0; sample_num < FUZZ_MAX_ITERATIONS; sample_num++) {
+ s64 spec_offset = get_fuzz();
+ s64 spec_size = rand() % (master_length + 1024);
+
+ calculate_pfs_read(&calc, master_length, spec_offset, spec_size);
+
+ buffer.resize(spec_size);
+ std::fill(buffer.begin(), buffer.end(), DEFAULT_8);
+
+ fd = sceKernelOpen(input_pfs, O_DIRECTORY, 0777);
+ basep = sceKernelLseek(fd, calc.read_offset, 0);
+ errno = 0;
+ tbr = sceKernelRead(fd, buffer.data(), calc.read_size);
+ hardware_errno = errno;
+ end_ptr_position = sceKernelLseek(fd, 0, 1);
+ sceKernelClose(fd);
+
+ if (s64 diff_idx = compare_data_dump(master_buffer, buffer, tbr, calc.meta_dirent_start); diff_idx <= 0) {
+ if (++failed_samples > FUZZ_MAX_FAILURES) continue;
+ LogError(calc.read_size, calc.read_offset, "->", calc.expected_basep, val_or_err(calc.expected_result), calc.expected_end_position, calc.expected_errno,
+ "->", basep, val_or_err(tbr), end_ptr_position, hardware_errno, to_hex_string(buffer.data(), 16, ""));
+ LogError("Inconsistent read at/idx", calc.read_offset - diff_idx, -diff_idx);
+ if (s64 diff = master_length - calc.meta_dirent_start; diff > 0)
+ LogError("Global dump:", to_hex_string(master_buffer.data() + calc.meta_dirent_start - diff_idx, diff < 32 ? diff : 32, ""));
+ if (tbr > 0) LogError("Recent dump:", to_hex_string(buffer.data() - diff_idx, tbr < 32 ? tbr : 32, ""));
+ }
+
+ if (calc.expected_basep == basep && calc.expected_result == tbr && calc.expected_end_position == end_ptr_position && calc.expected_errno == hardware_errno)
+ continue;
+ if (++failed_samples >= FUZZ_MAX_FAILURES) continue;
+ LogError(calc.read_size, calc.read_offset, "->", calc.expected_basep, val_or_err(calc.expected_result), calc.expected_end_position, calc.expected_errno,
+ "->", basep, val_or_err(tbr), end_ptr_position, hardware_errno, to_hex_string(buffer.data(), 16, ""));
+ }
+
+ double fail_rate = 100.0f * failed_samples / sample_num;
+ if (fail_rate == 0.0f) {
+ LogSuccess("Fuzzing passed!");
+ return;
+ }
+ Log("Failure rate%:", fail_rate, "(", failed_samples, "/", sample_num, "failed )");
+}
+
+TEST(DirentTests, NormalReadFuzz) {
+ LogTest("<<<< Normal read fuzzing test >>>>");
+ if (conf_opt_nofuzz) {
+ Log("Skipped");
+ return;
+ }
+ LogTest("Note: Only first 20 bad entries are shown");
+ LogTest("Note: This may take a while");
+
+ int fd {};
+ s64 tbr {};
+ fuck buffer;
+ fuck master_buffer;
+ const s64 master_length = undump_file(output_normal_read, master_buffer);
+ oi::DirentCombination calc {};
+ s64 basep {};
+ s64 end_ptr_position {};
+ int hardware_errno {};
+
+ LogTest("Master Normal read length is", master_length, ",", "testing", FUZZ_MAX_ITERATIONS, "samples", ",", "max", FUZZ_MAX_FAILURES,
+ "bad returns are shown");
+
+ srand(time(nullptr));
+
+ s64 sample_num {};
+ s64 failed_samples {};
+ for (sample_num = 0; sample_num < FUZZ_MAX_ITERATIONS; sample_num++) {
+ s64 spec_offset = get_fuzz();
+ s64 spec_size = rand() % (master_length + 1024);
+
+ calculate_pfs_read(&calc, master_length, spec_offset, spec_size);
+
+ buffer.resize(spec_size);
+ std::fill(buffer.begin(), buffer.end(), DEFAULT_8);
+
+ fd = sceKernelOpen(input_normal, O_DIRECTORY, 0777);
+ basep = sceKernelLseek(fd, calc.read_offset, 0);
+ errno = 0;
+ tbr = sceKernelRead(fd, buffer.data(), calc.read_size);
+ hardware_errno = errno;
+ end_ptr_position = sceKernelLseek(fd, 0, 1);
+ sceKernelClose(fd);
+
+ if (s64 diff_idx = compare_data_dump(master_buffer, buffer, tbr, calc.meta_dirent_start); diff_idx <= 0) {
+ if (++failed_samples > FUZZ_MAX_FAILURES) continue;
+ LogError(calc.read_size, calc.read_offset, "->", calc.expected_basep, val_or_err(calc.expected_result), calc.expected_end_position, calc.expected_errno,
+ "->", basep, val_or_err(tbr), end_ptr_position, hardware_errno, to_hex_string(buffer.data(), 16, ""));
+ LogError("Inconsistent read at/idx", calc.read_offset - diff_idx, -diff_idx);
+ if (s64 diff = master_length - calc.meta_dirent_start; diff > 0)
+ LogError("Global dump:", to_hex_string(master_buffer.data() + calc.meta_dirent_start - diff_idx, diff < 32 ? diff : 32, ""));
+ if (tbr > 0) LogError("Recent dump:", to_hex_string(buffer.data() - diff_idx, tbr < 32 ? tbr : 32, ""));
+ }
+
+ if (calc.expected_basep == basep && calc.expected_result == tbr && calc.expected_end_position == end_ptr_position && calc.expected_errno == hardware_errno)
+ continue;
+ if (++failed_samples >= FUZZ_MAX_FAILURES) continue;
+ LogError(calc.read_size, calc.read_offset, "->", calc.expected_basep, val_or_err(calc.expected_result), calc.expected_end_position, calc.expected_errno,
+ "->", basep, val_or_err(tbr), end_ptr_position, hardware_errno, to_hex_string(buffer.data(), 16, ""));
+ }
+
+ double fail_rate = 100.0f * failed_samples / sample_num;
+ if (fail_rate == 0.0f) {
+ LogSuccess("Fuzzing passed!");
+ return;
+ }
+ Log("Failure rate%:", fail_rate, "(", failed_samples, "/", sample_num, "failed )");
+}
+
+TEST(DirentTests, PFSRead) {
+ LogTest("<<<< PFS read tests >>>>");
+
+ int fd {};
+ s64 tbr {};
+ fuck buffer;
+ fuck master_buffer;
+ const s64 master_length = undump_file(output_pfs_read, master_buffer);
+ oi::DirentCombination calc {};
+ s64 basep {};
+ s64 end_ptr_position {};
+ int hardware_errno {};
+
+ LogTest("Master PFS read length is", master_length);
+
+ for (const auto& spec: pfs_read_variants) {
+ calculate_pfs_read(&calc, master_length, spec.offset, spec.size);
+
+ buffer.resize(master_length);
+ std::fill(buffer.begin(), buffer.end(), DEFAULT_8);
+
+ fd = sceKernelOpen(input_pfs, O_DIRECTORY, 0777);
+ sceKernelLseek(fd, calc.read_offset, 0);
+ basep = sceKernelLseek(fd, 0, 1);
+ errno = 0;
+ tbr = sceKernelRead(fd, buffer.data(), calc.read_size);
+ hardware_errno = errno;
+ end_ptr_position = sceKernelLseek(fd, 0, 1);
+ sceKernelClose(fd);
+
+ LogTest(calc.read_size, calc.read_offset, "->", calc.expected_basep, val_or_err(calc.expected_result), calc.expected_end_position, calc.expected_errno,
+ "->", basep, val_or_err(tbr), end_ptr_position, hardware_errno, to_hex_string(buffer.data(), 16, ""));
+
+ if (s64 diff_idx = compare_data_dump(master_buffer, buffer, tbr, calc.meta_dirent_start); diff_idx <= 0) {
+ LogError(calc.read_size, calc.read_offset, "->", calc.expected_basep, val_or_err(calc.expected_result), calc.expected_end_position, calc.expected_errno,
+ "->", basep, val_or_err(tbr), end_ptr_position, hardware_errno, to_hex_string(buffer.data(), 16, ""));
+ LogError("Inconsistent read at/idx", calc.read_offset - diff_idx, -diff_idx);
+ if (s64 diff = master_length - calc.meta_dirent_start; diff > 0)
+ LogError("Global dump:", to_hex_string(master_buffer.data() + calc.meta_dirent_start - diff_idx, diff < 32 ? diff : 32, ""));
+ if (tbr > 0) LogError("Recent dump:", to_hex_string(buffer.data() - diff_idx, tbr < 32 ? tbr : 32, ""));
+ }
+
+ if (calc.expected_basep == basep && calc.expected_result == tbr && calc.expected_end_position == end_ptr_position && calc.expected_errno == hardware_errno)
+ continue;
+
+ LogError(calc.read_size, calc.read_offset, "->", calc.expected_basep, val_or_err(calc.expected_result), calc.expected_end_position, calc.expected_errno,
+ "->", basep, val_or_err(tbr), end_ptr_position, hardware_errno, to_hex_string(buffer.data(), 16, ""));
+ CHECK_EQUAL_TEXT(calc.expected_basep, basep, "Bad starting position");
+ CHECK_EQUAL_TEXT(calc.expected_result, tbr, "Bad read size");
+ CHECK_EQUAL_TEXT(calc.expected_end_position, end_ptr_position, "Bad pointer position after read");
+ CHECK_EQUAL_TEXT(calc.expected_errno, hardware_errno, "Bad errno");
+ }
+}
+
+TEST(DirentTests, NormalRead) {
+ LogTest("<<<< Normal read tests >>>>");
+
+ int fd {};
+ s64 tbr {};
+ fuck buffer;
+ fuck master_buffer;
+ const s64 master_length = undump_file(output_normal_read, master_buffer);
+ oi::DirentCombination calc {};
+ s64 basep {};
+ s64 end_ptr_position {};
+ int hardware_errno {};
+
+ LogTest("Master Normal read length is", master_length);
+
+ for (const auto& spec: normal_read_variants) {
+ calculate_normal_read(&calc, master_length, spec.offset, spec.size);
+
+ buffer.resize(master_length);
+ std::fill(buffer.begin(), buffer.end(), DEFAULT_8);
+
+ fd = sceKernelOpen(input_normal, O_DIRECTORY, 0777);
+ sceKernelLseek(fd, calc.read_offset, 0);
+ basep = sceKernelLseek(fd, 0, 1);
+ errno = 0;
+ tbr = sceKernelRead(fd, buffer.data(), calc.read_size);
+ hardware_errno = errno;
+ end_ptr_position = sceKernelLseek(fd, 0, 1);
+ sceKernelClose(fd);
+
+ // LogTest(calc.read_size, calc.read_offset, "->", calc.expected_basep, val_or_err(calc.expected_result), calc.expected_end_position, calc.expected_errno,
+ // "->", basep, val_or_err(tbr), end_ptr_position, hardware_errno, to_hex_string(buffer, 16, ""));
+
+ if (s64 diff_idx = compare_data_dump(master_buffer, buffer, tbr, calc.meta_dirent_start); diff_idx <= 0) {
+ LogError(calc.read_size, calc.read_offset, "->", calc.expected_basep, val_or_err(calc.expected_result), calc.expected_end_position, calc.expected_errno,
+ "->", basep, val_or_err(tbr), end_ptr_position, hardware_errno, to_hex_string(buffer.data(), 16, ""));
+ LogError("Inconsistent read at/idx", calc.read_offset - diff_idx, -diff_idx);
+ if (s64 diff = master_length - calc.meta_dirent_start; diff > 0)
+ LogError("Global dump:", to_hex_string(master_buffer.data() + calc.meta_dirent_start - diff_idx, diff < 32 ? diff : 32, ""));
+ if (tbr > 0) LogError("Recent dump:", to_hex_string(buffer.data() - diff_idx, tbr < 32 ? tbr : 32, ""));
+ }
+
+ if (calc.expected_basep == basep && calc.expected_result == tbr && calc.expected_end_position == end_ptr_position && calc.expected_errno == hardware_errno)
+ continue;
+
+ LogError(calc.read_size, calc.read_offset, "->", calc.expected_basep, val_or_err(calc.expected_result), calc.expected_end_position, calc.expected_errno,
+ "->", basep, val_or_err(tbr), end_ptr_position, hardware_errno, to_hex_string(buffer.data(), 16, ""));
+ CHECK_EQUAL_TEXT(calc.expected_basep, basep, "Bad starting position");
+ CHECK_EQUAL_TEXT(calc.expected_result, tbr, "Bad read size");
+ CHECK_EQUAL_TEXT(calc.expected_end_position, end_ptr_position, "Bad pointer position after read");
+ CHECK_EQUAL_TEXT(calc.expected_errno, hardware_errno, "Bad errno");
+ }
+}
+
+TEST(DirentTests, PFSLSeekFuzz) {
+ LogTest("<<<< PFS lseek fuzzing test >>>>");
+ if (conf_opt_nofuzz) {
+ Log("Skipped");
+ return;
+ }
+ LogTest("Note: Only first 20 bad entries are shown");
+
+ int fd {};
+ s64 master_length {};
+ s64 current_offset {};
+ s64 previous_offset {};
+ s64 expected_offset {};
+ s64 hardware_offset {};
+ int expected_errno {};
+ int hardware_errno {};
+
+ s64 sample_num {};
+ s64 failed_samples {};
+ fd = sceKernelOpen(input_pfs, O_DIRECTORY, 0777);
+ add_fd(fd);
+
+ master_length = sceKernelLseek(fd, 0, 2);
+ CHECK_EQUAL_ZERO(sceKernelLseek(fd, 0, 0));
+ current_offset = 0;
+
+ srand(time(nullptr));
+
+ for (sample_num = 0; sample_num < FUZZ_MAX_ITERATIONS; sample_num++) {
+ s64 spec_offset = get_fuzz();
+ int spec_whence = rand() % 6 - 1; // -1 to 4; // -1 to 4
+
+ expected_offset = calculate_lseek(master_length, current_offset, spec_offset, spec_whence, &expected_errno);
+ errno = 0;
+ hardware_offset = sceKernelLseek(fd, spec_offset, spec_whence);
+ hardware_errno = errno;
+
+ previous_offset = current_offset;
+ if (hardware_offset >= 0) current_offset = hardware_offset; // set this because if one fails, all subsequent ones fail too
+ if (expected_offset == hardware_offset && expected_errno == hardware_errno) {
+ continue;
+ }
+
+ if (++failed_samples >= FUZZ_MAX_FAILURES) continue;
+
+ LogError("Size:", master_length, "Spec off:", spec_offset, "Spec whence:", spec_whence, "Start off:", previous_offset, "Expected off:", expected_offset,
+ "DUT off:", hardware_offset, "Expected errno:", expected_errno, "DUT errno:", hardware_errno);
+ }
+
+ sceKernelClose(fd);
+
+ double fail_rate = 100.0f * failed_samples / sample_num;
+ if (fail_rate == 0.0f) {
+ LogSuccess("Fuzzing passed!");
+ return;
+ }
+ Log("Failure rate%:", fail_rate, "(", failed_samples, "/", sample_num, "failed )");
+}
+
+TEST(DirentTests, NormalLSeekFuzz) {
+ LogTest("<<<< Normal lseek fuzzing test >>>>");
+ if (conf_opt_nofuzz) {
+ Log("Skipped");
+ return;
+ }
+ LogTest("Note: Only first 20 bad entries are shown");
+
+ int fd {};
+ s64 master_length {};
+ s64 current_offset {};
+ s64 previous_offset {};
+ s64 expected_offset {};
+ s64 hardware_offset {};
+ int expected_errno {};
+ int hardware_errno {};
+
+ s64 sample_num {};
+ s64 failed_samples {};
+
+ fd = sceKernelOpen(input_normal, O_DIRECTORY, 0777);
+ add_fd(fd);
+
+ master_length = sceKernelLseek(fd, 0, 2);
+ CHECK_EQUAL_ZERO(sceKernelLseek(fd, 0, 0));
+ current_offset = 0;
+
+ srand(time(nullptr));
+
+ for (sample_num = 0; sample_num < FUZZ_MAX_ITERATIONS; sample_num++) {
+ s64 spec_offset = get_fuzz();
+ int spec_whence = rand() % 6 - 1; // -1 to 4; // -1 to 4
+
+ expected_offset = calculate_lseek(master_length, current_offset, spec_offset, spec_whence, &expected_errno);
+ errno = 0;
+ hardware_offset = sceKernelLseek(fd, spec_offset, spec_whence);
+ hardware_errno = errno;
+
+ previous_offset = current_offset;
+ if (hardware_offset >= 0) current_offset = hardware_offset; // set this because if one fails, all subsequent ones fail too
+ if (expected_offset == hardware_offset && expected_errno == hardware_errno) {
+ continue;
+ }
+
+ if (++failed_samples >= FUZZ_MAX_FAILURES) continue;
+
+ LogError("Size:", master_length, "Spec off:", spec_offset, "Spec whence:", spec_whence, "Start off:", previous_offset, "Expected off:", expected_offset,
+ "DUT off:", hardware_offset, "Expected errno:", expected_errno, "DUT errno:", hardware_errno);
+ }
+
+ sceKernelClose(fd);
+
+ double fail_rate = 100.0f * failed_samples / sample_num;
+ if (fail_rate == 0.0f) {
+ LogSuccess("Fuzzing passed!");
+ return;
+ }
+ Log("Failure rate%:", fail_rate, "(", failed_samples, "/", sample_num, "failed )");
+}
+
+TEST(DirentTests, PFSLSeekTests) {
+ LogTest("<<<< PFS lseek tests >>>>");
+
+ int fd {};
+ s64 master_length {};
+ s64 current_offset {};
+ s64 previous_offset {};
+ s64 expected_offset {};
+ s64 hardware_offset {};
+ int expected_errno {};
+ int hardware_errno {};
+
+ fd = sceKernelOpen(input_pfs, O_DIRECTORY, 0777);
+ add_fd(fd);
+
+ master_length = sceKernelLseek(fd, 0, 2);
+ CHECK_EQUAL_ZERO(sceKernelLseek(fd, 0, 0));
+ current_offset = 0;
+
+ for (const auto& spec: pfs_lseek_variants) {
+ expected_offset = calculate_lseek(master_length, current_offset, spec.offset, spec.whence, &expected_errno);
+ errno = 0;
+ hardware_offset = sceKernelLseek(fd, spec.offset, spec.whence);
+ hardware_errno = errno;
+
+ // LogTest(previous_offset, spec.offset, spec.whence, "->", val_or_err(expected_offset), expected_errno, "->", val_or_err(hardware_offset), hardware_errno);
+
+ previous_offset = current_offset;
+ if (hardware_offset >= 0) current_offset = hardware_offset; // set this because if one fails, all subsequent ones fail too
+ if (expected_offset == hardware_offset && expected_errno == hardware_errno) {
+ continue;
+ }
+
+ LogError("Size:", master_length, "Spec off:", spec.offset, "Spec whence:", spec.whence, "Start off:", previous_offset, "Expected off:", expected_offset,
+ "DUT off:", hardware_offset, "Expected errno:", expected_errno, "DUT errno:", hardware_errno);
+ }
+
+ sceKernelClose(fd);
+}
+
+TEST(DirentTests, NormalLSeekTests) {
+ LogTest("<<<< Normal lseek tests >>>>");
+
+ int fd {};
+ s64 master_length {};
+ s64 current_offset {};
+ s64 previous_offset {};
+ s64 expected_offset {};
+ s64 hardware_offset {};
+ int expected_errno {};
+ int hardware_errno {};
+
+ fd = sceKernelOpen(input_normal, O_DIRECTORY, 0777);
+ add_fd(fd);
+
+ master_length = sceKernelLseek(fd, 0, 2);
+ CHECK_EQUAL_ZERO(sceKernelLseek(fd, 0, 0));
+ current_offset = 0;
+
+ for (const auto& spec: normal_lseek_variants) {
+ expected_offset = calculate_lseek(master_length, current_offset, spec.offset, spec.whence, &expected_errno);
+ errno = 0;
+ hardware_offset = sceKernelLseek(fd, spec.offset, spec.whence);
+ hardware_errno = errno;
+
+ // LogTest(previous_offset, spec.offset, spec.whence, "->", val_or_err(expected_offset), expected_errno, "->", val_or_err(hardware_offset), hardware_errno);
+
+ previous_offset = current_offset;
+ if (hardware_offset >= 0) current_offset = hardware_offset; // set this because if one fails, all subsequent ones fail too
+ if (expected_offset == hardware_offset && expected_errno == hardware_errno) {
+ continue;
+ }
+
+ LogError("Size:", master_length, "Spec off:", spec.offset, "Spec whence:", spec.whence, "Start off:", previous_offset, "Expected off:", expected_offset,
+ "DUT off:", hardware_offset, "Expected errno:", expected_errno, "DUT errno:", hardware_errno);
+ }
+
+ sceKernelClose(fd);
+}
+
+s64 NormalComparator(const char* read, const char* getdirentries, u64 length) {
+ s64 offset {0};
+ u64 entry_counter {0};
+ while (offset < length) {
+ const oi::FolderDirent* dirent_read = reinterpret_cast(read + offset);
+ const oi::FolderDirent* dirent_getdirentries = reinterpret_cast(getdirentries + offset);
+
+ if (validate_normal_dirent(dirent_read) < 0) break;
+ if (validate_normal_dirent(dirent_getdirentries) < 0) break;
+ if (dirent_read->d_namlen != dirent_getdirentries->d_namlen) break;
+ if (dirent_read->d_reclen != dirent_getdirentries->d_reclen) break;
+ if (dirent_read->d_type != dirent_getdirentries->d_type) break;
+ if (memcmp(dirent_read->d_name, dirent_getdirentries->d_name, dirent_read->d_namlen)) break; // namlen is the same
+ if (offset + dirent_read->d_reclen > length) break;
+ offset += dirent_read->d_reclen;
+ if (dirent_read->d_reclen == 0) break;
+ entry_counter++;
+ }
+
+ Log("Compared", entry_counter, "entries , length =", offset);
+ return offset;
+}
+
+TEST(DirentTests, Normal_Consistency) {
+ LogTest("<<<< Normal read and getdirentries consistency >>>>");
+ Log("Note:", files_cloned_target + 2, "files are supposed to be compared");
+
+ fuck master_read;
+ fuck master_getdirentries;
+
+ auto master_read_size = undump_file(output_normal_read, master_read);
+ auto master_getdirentries_size = undump_file(output_normal_getdirentries, master_getdirentries);
+
+ if (auto res = NormalComparator(master_read.data(), master_getdirentries.data(), master_read_size); master_getdirentries_size != res) {
+ LogError("Normal read and getdirentries have a different dirent at", res, ":");
+ LogError("Normal Read:\t ", to_hex_string(master_read.data() + res, 24));
+ LogError("Normal Getdirentries: ", to_hex_string(master_read.data() + res, 24));
+ FAIL("Normal read and getdirentries returned different amount of data");
+ }
+}
+
+s64 PFSComparator(const char* read, const char* getdirentries, u64 length) {
+ s64 offset {0};
+ u64 entry_counter {0};
+ while (offset < length) {
+ const oi::PfsDirent* dirent_read = reinterpret_cast(read + offset);
+ const oi::FolderDirent* dirent_getdirentries = reinterpret_cast(getdirentries + offset);
+
+ if (validate_pfs_read_dirent(dirent_read) < 0) break;
+ if (validate_pfs_getdirentries_dirent(dirent_getdirentries) < 0) break;
+ if (dirent_read->d_namlen != dirent_getdirentries->d_namlen) break;
+ if (dirent_read->d_reclen != dirent_getdirentries->d_reclen) break;
+ // if (dirent_read->d_type != dirent_getdirentries->d_type) break;
+ if (memcmp(dirent_read->d_name, dirent_getdirentries->d_name, dirent_read->d_namlen)) break; // namlen is the same
+ if (dirent_read->d_reclen == 0) break; // reclen is the same
+ if (offset + dirent_read->d_reclen > length) break;
+ offset += dirent_read->d_reclen;
+ entry_counter++;
+ }
+
+ Log("Compared", entry_counter, "entries , length =", offset);
+ return offset;
+}
+
+TEST(DirentTests, PFS_Consistency) {
+ LogTest("<<<< PFS read and getdirentries consistency >>>>");
+ Log("Note:", files_cloned_target + 2, "files are supposed to be compared");
+ LogWarning("Note: This function does not translate d_type between PFS and user filesystems");
+
+ fuck master_read {DEFAULT_CHR};
+ fuck master_getdirentries {DEFAULT_CHR};
+
+ auto master_read_size = undump_file(output_pfs_read, master_read);
+ auto master_getdirentries_size = undump_file(output_pfs_getdirentries, master_getdirentries);
+
+ if (auto res = PFSComparator(master_read.data(), master_getdirentries.data(), master_read_size); master_getdirentries_size != res) {
+ LogError("PFS read and getdirentries have a different dirent at", res, ":");
+ LogError("PFS Read:\t ", to_hex_string(master_read.data() + res, 24));
+ LogError("PFS Getdirentries: ", to_hex_string(master_read.data() + res, 24));
+ FAIL("PFS read and getdirentries returned different amount of data");
+ }
+}
+
+TEST(DirentTests, ValidateDirentries) {
+ LogTest("<<<< Dirent structure validation >>>>");
+ fuck buffer;
+ s64 master_length {};
+ s64 offset {};
+
+ // these tests are not done yet
+ LogTest("Normal read");
+ master_length = undump_file(output_normal_read, buffer);
+ CHECK_COMPARE_TEXT(validate_normal_getdirentries(buffer.data(), master_length), >, 0, "Normal Read validation failed");
+ LogTest("Normal getdirentries");
+ master_length = undump_file(output_normal_getdirentries, buffer);
+ CHECK_COMPARE_TEXT(validate_normal_getdirentries(buffer.data(), master_length), >, 0, "Normal getdirentries validation failed");
+
+ LogTest("PFS read");
+ master_length = undump_file(output_pfs_read, buffer);
+ CHECK_COMPARE_TEXT(validate_pfs_read(buffer.data(), master_length), >, 0, "PFS read validation failed");
+ LogTest("PFS getdirentries");
+ master_length = undump_file(output_pfs_getdirentries, buffer);
+ CHECK_COMPARE_TEXT(validate_pfs_getdirentries(buffer.data(), master_length), >, 0, "PFS getdirentries validation failed");
+}
+
+TEST(DirentTests, DumpEverythingRaw) {
+ LogTest("<<<< Dump everything >>>>");
+
+ int fd_read {};
+ int fd_dump {};
+ char buffer[65536];
+ s64 tbr {};
+
+ sceKernelMkdir(output_dir, 0777);
+
+ //
+
+ fd_read = sceKernelOpen(input_pfs, O_DIRECTORY | O_RDONLY, 0777);
+ CHECK_COMPARE_TEXT(fd_read, >, 0, "Can't open input dir");
+ add_fd(fd_read);
+
+ //
+
+ fd_dump = sceKernelOpen(output_pfs_read, O_CREAT | O_TRUNC | O_WRONLY, 0777);
+ add_fd(fd_dump);
+ CHECK_COMPARE_TEXT(fd_dump, >, 0, "Can't open output dir");
+ do {
+ memset(buffer, DEFAULT_8, 65536);
+ tbr = sceKernelRead(fd_read, buffer, 65536);
+ CHECK_COMPARE_TEXT(tbr, >=, 0, "PFS read failed");
+ LogTest("PFS read got", tbr, "bytes");
+ if (tbr == 0) break;
+ CHECK_EQUAL(tbr, sceKernelWrite(fd_dump, buffer, tbr));
+ } while (tbr > 0);
+ CHECK_EQUAL_ZERO(sceKernelClose(fd_dump));
+
+ //
+
+ fd_dump = sceKernelOpen(output_pfs_getdirentries, O_CREAT | O_TRUNC | O_WRONLY, 0777);
+ add_fd(fd_dump);
+ CHECK_COMPARE_TEXT(fd_dump, >, 0, "Can't open output dir");
+ CHECK_EQUAL_ZERO_TEXT(sceKernelLseek(fd_read, 0, 0), "Can't rewind directory");
+ do {
+ memset(buffer, DEFAULT_8, 65536);
+ tbr = sceKernelGetdirentries(fd_read, buffer, 65536, nullptr);
+ CHECK_COMPARE_TEXT(tbr, >=, 0, "PFS sceKernelGetdirentries failed");
+ LogTest("PFS sceKernelGetdirentries got", tbr, "bytes");
+ if (tbr == 0) break;
+ CHECK_EQUAL(tbr, sceKernelWrite(fd_dump, buffer, tbr));
+ } while (tbr > 0);
+ CHECK_EQUAL_ZERO(sceKernelClose(fd_dump));
+
+ //
+
+ CHECK_EQUAL_ZERO(sceKernelClose(fd_read));
+ fd_read = sceKernelOpen(input_normal, O_DIRECTORY | O_RDONLY, 0777);
+ add_fd(fd_read);
+ CHECK_COMPARE_TEXT(fd_read, >, 0, "Can't open input dir");
+
+ //
+
+ fd_dump = sceKernelOpen(output_normal_read, O_CREAT | O_TRUNC | O_WRONLY, 0777);
+ add_fd(fd_dump);
+ CHECK_COMPARE_TEXT(fd_dump, >, 0, "Can't open output dir");
+ do {
+ memset(buffer, DEFAULT_8, 65536);
+ tbr = sceKernelRead(fd_read, buffer, 65536);
+ CHECK_COMPARE_TEXT(tbr, >=, 0, "Normal read failed");
+ LogTest("Normal read got", tbr, "bytes");
+ if (tbr == 0) break;
+ CHECK_EQUAL(tbr, sceKernelWrite(fd_dump, buffer, tbr));
+ } while (tbr > 0);
+ CHECK_EQUAL_ZERO(sceKernelClose(fd_dump));
+
+ //
+ fd_dump = sceKernelOpen(output_normal_getdirentries, O_CREAT | O_TRUNC | O_WRONLY, 0777);
+ add_fd(fd_dump);
+ CHECK_COMPARE_TEXT(fd_dump, >, 0, "Can't open output dir");
+ CHECK_EQUAL_ZERO_TEXT(sceKernelLseek(fd_read, 0, 0), "Can't rewind directory");
+ do {
+ memset(buffer, DEFAULT_8, 65536);
+ tbr = sceKernelGetdirentries(fd_read, buffer, 65536, nullptr);
+ CHECK_COMPARE_TEXT(tbr, >=, 0, "Normal sceKernelGetdirentries failed");
+ LogTest("Normal sceKernelGetdirentries got", tbr, "bytes");
+ if (tbr == 0) break;
+ CHECK_EQUAL(tbr, sceKernelWrite(fd_dump, buffer, tbr));
+ } while (tbr > 0);
+ CHECK_EQUAL_ZERO(sceKernelClose(fd_dump));
+
+ //
+
+ CHECK_EQUAL_ZERO(sceKernelClose(fd_read));
+}
+
+TEST(DirentTests, PrepareTests) {
+ LogTest("<<<< Preparing test directory >>>>");
+
+ fs::path target {};
+ s32 status {};
+
+ RegenerateDir(enderman_root);
+ sceKernelMkdir(input_normal, 0777);
+
+ s64 entry_counter {0};
+ // ironic because directory_iterator uses dirents hehe
+ for (auto& dent: fs::directory_iterator(input_pfs)) {
+ target = fs::path(input_normal) / dent.path().filename();
+ if (dent.is_regular_file()) {
+ status = touch(target.c_str());
+ entry_counter++;
+ continue;
+ }
+ if (dent.is_directory()) {
+ status = sceKernelMkdir(target.c_str(), 0777);
+ entry_counter++;
+ continue;
+ }
+ LogError("Can't create", target.string());
+ FAIL("");
+ }
+
+ Log("Cloned into", entry_counter, "elements");
+ if (entry_counter != files_cloned_target) LogError("Not all files cloned:", entry_counter, "out of", files_cloned_target);
+}
+
+TEST(DirentTests, GetConfig) {
+ LogTest("<<<< Get config >>>>");
+ conf_opt_nofuzz = false;
+
+ if (sceKernelMkdir(config_path, 0777) == 0) {
+ Log("Config directory created. Assuming no options deactivated");
+ return;
+ }
+
+ OrbisKernelStat st {};
+ if (int status = sceKernelStat(config_path_nofuzz, &st); status == 0) {
+ Log("Enabled skip fuzzing");
+ conf_opt_nofuzz = true;
+ }
+}
\ No newline at end of file
diff --git a/tests/code/filesystem_dirents/code/fs_test.h b/tests/code/filesystem_dirents/code/fs_test.h
new file mode 100644
index 00000000..2d66ae4b
--- /dev/null
+++ b/tests/code/filesystem_dirents/code/fs_test.h
@@ -0,0 +1,100 @@
+#ifndef FS_TEST_H
+#define FS_TEST_H
+
+#pragma once
+
+#include "log.h"
+
+#include
+
+#define ALUP(x, y) (((x) & (~((y) - 1))) + (y))
+#define ALDN(x, y) (((x) & (~((y) - 1))))
+#define ISAL(x, y) (bool(((x) & ((y) - 1)) == 0))
+
+#define UNSIGNED_INT_EQUALS(expected, actual) UNSIGNED_LONGS_EQUAL_LOCATION((uint32_t)expected, (uint32_t)actual, NULLPTR, __FILE__, __LINE__)
+#define UNSIGNED_INT_EQUALS_TEXT(expected, actual, text) UNSIGNED_LONGS_EQUAL_LOCATION((uint32_t)expected, (uint32_t)actual, text, __FILE__, __LINE__)
+
+// direct casts to x64 fail, they need to be assigned to an int
+constexpr int einval_int = ORBIS_KERNEL_ERROR_EINVAL;
+constexpr int enotty_int = ORBIS_KERNEL_ERROR_ENOTTY;
+constexpr int enxio_int = ORBIS_KERNEL_ERROR_ENXIO;
+constexpr int eoverflow_int = ORBIS_KERNEL_ERROR_EOVERFLOW;
+
+using s8 = int8_t;
+using s16 = int16_t;
+using s32 = int32_t;
+using s64 = int64_t;
+
+using u8 = uint8_t;
+using u16 = uint16_t;
+using u32 = uint32_t;
+using u64 = uint64_t;
+
+using fuck = std::vector;
+
+namespace OrbisInternals {
+
+typedef struct {
+ u64 size;
+ s64 offset;
+} spec_t;
+
+typedef struct {
+ s64 offset;
+ int whence;
+} offset_spec_t;
+
+typedef struct {
+ u64 read_size; // user-defined
+ s64 read_offset; // user-defined
+ // results, calculated:
+ s64 expected_lseek; // lseek result
+ s64 expected_basep; // read start position
+ s64 meta_dirent_start; // offset relative to offset of the first dirent (PFS getdirentries only)
+ s64 expected_result; // return from read/getdirentries
+ s64 expected_end_position; // file pointer
+ int expected_errno;
+} DirentCombination;
+
+typedef struct {
+ s32 d_fileno;
+ s32 d_type;
+ s32 d_namlen;
+ s32 d_reclen;
+ char d_name[256];
+} PfsDirent;
+
+typedef struct {
+ u32 d_fileno;
+ u16 d_reclen;
+ u8 d_type;
+ u8 d_namlen;
+ char d_name[256];
+} FolderDirent;
+} // namespace OrbisInternals
+
+s64 get_fuzz();
+
+void RegenerateDir(const char* path);
+void Obliterate(const char* path);
+int32_t touch(const char* path);
+int32_t touch(const std::string& path);
+bool is_directory_relatives(const char* data);
+s64 imemcmp(const void* object, const void* reflection, s64 bytes);
+s64 fillcheck(const void* data, const u8 value, const u64 bytes);
+
+s64 get_stat_size(const char* path);
+
+std::string val_or_err(s64 value);
+s64 compare_data_dump(const fuck& master, const fuck& test, s64 tbr, s64 offset);
+
+s64 validate_normal_dirent(const OrbisInternals::FolderDirent* dirent);
+s64 validate_pfs_read_dirent(const OrbisInternals::PfsDirent* dirent);
+s64 validate_pfs_getdirentries_dirent(const OrbisInternals::FolderDirent* dirent);
+s64 validate_pfs_getdirentries_experimental(const OrbisInternals::PfsDirent* dirent);
+
+s64 validate_normal_getdirentries(const char* data, const s64 bytes);
+s64 validate_pfs_read(const char* data, const s64 bytes);
+s64 validate_pfs_getdirentries(const char* data, const s64 bytes);
+
+#endif // FS_TEST_H
diff --git a/tests/code/filesystem_dirents/code/fs_test_constants.h b/tests/code/filesystem_dirents/code/fs_test_constants.h
new file mode 100644
index 00000000..000b9b20
--- /dev/null
+++ b/tests/code/filesystem_dirents/code/fs_test_constants.h
@@ -0,0 +1,21 @@
+#ifndef FS_TEST_CONST_H
+#define FS_TEST_CONST_H
+
+#pragma once
+
+#define FUZZ_MAX_ITERATIONS 50000 // arbitrary but large enough
+#define FUZZ_MAX_FAILURES 20
+
+constexpr s64 files_cloned_target = 530;
+
+constexpr u64 buffer_size = 65536 * 3;
+
+constexpr char DEFAULT_CHR = 'A';
+constexpr u8 DEFAULT_8 = 0xAA;
+constexpr u8 DEFAULT_16 = 0xAAAA;
+constexpr u8 DEFAULT_32 = 0xAAAAAAAA;
+constexpr u8 DEFAULT_64 = 0xAAAAAAAAAAAAAAAA;
+
+#include "read_variants/variants.h"
+
+#endif // FS_TEST_CONST_H
\ No newline at end of file
diff --git a/tests/code/filesystem_dirents/code/fs_test_tools.cpp b/tests/code/filesystem_dirents/code/fs_test_tools.cpp
new file mode 100755
index 00000000..0ebfe641
--- /dev/null
+++ b/tests/code/filesystem_dirents/code/fs_test_tools.cpp
@@ -0,0 +1,284 @@
+#include "fs_test.h"
+
+#include
+#include
+#include
+#include
+
+namespace fs = std::filesystem;
+namespace oi = OrbisInternals;
+
+s64 get_fuzz() {
+ return ((s64(rand()) << 32) | rand()) >> (rand() % 64);
+}
+
+std::string val_or_err(s64 value) {
+ switch (value) {
+ default: return std::to_string(value);
+ case einval_int: return "EINVAL";
+ case enotty_int: return "ENOTTY";
+ case enxio_int: return "ENXIO";
+ case eoverflow_int: return "EOVERFLOW";
+ }
+ return "WHATTHEFUCK";
+}
+
+// 1 on equal, <=0 on diff idx
+s64 compare_data_dump(const fuck& master, const fuck& test, s64 tbr, s64 offset) {
+ s64 buffer_size = master.size();
+
+ if (tbr <= 0) return 1;
+ if (offset < 0) return 0;
+ if (offset >= buffer_size) return 0;
+ if (offset + tbr > buffer_size) {
+ return 0;
+ // LogError("Partial comparsion possible:", buffer_size - offset, "/", tbr, "can be compared");
+ // tbr = buffer_size - offset;
+ }
+
+ if (s64 idx = imemcmp(master.data() + offset, test.data(), tbr); idx <= 0) {
+ // differing idx is negative
+ return idx;
+ }
+ return 1;
+}
+
+// 1 = equal, <=0 = diff idx
+// does not adhere to memcmp spec, i want differing indexes, not values!
+s64 imemcmp(const void* object, const void* reflection, s64 bytes) {
+ if (bytes <= 0) return 1;
+
+ u32 longs = (bytes & ~0x7) >> 3; // bytes to longs (divide by 8 basically)
+ const u64* object_ptr64 = static_cast(object);
+ const u64* reflection_ptr64 = static_cast(reflection);
+ const u8* object_ptr8 = static_cast(object);
+ const u8* reflection_ptr8 = static_cast(reflection);
+ s64 idx = 0;
+
+ for (idx = 0; idx < longs; idx++) {
+ // target is 64bit, so one step is 8 bytes
+ if (*(object_ptr64 + idx) == *(reflection_ptr64 + idx)) continue;
+ // if different, skip the rest to compare shorts
+ break;
+ }
+
+ // longlong->byte conversion
+ // worst case scenario 8 iterations
+ for (idx <<= 3; idx < bytes; idx++) {
+ if (*(object_ptr8 + idx) == *(reflection_ptr8 + idx)) continue;
+ return -idx;
+ }
+
+ return 1;
+}
+
+s64 fillcheck(const void* data, const u8 value, const u64 bytes) {
+ u64 longval = 0x0101010101010101 * value; // fills entire u64 with one value
+ u32 longs = (bytes & ~0x7) >> 3;
+
+ const u64* data_ptr64 = static_cast(data);
+ const u8* data_ptr8 = static_cast(data);
+ u64 idx = 0;
+
+ for (idx = 0; idx < longs; idx++) {
+ if (longval != *(data_ptr64 + idx)) break;
+ }
+
+ for (idx <<= 3; idx < bytes; idx++) {
+ if (value != *(data_ptr8 + idx)) return idx;
+ }
+
+ return -1;
+};
+
+s64 validate_normal_dirent(const oi::FolderDirent* dirent) {
+ // N/A it'd need offset to calculate reclen correctly
+ // i think this test is duplicated somewhere here too
+ // auto _reclen = 8 + dirent->d_namlen + 1;
+ // _reclen = ISAL(_reclen, 8) ? _reclen : ALUP(_reclen, 8);
+ // if (_reclen != dirent->d_reclen) return -10;
+
+ // best case scenario tbh
+ if (dirent->d_reclen & 0x03) return -10;
+ if (dirent->d_fileno == 0) return -11;
+
+ // these don't fail so often
+ if (dirent->d_namlen == 0) return -12;
+ if (dirent->d_type == 0) return -13;
+ if (dirent->d_reclen == 0) return -14;
+ if (dirent->d_reclen < 12 || dirent->d_reclen > 512) return -16;
+ if (dirent->d_type > 15) return -17;
+ if (strnlen(dirent->d_name, 255) != dirent->d_namlen) return -18;
+
+ return 1;
+}
+
+/**
+ * reclen is basically a checksum
+ * i've never seen any other than -11, but i've attached others for verbosity
+ */
+
+// pfs getdirentries returns normal direntries
+s64 validate_pfs_read_dirent(const oi::PfsDirent* dirent) {
+ auto _reclen = 16 + dirent->d_namlen + 1;
+ _reclen = ISAL(_reclen, 8) ? _reclen : ALUP(_reclen, 8);
+ if (_reclen != dirent->d_reclen) return -10;
+ if (dirent->d_fileno == 0) return -11;
+
+ // these don't fail so often
+ if (dirent->d_namlen == 0) return -12;
+ if (dirent->d_type == 0) return -13;
+ if (dirent->d_reclen == 0) return -14;
+ if ((dirent->d_reclen & 0x07) != 0) return -15;
+ if (dirent->d_reclen < 24 || dirent->d_reclen > 272) return -16;
+ if (dirent->d_type > 15) return -17;
+ if (strnlen(dirent->d_name, 255) != dirent->d_namlen) return -18;
+
+ return 1;
+}
+
+// pfs getdirentries returns normal direntries
+s64 validate_pfs_getdirentries_dirent(const oi::FolderDirent* dirent) {
+ auto _reclen = 16 + dirent->d_namlen + 1;
+ _reclen = ISAL(_reclen, 8) ? _reclen : ALUP(_reclen, 8);
+ if (_reclen != dirent->d_reclen) return -10;
+ if (dirent->d_fileno == 0) return -11;
+
+ // these don't fail so often
+ if (dirent->d_namlen == 0) return -12;
+ if (dirent->d_type == 0) return -13;
+ if (dirent->d_reclen == 0) return -14;
+ if ((dirent->d_reclen & 0x07) != 0) return -15;
+ if (dirent->d_reclen < 24 || dirent->d_reclen > 272) return -16;
+ if (dirent->d_type > 15) return -17;
+ if (strnlen(dirent->d_name, 255) != dirent->d_namlen) return -18;
+
+ return 1;
+}
+
+/**
+ * I suspect that pfs dirents are u32 but need to be mask
+ * maybe Orbis uses normal types, but on disk each one is u32 instead of u32,u16,u8,u8
+ * so we can clear lower bytes and check for anything above!
+ */
+
+// pfs getdirentries returns normal direntries
+s64 validate_pfs_getdirentries_experimental(const oi::PfsDirent* dirent) {
+ if (dirent->d_type & ~s32(0xFF)) return -12;
+ if (dirent->d_namlen & ~s32(0xFF)) return -13;
+ if (dirent->d_reclen & ~s32(0xFFFF)) return -14;
+
+ if (ALUP(16 + dirent->d_namlen + 1, 8) != dirent->d_reclen) return -15;
+ if ((dirent->d_reclen < 24) || (dirent->d_reclen > 272)) return -16;
+ if (dirent->d_type > 15) return -17;
+ if (dirent->d_namlen == 0) return -18;
+ if (strnlen(dirent->d_name, 255) != dirent->d_namlen) return -19;
+ return 0;
+}
+
+s64 validate_normal_getdirentries(const char* data, const s64 bytes) {
+ if (bytes < 0) return bytes;
+ if (data == nullptr) return -1;
+
+ s64 offset = 0;
+ u32 current_size = 0;
+
+ while (offset < bytes) { // this element is in bounds
+ const oi::FolderDirent* dirent = reinterpret_cast(data + offset);
+ auto vstat = validate_normal_dirent(dirent);
+ if (vstat < 0) {
+ LogError("VSTAT", "=", vstat);
+ return vstat;
+ }
+
+ s64 next_alignment = ALUP(offset, 512);
+ if ((offset + dirent->d_reclen) > next_alignment) {
+ LogError("Dirent not aligned to 512 byte sector at", offset, "leaking", offset + dirent->d_reclen - next_alignment, "bytes");
+ return -2;
+ }
+ offset += dirent->d_reclen;
+ }
+ return offset;
+}
+
+s64 validate_pfs_read(const char* data, const s64 bytes) {
+ if (bytes <= 0) return 0;
+
+ s64 offset = 0;
+
+ while (offset < bytes) { // this element is in bounds
+ const oi::PfsDirent* dirent = reinterpret_cast(data + offset);
+ if (auto ret = validate_pfs_read_dirent(dirent); ret < 0) break;
+ if (offset + dirent->d_reclen > bytes) break;
+ offset += dirent->d_reclen;
+ }
+ return offset;
+}
+
+s64 validate_pfs_getdirentries(const char* data, const s64 bytes) {
+ if (bytes < 0) return bytes;
+
+ s64 offset = 0;
+
+ while (offset < bytes) { // this element is in bounds
+ const oi::FolderDirent* dirent = reinterpret_cast(data + offset);
+ if (auto ret = validate_pfs_getdirentries_dirent(dirent); ret < 0) break;
+ if (offset + dirent->d_reclen > bytes) break;
+ offset += dirent->d_reclen;
+ }
+ return offset;
+}
+
+bool is_directory_relatives(const char* data) {
+ const u32 dotfinder = *reinterpret_cast(data);
+ return ((dotfinder & 0x0000FFFF) == 0x002e) || ((dotfinder & 0x00FFFFFF) == 0x002e2e);
+}
+
+int32_t touch(const char* path) {
+ return sceKernelClose(sceKernelOpen(path, O_CREAT | O_WRONLY | O_TRUNC, 0777));
+}
+
+int32_t touch(const std::string& path) {
+ return sceKernelClose(sceKernelOpen(path.c_str(), O_CREAT | O_WRONLY | O_TRUNC, 0777));
+}
+
+void Obliterate(const char* path) {
+ Log("<< rm -rf [", path, "] >>");
+ std::error_code ec {};
+
+ std::vector entries;
+ for (auto& p: fs::recursive_directory_iterator(path, fs::directory_options::skip_permission_denied, ec))
+ entries.push_back(p.path().string());
+
+ for (auto it = entries.rbegin(); it != entries.rend(); ++it) {
+ if (ec) {
+ LogError("Exception: [", ec.value(), "] :", ec.message());
+ ec.clear();
+ continue;
+ }
+
+ const char* pp = it->c_str();
+
+ // see what sticks
+ errno = 0;
+ if (0 == sceKernelUnlink(pp)) continue;
+ errno = 0;
+ if (0 == sceKernelRmdir(pp)) continue;
+ LogError("Cannot remove [", pp, "] ( errno =", errno, ")");
+ }
+ if (0 != sceKernelRmdir(path) && errno == ENOENT) LogError("Cannot remove [", path, "] ( errno =", errno, ")");
+
+ LogSuccess(">> rm -rf [", path, "] <<");
+ return;
+}
+
+s64 get_stat_size(const char* path) {
+ OrbisKernelStat st {};
+ if (auto tmp = sceKernelStat(path, &st); tmp != 0) return tmp;
+ return st.st_size;
+}
+
+void RegenerateDir(const char* path) {
+ Obliterate(path);
+ sceKernelMkdir(path, 0777);
+}
diff --git a/tests/code/filesystem_dirents/code/log.cpp b/tests/code/filesystem_dirents/code/log.cpp
new file mode 100644
index 00000000..1680768a
--- /dev/null
+++ b/tests/code/filesystem_dirents/code/log.cpp
@@ -0,0 +1,60 @@
+#include "log.h"
+
+#include
+#include
+
+namespace Style {
+static const unsigned style_size = __enum_end + 1;
+
+static const char* styles[style_size] = {
+ "\033[0m", "\033[1m", // res, bold
+ "\033[22m", // notbold
+ "\033[30m", "\033[31m", "\033[32m", "\033[33m", "\033[34m", "\033[35m", "\033[36m", "\033[37m", // FG
+ "", // end
+};
+
+} // namespace Style
+
+const char* GetSt(Style::Style style) {
+ using namespace Style;
+ if (style < style_size) return styles[style];
+ return styles[style_size - 1];
+}
+
+std::ostream& center(std::ostream& os, const std::string& s, int width) {
+ int len = (int)s.size();
+ if (width <= len) return os << s.substr(0, width);
+ int left = (width - len) / 2;
+ int right = width - len - left;
+ return os << std::string(left, ' ') << s << std::string(right, ' ');
+}
+
+std::string center(const std::string& s, int width) {
+ int len = (int)s.size();
+ if (width <= len) return s.substr(0, width);
+ int left = (width - len) / 2;
+ int right = width - len - left;
+ return std::string(std::string(left, ' ') + s + std::string(right, ' '));
+}
+
+std::ostream& right(std::ostream& os, const std::string& s, int width) {
+ int len = (int)s.size();
+ if (width <= len) return os << s.substr(0, width);
+ int left = (width - len);
+ return os << std::string(left, ' ') << s;
+}
+
+std::string right(const std::string& s, int width) {
+ int len = (int)s.size();
+ if (width <= len) return s.substr(0, width);
+ int left = (width - len);
+ return std::string(std::string(left, ' ') + s);
+}
+
+std::string to_hex_string(const void* data, long long length, std::string sep) {
+ std::ostringstream oss {};
+ for (auto i = 0; i < length; i++) {
+ oss << std::hex << std::setw(2) << std::setfill('0') << (0xFF & static_cast(*(reinterpret_cast(data) + i))) << sep;
+ }
+ return oss.str();
+}
\ No newline at end of file
diff --git a/tests/code/filesystem_dirents/code/log.h b/tests/code/filesystem_dirents/code/log.h
new file mode 100644
index 00000000..67994c3b
--- /dev/null
+++ b/tests/code/filesystem_dirents/code/log.h
@@ -0,0 +1,104 @@
+#ifndef LOG_H
+#define LOG_H
+
+#pragma once
+
+#include
+#include
+#include
+
+#define STR(x) std::to_string(x)
+
+namespace Style {
+typedef enum Style: unsigned {
+ RESET = 0,
+ BOLD,
+ NOTBOLD,
+ FG_BLACK,
+ FG_RED,
+ FG_GREEN,
+ FG_YELLOW,
+ FG_BLUE,
+ FG_MAGENTA,
+ FG_CYAN,
+ FG_WHITE,
+ __enum_end,
+} Style;
+
+} // namespace Style
+
+const char* GetSt(Style::Style code);
+
+std::ostream& center(std::ostream& os, const std::string& s, int width);
+std::string center(const std::string& s, int width);
+std::ostream& right(std::ostream& os, const std::string& s, int width);
+std::string right(const std::string& s, int width);
+
+template
+std::string to_octal(T value) {
+ std::ostringstream oss;
+ oss << std::oct << value;
+ return oss.str();
+}
+
+template
+std::string to_hex(T value) {
+ std::ostringstream oss;
+ oss << std::hex << value;
+ return std::string(oss.str());
+}
+
+std::string to_hex_string(const void* data, long long length, std::string sep = " ");
+
+template
+void LogCustom(const char* fn, bool show_line, const char* msg, Args&&... args) {
+ std::cout << GetSt(Style::RESET) << "[" << center(fn, 20) << "] " << msg;
+ ((std::cout << " " << args), ...);
+ std::cout << GetSt(Style::RESET);
+ if (show_line) {
+ std::cout << " ( " << __FILE__ << ":" << __LINE__ << " )";
+ }
+
+ std::cout << std::endl;
+}
+
+extern int error_counter;
+
+int GetErrorCounter(void);
+void ResetErrorCounter(void);
+
+#define Log(...) \
+ { \
+ LogCustom(__FUNCTION__, false, " [INFO]", ##__VA_ARGS__); \
+ }
+
+#define LogTest(...) \
+ { \
+ LogCustom(__FUNCTION__, false, GetSt(Style::BOLD), GetSt(Style::FG_BLUE), "[TEST]", GetSt(Style::RESET), ##__VA_ARGS__); \
+ }
+
+#define LogError(...) \
+ { \
+ LogCustom(__FUNCTION__, true, GetSt(Style::BOLD), GetSt(Style::FG_RED), "[FAIL]", GetSt(Style::RESET), ##__VA_ARGS__); \
+ }
+
+#define LogWarning(...) \
+ { \
+ LogCustom(__FUNCTION__, true, GetSt(Style::BOLD), GetSt(Style::FG_YELLOW), "[WARN]", GetSt(Style::RESET), ##__VA_ARGS__); \
+ }
+
+#define LogSuccess(...) \
+ { \
+ LogCustom(__FUNCTION__, false, GetSt(Style::BOLD), GetSt(Style::FG_GREEN), "[SUCC]", GetSt(Style::RESET), ##__VA_ARGS__); \
+ }
+
+#define TEST_CASE(cond, success_str, fail_str, ...) \
+ { \
+ if (cond) { \
+ LogSuccess(success_str, ##__VA_ARGS__); \
+ } else { \
+ LogError(fail_str, ##__VA_ARGS__); \
+ } \
+ }
+
+#endif // LOG_H
\ No newline at end of file
diff --git a/tests/code/filesystem_dirents/code/main.cpp b/tests/code/filesystem_dirents/code/main.cpp
new file mode 100644
index 00000000..e6f77a44
--- /dev/null
+++ b/tests/code/filesystem_dirents/code/main.cpp
@@ -0,0 +1,34 @@
+#include "fs_test.h"
+#include "log.h"
+
+#include
+#include
+
+IMPORT_TEST_GROUP(DirentTests);
+
+int main(int ac, char** av) {
+ // No buffering
+ setvbuf(stdout, NULL, _IONBF, 0);
+
+ // Log tests start
+ Log();
+ Log("<<<< TESTS START >>>>");
+ Log();
+
+ Log("<<<< Available config options >>>>");
+ Log("<<<< nofuzz - skip fuzzing tests");
+ Log("Create an entry in /data/ender_conf to activate");
+ Log();
+
+ // Run file system tests
+ int result = RUN_ALL_TESTS(ac, av);
+
+ // Log tests end
+ Log();
+ Log("<<<< TESTS END >>>>");
+ Log();
+
+ sceSystemServiceLoadExec("EXIT", nullptr);
+ return 0;
+ // return result;
+}
diff --git a/tests/code/filesystem_dirents/code/read_variants/normal_getdirentries.h b/tests/code/filesystem_dirents/code/read_variants/normal_getdirentries.h
new file mode 100644
index 00000000..98394a33
--- /dev/null
+++ b/tests/code/filesystem_dirents/code/read_variants/normal_getdirentries.h
@@ -0,0 +1,90 @@
+#include "../fs_test.h"
+
+#include
+
+std::vector normal_dirent_variants = {
+ {.size = 0, .offset = 0}, // 170 EINVAL 0 22 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+ {.size = 128, .offset = 128}, // 170 EINVAL 128 22 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+ {.size = 512, .offset = 1024}, // 1024 512 1536 0 05d60c011c00081066696c656e616d65
+ {.size = 128, .offset = 128}, // 170 EINVAL 128 22 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+ {.size = 512, .offset = 0}, // 0 512 512 0 ddd50c010c0004012e000000dad50c01
+ {.size = 512, .offset = 16}, // 16 496 512 0 0c0004022e2e0000ded50c010c000801
+ {.size = 512, .offset = 24}, // 24 488 512 0 ded50c010c00080161000000dfd50c01
+ {.size = 512, .offset = 28}, // 28 484 512 0 0c00080161000000dfd50c010c000802
+ {.size = 512, .offset = 32}, // 32 480 512 0 61000000dfd50c010c00080261610000
+ {.size = 512, .offset = 40}, // 40 472 512 0 0c00080261610000e0d50c010c000803
+ {.size = 512, .offset = 47}, // 47 465 512 0 00e0d50c010c00080361616100e1d50c
+ {.size = 512, .offset = 48}, // 48 464 512 0 e0d50c010c00080361616100e1d50c01
+ {.size = 512, .offset = 49}, // 49 463 512 0 d50c010c00080361616100e1d50c0110
+ {.size = 512, .offset = 50}, // 50 462 512 0 0c010c00080361616100e1d50c011000
+ {.size = 512, .offset = 51}, // 51 461 512 0 010c00080361616100e1d50c01100008
+ {.size = 512, .offset = 52}, // 52 460 512 0 0c00080361616100e1d50c0110000804
+ {.size = 512, .offset = 53}, // 53 459 512 0 00080361616100e1d50c011000080461
+ {.size = 512, .offset = 54}, // 54 458 512 0 080361616100e1d50c01100008046161
+ {.size = 512, .offset = 55}, // 55 457 512 0 0361616100e1d50c0110000804616161
+ {.size = 512, .offset = 56}, // 56 456 512 0 61616100e1d50c011000080461616161
+ {.size = 512, .offset = 57}, // 57 455 512 0 616100e1d50c01100008046161616100
+ {.size = 512, .offset = 64}, // 64 448 512 0 100008046161616100000000e2d50c01
+ {.size = 512, .offset = 128}, // 128 384 512 0 e5d50c011400080a6161616161616161
+ {.size = 512, .offset = 512}, // 512 512 1024 0 f3d50c011c00081066696c656e616d65
+ {.size = 513, .offset = 0}, // 0 512 512 0 ddd50c010c0004012e000000dad50c01
+ {.size = 536, .offset = 0}, // 0 512 512 0 ddd50c010c0004012e000000dad50c01
+ {.size = 64, .offset = 1008}, // 1008 16 1024 0 78743331000000000000000000000000
+ {.size = 64, .offset = 1011}, // 1011 13 1024 0 31000000000000000000000000aaaaaa
+ {.size = 64, .offset = 1012}, // 1012 12 1024 0 000000000000000000000000aaaaaaaa
+ {.size = 64, .offset = 1015}, // 1015 9 1024 0 000000000000000000aaaaaaaaaaaaaa
+ {.size = 64, .offset = 1016}, // 1016 8 1024 0 0000000000000000aaaaaaaaaaaaaaaa
+ {.size = 64, .offset = 1017}, // 1017 7 1024 0 00000000000000aaaaaaaaaaaaaaaaaa
+ {.size = 80, .offset = 1015}, // 1015 9 1024 0 000000000000000000aaaaaaaaaaaaaa
+ {.size = 80, .offset = 1016}, // 1016 8 1024 0 0000000000000000aaaaaaaaaaaaaaaa
+ {.size = 80, .offset = 1017}, // 1017 7 1024 0 00000000000000aaaaaaaaaaaaaaaaaa
+ {.size = 1023, .offset = 0}, // 0 512 512 0 ddd50c010c0004012e000000dad50c01
+ {.size = 1024, .offset = 0}, // 0 1024 1024 0 ddd50c010c0004012e000000dad50c01
+ {.size = 1024, .offset = 511}, // 511 513 1024 0 00f3d50c011c00081066696c656e616d
+ {.size = 1024, .offset = 512}, // 512 1024 1536 0 f3d50c011c00081066696c656e616d65
+ {.size = 1024, .offset = 513}, // 513 1023 1536 0 d50c011c00081066696c656e616d6564
+ {.size = 1025, .offset = 513}, // 513 1023 1536 0 d50c011c00081066696c656e616d6564
+ {.size = 1026, .offset = 513}, // 513 1023 1536 0 d50c011c00081066696c656e616d6564
+ {.size = 256, .offset = 256}, // 256 256 512 0 00000000ead50c011c00081066696c65
+ {.size = 23, .offset = 511}, // 511 1 512 0 00aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+ {.size = 24, .offset = 511}, // 511 1 512 0 00aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+ {.size = 25, .offset = 511}, // 511 1 512 0 00aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+ {.size = 8, .offset = 504}, // 504 8 512 0 7874313300000000aaaaaaaaaaaaaaaa
+ {.size = 16, .offset = 496}, // 496 16 512 0 6e616d65646f74657874313300000000
+ {.size = 24, .offset = 488}, // 488 24 512 0 1c00081066696c656e616d65646f7465
+ {.size = 48, .offset = 464}, // 464 48 512 0 66696c656e616d65646f746578743132
+ {.size = 64, .offset = 448}, // 448 64 512 0 7874313100000000f1d50c011c000810
+ {.size = 128, .offset = 384}, // 384 128 512 0 6e616d65646f74657874303900000000
+ {.size = 256, .offset = 256}, // 256 256 512 0 00000000ead50c011c00081066696c65
+ {.size = 511, .offset = 1}, // 1 511 512 0 d50c010c0004012e000000dad50c010c
+ {.size = 32, .offset = 4064}, // 4064 32 4096 0 676e616d653037000000000000000000
+ {.size = 64, .offset = 4064}, // 4064 32 4096 0 676e616d653037000000000000000000
+ {.size = 80, .offset = 4064}, // 4064 32 4096 0 676e616d653037000000000000000000
+ {.size = 112, .offset = 4064}, // 4064 32 4096 0 676e616d653037000000000000000000
+ {.size = 128, .offset = 4064}, // 4064 32 4096 0 676e616d653037000000000000000000
+ {.size = 256, .offset = 4064}, // 4064 32 4096 0 676e616d653037000000000000000000
+ {.size = 544, .offset = 4064}, // 4064 544 4608 0 676e616d653037000000000000000000
+ {.size = 1024, .offset = 0}, // 0 1024 1024 0 ddd50c010c0004012e000000dad50c01
+ {.size = 32, .offset = 480}, // 480 32 512 0 00000000f2d50c011c00081066696c65
+ {.size = 1024, .offset = 10000}, // 10000 0 10000 0 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+ {.size = 8192, .offset = 10000}, // 10000 0 10000 0 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+ {.size = 8192, .offset = 35565}, // 35565 0 35565 0 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+ {.size = 511, .offset = 1024}, // 170 EINVAL 1024 22 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+ {.size = 128, .offset = 4096}, // 170 EINVAL 4096 22 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+ {.size = 1024, .offset = 0x00000000000000FF}, // 255 769 1024 0 3400000000ead50c011c00081066696c
+ {.size = 1024, .offset = 0x000000000000FF00}, // 65280 0 65280 0 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+ {.size = 1024, .offset = 0x0000000000FF0000}, // 16711680 0 16711680 0 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+ {.size = 1024, .offset = 0x00000000FF000000}, // 4278190080 0 4278190080 0 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+ {.size = 1024, .offset = 0x000000FF00000000}, // 1095216660480 0 1095216660480 0 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+ {.size = 1024, .offset = 0x0000FF0000000000}, // 280375465082880 0 280375465082880 0 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+ {.size = 1024, .offset = 0x00FF000000000000}, // 71776119061217280 0 71776119061217280 0 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+ {.size = 1024, .offset = s64(0xFF00000000000000)}, // 0 1024 1024 0 ddd50c010c0004012e000000dad50c01
+
+ {.size = 1024, .offset = 65000}, //
+ {.size = 1024, .offset = 65023}, //
+ {.size = 1024, .offset = 65024}, //
+ {.size = 1024, .offset = 65025}, //
+ {.size = 1024, .offset = 70123}, //
+ {.size = 1024, .offset = 92616}, //
+ {.size = 1024, .offset = 92544}, //
+};
diff --git a/tests/code/filesystem_dirents/code/read_variants/normal_lseek.h b/tests/code/filesystem_dirents/code/read_variants/normal_lseek.h
new file mode 100644
index 00000000..fc02512c
--- /dev/null
+++ b/tests/code/filesystem_dirents/code/read_variants/normal_lseek.h
@@ -0,0 +1,83 @@
+#ifndef NORMAL_LSEEK_H
+#define NORMAL_LSEEK_H
+
+#pragma once
+
+#include "../fs_test.h"
+
+#include
+
+std::vector normal_lseek_variants = {
+ {.offset = 0, .whence = 0}, // 0 0 0 -> 0 0 -> 0 0
+ {.offset = -123, .whence = 0}, // 0 -123 0 -> EINVAL 22 -> EINVAL 22
+ {.offset = 123456, .whence = 0}, // 0 123456 0 -> 123456 0 -> 123456 0
+ {.offset = 60, .whence = 0}, // 0 60 0 -> 60 0 -> 60 0
+ {.offset = 0, .whence = 1}, // 123456 0 1 -> 60 0 -> 60 0
+ {.offset = 24, .whence = 1}, // 60 24 1 -> 84 0 -> 84 0
+ {.offset = -24, .whence = 1}, // 60 -24 1 -> 60 0 -> 60 0
+ {.offset = -6666, .whence = 1}, // 84 -6666 1 -> EINVAL 22 -> EINVAL 22
+ {.offset = 123456, .whence = 1}, // 60 123456 1 -> 123516 0 -> 123516 0
+ {.offset = 0, .whence = 2}, // 60 0 2 -> 8704 0 -> 8704 0
+ {.offset = 123456, .whence = 2}, // 123516 123456 2 -> 132160 0 -> 132160 0
+ {.offset = 100, .whence = 2}, // 8704 100 2 -> 8804 0 -> 8804 0
+ {.offset = -100, .whence = 2}, // 132160 -100 2 -> 8604 0 -> 8604 0
+ {.offset = -100000, .whence = 2}, // 8804 -100000 2 -> EINVAL 22 -> EINVAL 22
+ {.offset = 0, .whence = 3}, // 0 0 3 -> ENOTTY 25 -> ENOTTY 25
+ {.offset = 8, .whence = 3}, // 1 8 3 -> ENOTTY 25 -> ENOTTY 25
+ {.offset = 16, .whence = 3}, // 1 16 3 -> ENOTTY 25 -> ENOTTY 25
+ {.offset = 24, .whence = 3}, // 1 24 3 -> ENOTTY 25 -> ENOTTY 25
+ {.offset = 32, .whence = 3}, // 1 32 3 -> ENOTTY 25 -> ENOTTY 25
+ {.offset = 40, .whence = 3}, // 1 40 3 -> ENOTTY 25 -> ENOTTY 25
+ {.offset = 10240, .whence = 3}, // 1 10240 3 -> ENOTTY 25 -> ENOTTY 25
+ {.offset = -1024, .whence = 3}, // 1 -1024 3 -> ENOTTY 25 -> ENOTTY 25
+ {.offset = -10240, .whence = 3}, // 1 -10240 3 -> ENOTTY 25 -> ENOTTY 25
+ {.offset = 0, .whence = 4}, // 1 0 4 -> ENOTTY 25 -> ENOTTY 25
+ {.offset = 8, .whence = 4}, // 1 8 4 -> ENOTTY 25 -> ENOTTY 25
+ {.offset = 16, .whence = 4}, // 1 16 4 -> ENOTTY 25 -> ENOTTY 25
+ {.offset = 24, .whence = 4}, // 1 24 4 -> ENOTTY 25 -> ENOTTY 25
+ {.offset = 32, .whence = 4}, // 1 32 4 -> ENOTTY 25 -> ENOTTY 25
+ {.offset = 40, .whence = 4}, // 1 40 4 -> ENOTTY 25 -> ENOTTY 25
+ {.offset = 10240, .whence = 4}, // 1 10240 4 -> ENOTTY 25 -> ENOTTY 25
+ {.offset = -1024, .whence = 4}, // 1 -1024 4 -> ENOTTY 25 -> ENOTTY 25
+ {.offset = -10240, .whence = 4}, // 1 -10240 4 -> ENOTTY 25 -> ENOTTY 25
+ {.offset = s64(0xFFFFFFFFFFFFFFFF), .whence = 0}, // 1 -1 0 -> EINVAL 22 -> EINVAL 22
+ {.offset = s64(0xFFFFFFFFFFFFFFFE), .whence = 0}, // 1 -2 0 -> EINVAL 22 -> EINVAL 22
+ {.offset = 0xFFFFFFFFFFFFFF, .whence = 0}, // 1 72057594037927935 0 -> 72057594037927935 0 -> 72057594037927935 0
+ {.offset = 0xFFFFFFFFFFFFFE, .whence = 0}, // 1 72057594037927934 0 -> 72057594037927934 0 -> 72057594037927934 0
+ {.offset = 0xFFFFFFFFFFFF, .whence = 0}, // 72057594037927935 281474976710655 0 -> 281474976710655 0 -> 281474976710655 0
+ {.offset = 0xFFFFFFFFFFFE, .whence = 0}, // 72057594037927934 281474976710654 0 -> 281474976710654 0 -> 281474976710654 0
+ {.offset = 0xFFFFFFFFFF, .whence = 0}, // 281474976710655 1099511627775 0 -> 1099511627775 0 -> 1099511627775 0
+ {.offset = 0xFFFFFFFFFE, .whence = 0}, // 281474976710654 1099511627774 0 -> 1099511627774 0 -> 1099511627774 0
+ {.offset = 0xFFFFFFFF, .whence = 0}, // 1099511627775 4294967295 0 -> 4294967295 0 -> 4294967295 0
+ {.offset = 0xFFFFFFFE, .whence = 0}, // 1099511627774 4294967294 0 -> 4294967294 0 -> 4294967294 0
+ {.offset = 0xEFFFFFFF, .whence = 0}, // 4294967295 4026531839 0 -> 4026531839 0 -> 4026531839 0
+ {.offset = 0xEFFFFFFE, .whence = 0}, // 4294967294 4026531838 0 -> 4026531838 0 -> 4026531838 0
+ {.offset = 0xDFFFFFFF, .whence = 0}, // 4026531839 3758096383 0 -> 3758096383 0 -> 3758096383 0
+ {.offset = 0xDFFFFFFE, .whence = 0}, // 4026531838 3758096382 0 -> 3758096382 0 -> 3758096382 0
+ {.offset = 0xCFFFFFFF, .whence = 0}, // 3758096383 3489660927 0 -> 3489660927 0 -> 3489660927 0
+ {.offset = 0xCFFFFFFE, .whence = 0}, // 3758096382 3489660926 0 -> 3489660926 0 -> 3489660926 0
+ {.offset = 0xBFFFFFFF, .whence = 0}, // 3489660927 3221225471 0 -> 3221225471 0 -> 3221225471 0
+ {.offset = 0xBFFFFFFE, .whence = 0}, // 3489660926 3221225470 0 -> 3221225470 0 -> 3221225470 0
+ {.offset = 0xAFFFFFFF, .whence = 0}, // 3221225471 2952790015 0 -> 2952790015 0 -> 2952790015 0
+ {.offset = 0xAFFFFFFE, .whence = 0}, // 3221225470 2952790014 0 -> 2952790014 0 -> 2952790014 0
+ {.offset = 0xA0000000, .whence = 0}, // 2952790015 2684354560 0 -> 2684354560 0 -> 2684354560 0
+ {.offset = 0x9FFFFFFF, .whence = 0}, // 2952790014 2684354559 0 -> 2684354559 0 -> 2684354559 0
+ {.offset = 0x9FFFFFFE, .whence = 0}, // 2684354560 2684354558 0 -> 2684354558 0 -> 2684354558 0
+ {.offset = 0x90000000, .whence = 0}, // 2684354559 2415919104 0 -> 2415919104 0 -> 2415919104 0
+ {.offset = 0x8FFFFFFF, .whence = 0}, // 2684354558 2415919103 0 -> 2415919103 0 -> 2415919103 0
+ {.offset = 0x8FFFFFFE, .whence = 0}, // 2415919104 2415919102 0 -> 2415919102 0 -> 2415919102 0
+ {.offset = 0x80000000, .whence = 0}, // 2415919103 2147483648 0 -> 2147483648 0 -> 2147483648 0
+ {.offset = 0x7FFFFFFF, .whence = 0}, // 2415919102 2147483647 0 -> 2147483647 0 -> 2147483647 0
+ {.offset = 0x7FFFFFFE, .whence = 0}, // 2147483648 2147483646 0 -> 2147483646 0 -> 2147483646 0
+ {.offset = 0x70000000, .whence = 0}, // 2147483647 1879048192 0 -> 1879048192 0 -> 1879048192 0
+ {.offset = 0x6FFFFFFF, .whence = 0}, // 2147483646 1879048191 0 -> 1879048191 0 -> 1879048191 0
+ {.offset = 0x6FFFFFFE, .whence = 0}, // 1879048192 1879048190 0 -> 1879048190 0 -> 1879048190 0
+ {.offset = 0xFFFFFF, .whence = 0}, // 1879048191 16777215 0 -> 16777215 0 -> 16777215 0
+ {.offset = 0xFFFFFE, .whence = 0}, // 1879048190 16777214 0 -> 16777214 0 -> 16777214 0
+ {.offset = 0xFFFF, .whence = 0}, // 16777215 65535 0 -> 65535 0 -> 65535 0
+ {.offset = 0xFFFE, .whence = 0}, // 16777214 65534 0 -> 65534 0 -> 65534 0
+ {.offset = 0xFF, .whence = 0}, // 65535 255 0 -> 255 0 -> 255 0
+ {.offset = 0xFE, .whence = 0}, // 65534 254 0 -> 254 0 -> 254 0
+};
+
+#endif // NORMAL_LSEEK_H
\ No newline at end of file
diff --git a/tests/code/filesystem_dirents/code/read_variants/normal_read.h b/tests/code/filesystem_dirents/code/read_variants/normal_read.h
new file mode 100644
index 00000000..42e992c4
--- /dev/null
+++ b/tests/code/filesystem_dirents/code/read_variants/normal_read.h
@@ -0,0 +1,36 @@
+#include "../fs_test.h"
+
+#include
+
+// read size, read offset // HW return, HW end position
+std::vector normal_read_variants = {
+ {.size = 0, .offset = 0}, // 0 0 -> 0 0 0 -> 0 0 0 -> aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+ {.size = 64, .offset = 0}, // 64 0 -> 0 64 64 -> 0 64 64 -> dad50c010c0004012e000000d8d50c01
+ {.size = 128, .offset = 0}, // 128 0 -> 0 128 128 -> 0 128 128 -> dad50c010c0004012e000000d8d50c01
+ {.size = 256, .offset = 0}, // 256 0 -> 0 256 256 -> 0 256 256 -> dad50c010c0004012e000000d8d50c01
+ {.size = 511, .offset = 0}, // 511 0 -> 0 511 511 -> 0 511 511 -> dad50c010c0004012e000000d8d50c01
+ {.size = 511, .offset = 1}, // 511 1 -> 1 511 512 -> 1 511 512 -> d50c010c0004012e000000d8d50c010c
+ {.size = 511, .offset = 2}, // 511 2 -> 2 511 513 -> 2 511 513 -> 0c010c0004012e000000d8d50c010c00
+ {.size = 512, .offset = 0}, // 512 0 -> 0 512 512 -> 0 512 512 -> dad50c010c0004012e000000d8d50c01
+ {.size = 2048, .offset = 1245}, // 2048 1245 -> 1245 2048 3293 -> 1245 2048 3293 -> 000000e2d60c011c00081066696c656e
+ {.size = 7257, .offset = 1245}, // 7257 1245 -> 1245 7257 8502 -> 1245 7257 8502 -> 000000e2d60c011c00081066696c656e
+ {.size = 418, .offset = 574}, // 418 574 -> 574 418 992 -> 574 418 992 -> 081066696c656e616d65646f74657874
+ {.size = 9363, .offset = 1111}, // 9363 1111 -> 1111 7593 8704 -> 1111 7593 8704 -> 011c00081066696c656e616d65646f74
+ {.size = 37865, .offset = 936}, // 37865 936 -> 936 7768 8704 -> 936 7768 8704 -> 1c00081066696c656e616d65646f7465
+ {.size = 17543, .offset = 1245}, // 17543 1245 -> 1245 7459 8704 -> 1245 7459 8704 -> 000000e2d60c011c00081066696c656e
+ {.size = 1024, .offset = 35565}, // 1024 35565 -> 35565 0 35565 -> 35565 0 35565 -> aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+ {.size = 512, .offset = 65534}, // 512 65534 -> 65534 0 65534 -> 65534 0 65534 -> aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+ {.size = 2048, .offset = 65534}, // 2048 65534 -> 65534 0 65534 -> 65534 0 65534 -> aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+ {.size = 4096, .offset = 8192}, // 4096 8192 -> 8192 512 8704 -> 8192 512 8704 -> 7bd70c014000083466696c6577697468
+ {.size = 1024, .offset = 8000}, // 1024 8000 -> 8000 704 8704 -> 8000 704 8704 -> 78d70c014000083466696c6577697468
+ {.size = 1024, .offset = 10000}, // 1024 10000 -> 10000 0 10000 -> 10000 0 10000 -> aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+ {.size = 4096, .offset = 10000}, // 4096 10000 -> 10000 0 10000 -> 10000 0 10000 -> aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+
+ {.size = 1024, .offset = 65000}, //
+ {.size = 1024, .offset = 65023}, //
+ {.size = 1024, .offset = 65024}, //
+ {.size = 1024, .offset = 65025}, //
+ {.size = 1024, .offset = 70123}, //
+ {.size = 1024, .offset = 92616}, //
+ {.size = 1024, .offset = 92544}, //
+};
diff --git a/tests/code/filesystem_dirents/code/read_variants/pfs_getdirentries.h b/tests/code/filesystem_dirents/code/read_variants/pfs_getdirentries.h
new file mode 100755
index 00000000..deb96c39
--- /dev/null
+++ b/tests/code/filesystem_dirents/code/read_variants/pfs_getdirentries.h
@@ -0,0 +1,133 @@
+#include "../fs_test.h"
+
+#include
+
+// read size, read offset // HW basep, HW return, HW end position
+std::vector pfs_dirent_variants = {
+
+ /**
+ * Final writeup:
+ * 1. offset + read size MUST break any 512b alignment before attempting to read
+ * offset+size=read 0+(<512), 256+(<256) BUT 511+16=0
+ */
+
+ /**
+ What i (again) think is that the entire 512byte buffer must be iterated? or sth
+ read can occur as long as read descriptor passes 512aligned mark, i.e.
+ it will read a couple of bytes if end position falls couple of bytes after the end
+ for example read 8@510 offset will read 2 bytes
+ 2 bytes, because thet's the farthest the current sector can go
+ however this is a bit different for larger reads. large reads still have this condition, but they include every buffer on their way
+ for PFS any uneven read backs off to the earliest full dirent, except if it cannot backtrack (like <24 will skip [.] and jump to [..], i.e. going
+ forward)
+
+ so the only way this can read stuff is when end position crosses current sector border
+ otherwise EINVAL
+
+ apart from that i think it's a classic as before, end of read must appear to be after 512b alignment mark
+ but reading from that
+ */
+
+ /**
+ * Apparent end crosses sector end - sector is read
+ * Apparent end doesn't cross sector end - everything from that sector is omitted
+ *
+ * Read start
+ */
+
+ // apparent end = offset + length before checking dirents
+
+ {.size = 0, .offset = 0}, // 0 0 -> 1 (0) EINVAL 0 22 -> 170 EINVAL 0 22 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+ {.size = 128, .offset = 128}, // 128 128 -> 1 (128) EINVAL 128 22 -> 170 EINVAL 128 22 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+ {.size = 512, .offset = 1024}, // 512 1024 -> 1024 (1056) 480 1504 0 -> 1024 480 1504 0 280000002800081066696c656e616d65
+ {.size = 128, .offset = 128}, // 128 128 -> 1 (128) EINVAL 128 22 -> 170 EINVAL 128 22 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+ {.size = 512, .offset = 0}, // 512 0 -> 0 (0) 496 496 0 -> 0 496 496 0 07000000180004012e00000000000000
+ {.size = 512, .offset = 16}, // 512 16 -> 16 (24) 472 488 0 -> 16 472 488 0 03000000180004022e2e000000000000
+ {.size = 512, .offset = 24}, // 512 24 -> 24 (24) 472 496 0 -> 24 472 496 0 03000000180004022e2e000000000000
+ {.size = 512, .offset = 28}, // 512 28 -> 28 (48) 448 476 0 -> 28 448 476 0 0c000000180008016100000000000000
+ {.size = 512, .offset = 32}, // 512 32 -> 32 (48) 448 480 0 -> 32 448 480 0 0c000000180008016100000000000000
+ {.size = 512, .offset = 40}, // 512 40 -> 40 (48) 448 488 0 -> 40 448 488 0 0c000000180008016100000000000000
+ {.size = 512, .offset = 47}, // 512 47 -> 47 (48) 448 495 0 -> 47 448 495 0 0c000000180008016100000000000000
+ {.size = 512, .offset = 48}, // 512 48 -> 48 (48) 448 496 0 -> 48 448 496 0 0c000000180008016100000000000000
+ {.size = 512, .offset = 49}, // 512 49 -> 49 (72) 424 473 0 -> 49 424 473 0 0d000000180008026161000000000000
+ {.size = 512, .offset = 50}, // 512 50 -> 50 (72) 424 474 0 -> 50 424 474 0 0d000000180008026161000000000000
+ {.size = 512, .offset = 51}, // 512 51 -> 51 (72) 424 475 0 -> 51 424 475 0 0d000000180008026161000000000000
+ {.size = 512, .offset = 52}, // 512 52 -> 52 (72) 424 476 0 -> 52 424 476 0 0d000000180008026161000000000000
+ {.size = 512, .offset = 53}, // 512 53 -> 53 (72) 424 477 0 -> 53 424 477 0 0d000000180008026161000000000000
+ {.size = 512, .offset = 54}, // 512 54 -> 54 (72) 424 478 0 -> 54 424 478 0 0d000000180008026161000000000000
+ {.size = 512, .offset = 55}, // 512 55 -> 55 (72) 424 479 0 -> 55 424 479 0 0d000000180008026161000000000000
+ {.size = 512, .offset = 56}, // 512 56 -> 56 (72) 424 480 0 -> 56 424 480 0 0d000000180008026161000000000000
+ {.size = 512, .offset = 57}, // 512 57 -> 57 (72) 424 481 0 -> 57 424 481 0 0d000000180008026161000000000000
+ {.size = 512, .offset = 64}, // 512 64 -> 64 (72) 424 488 0 -> 64 424 488 0 0d000000180008026161000000000000
+ {.size = 512, .offset = 128}, // 512 128 -> 128 (144) 352 480 0 -> 128 352 480 0 10000000180008056161616161000000
+ {.size = 512, .offset = 512}, // 512 512 -> 512 (536) 480 992 0 -> 512 480 992 0 1b0000002800081066696c656e616d65
+ {.size = 513, .offset = 0}, // 513 0 -> 0 (0) 496 496 0 -> 0 496 496 0 07000000180004012e00000000000000
+ {.size = 536, .offset = 0}, // 536 0 -> 0 (0) 496 496 0 -> 0 496 496 0 07000000180004012e00000000000000
+ {.size = 64, .offset = 1008}, // 64 1008 -> 1008 (1016) 0 1008 0 -> 1008 0 1008 0 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+ {.size = 64, .offset = 1011}, // 64 1011 -> 1011 (1016) 0 1011 0 -> 1011 0 1011 0 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+ {.size = 64, .offset = 1012}, // 64 1012 -> 1012 (1016) 0 1012 0 -> 1012 0 1012 0 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+ {.size = 64, .offset = 1015}, // 64 1015 -> 1015 (1016) 0 1015 0 -> 1015 0 1015 0 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+ {.size = 64, .offset = 1016}, // 64 1016 -> 1016 (1016) 0 1016 0 -> 1016 0 1016 0 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+ {.size = 64, .offset = 1017}, // 64 1017 -> 1017 (1056) 0 1017 0 -> 1017 0 1017 0 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+ {.size = 80, .offset = 1015}, // 80 1015 -> 1015 (1016) 0 1015 0 -> 1015 0 1015 0 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+ {.size = 80, .offset = 1016}, // 80 1016 -> 1016 (1016) 0 1016 0 -> 1016 0 1016 0 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+ {.size = 80, .offset = 1017}, // 80 1017 -> 1017 (1056) 0 1017 0 -> 1017 0 1017 0 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+ {.size = 1023, .offset = 0}, // 1023 0 -> 0 (0) 496 496 0 -> 0 496 496 0 07000000180004012e00000000000000
+ {.size = 1024, .offset = 0}, // 1024 0 -> 0 (0) 1016 1016 0 -> 0 1016 1016 0 07000000180004012e00000000000000
+ {.size = 1024, .offset = 511}, // 1024 511 -> 511 (536) 480 991 0 -> 511 480 991 0 1b0000002800081066696c656e616d65
+ {.size = 1024, .offset = 512}, // 1024 512 -> 512 (536) 1000 1512 0 -> 512 1000 1512 0 1b0000002800081066696c656e616d65
+ {.size = 1024, .offset = 513}, // 1024 513 -> 513 (536) 1000 1513 0 -> 513 1000 1513 0 1b0000002800081066696c656e616d65
+ {.size = 1025, .offset = 513}, // 1025 513 -> 513 (536) 1000 1513 0 -> 513 1000 1513 0 1b0000002800081066696c656e616d65
+ {.size = 1026, .offset = 513}, // 1026 513 -> 513 (536) 1000 1513 0 -> 513 1000 1513 0 1b0000002800081066696c656e616d65
+ {.size = 256, .offset = 256}, // 256 256 -> 256 (256) 240 496 0 -> 256 240 496 0 140000002800081066696c656e616d65
+ {.size = 23, .offset = 511}, // 23 511 -> 511 (536) 0 511 0 -> 511 0 511 0 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+ {.size = 24, .offset = 511}, // 24 511 -> 511 (536) 0 511 0 -> 511 0 511 0 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+ {.size = 25, .offset = 511}, // 25 511 -> 511 (536) 0 511 0 -> 511 0 511 0 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+ {.size = 8, .offset = 504}, // 8 504 -> 504 (536) 0 504 0 -> 504 0 504 0 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+ {.size = 16, .offset = 496}, // 16 496 -> 496 (496) 0 496 0 -> 496 0 496 0 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+ {.size = 24, .offset = 488}, // 24 488 -> 488 (496) 0 488 0 -> 488 0 488 0 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+ {.size = 48, .offset = 464}, // 48 464 -> 464 (496) 40 504 0 -> 464 40 504 0 1a0000002800081066696c656e616d65
+ {.size = 64, .offset = 448}, // 64 448 -> 448 (456) 40 488 0 -> 448 40 488 0 190000002800081066696c656e616d65
+ {.size = 128, .offset = 384}, // 128 384 -> 384 (416) 120 504 0 -> 384 120 504 0 180000002800081066696c656e616d65
+ {.size = 256, .offset = 256}, // 256 256 -> 256 (256) 240 496 0 -> 256 240 496 0 140000002800081066696c656e616d65
+ {.size = 511, .offset = 1}, // 511 1 -> 1 (24) 472 473 0 -> 1 472 473 0 03000000180004022e2e000000000000
+ {.size = 32, .offset = 4064}, // 32 4064 -> 4064 (4104) 0 4064 0 -> 4064 0 4064 0 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+ {.size = 64, .offset = 4064}, // 64 4064 -> 4064 (4104) 0 4064 0 -> 4064 0 4064 0 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+ {.size = 80, .offset = 4064}, // 80 4064 -> 4064 (4104) 0 4064 0 -> 4064 0 4064 0 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+ {.size = 112, .offset = 4064}, // 112 4064 -> 4064 (4104) 0 4064 0 -> 4064 0 4064 0 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+ {.size = 128, .offset = 4064}, // 128 4064 -> 4064 (4104) 0 4064 0 -> 4064 0 4064 0 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+ {.size = 256, .offset = 4064}, // 256 4064 -> 4064 (4104) 0 4064 0 -> 4064 0 4064 0 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+ {.size = 544, .offset = 4064}, // 544 4064 -> 4064 (4104) 504 4568 0 -> 4064 504 4568 0 670000003800082066696c6577697468
+ {.size = 1024, .offset = 0}, // 1024 0 -> 0 (0) 1016 1016 0 -> 0 1016 1016 0 07000000180004012e00000000000000
+ {.size = 32, .offset = 480}, // 32 480 -> 480 (496) 0 480 0 -> 480 0 480 0 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+ {.size = 1024, .offset = 10000}, // 1024 10000 -> 10000 (10008) 648 65536 0 -> 10000 648 65536 0 d30000004800083466696c6577697468
+ {.size = 8192, .offset = 10000}, // 8192 10000 -> 10000 (10008) 648 65536 0 -> 10000 648 65536 0 d30000004800083466696c6577697468
+ {.size = 8192, .offset = 35565}, // 8192 35565 -> 35565 (35565) 0 65536 0 -> 35565 0 65536 0 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+ {.size = 511, .offset = 1024}, // 511 1024 -> 1 (1024) EINVAL 1024 22 -> 170 EINVAL 1024 22 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+ {.size = 128, .offset = 4096}, // 128 4096 -> 1 (4096) EINVAL 4096 22 -> 170 EINVAL 4096 22 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+
+ {.size = 1024, .offset = 65000}, //
+ {.size = 1024, .offset = 65023}, //
+ {.size = 1024, .offset = 65024}, //
+ {.size = 1024, .offset = 65025}, //
+ {.size = 1024, .offset = 70123}, //
+ {.size = 1024, .offset = 92616}, //
+ {.size = 1024, .offset = 92544}, //
+
+ // there is literally no point in testing those
+ // some of those cause something somewhere which may (or may not) crash the console
+ // for some reason only PFS has issues with these tests
+ // {.size = 1024, .offset = (s64(0xFF) << 0)}, // 1024 255 -> 255 (256) 760 1015 0 -> 255 760 1015 0 140000002800081066696c656e616d65
+ // {.size = 1024, .offset = (s64(0xFF) << 8)}, // 1024 65280 -> 65280 (65280) 0 65536 0 -> 65280 0 65536 0 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+ // {.size = 1024, .offset = (s64(0xFF) << 16)}, // 1024 16711680 -> 16711680 (16711680) 0 16711680 0 -> 16711680 0 16711680 0
+ // aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+ // {.size = 1024, .offset = (s64(0xFF) << 24)}, // 1024 4278190080 -> 4278190080 (4278190080) 0 4278190080 0 ->
+ // // 4278190080 0 4278190080 0 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+ // {.size = 1024, .offset = (s64(0xFF) << 32)}, // 1024 1095216660480 -> 1095216660480 (1095216660480) 0 1095216660480 0 ->
+ // // 1095216660480 0 1095216660480 0 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+ // {.size = 1024, .offset = (s64(0xFF) << 40)}, // 1024 280375465082880 -> 280375465082880 (280375465082880) 0 280375465082880 0 ->
+ // // 280375465082880 0 280375465082880 0 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+ // {.size = 1024, .offset = (s64(0xFF) << 48)}, // 1024 71776119061217280 -> 71776119061217280 (71776119061217280) 0 71776119061217280 0 ->
+ // // 71776119061217280 0 71776119061217280 0 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+ // {.size = 1024, .offset = (s64(0xFF) << 56)}, // 1024 -72057594037927936 -> 0 (0) 1016 1016 0 -> 0 1016 1016 0 07000000180004012e00000000000000
+};
diff --git a/tests/code/filesystem_dirents/code/read_variants/pfs_lseek.h b/tests/code/filesystem_dirents/code/read_variants/pfs_lseek.h
new file mode 100644
index 00000000..2ce4c211
--- /dev/null
+++ b/tests/code/filesystem_dirents/code/read_variants/pfs_lseek.h
@@ -0,0 +1,83 @@
+#ifndef PFS_LSEEK_H
+#define PFS_LSEEK_H
+
+#pragma once
+
+#include "../fs_test.h"
+
+#include
+
+std::vector pfs_lseek_variants = {
+ {.offset = 0, .whence = 0}, // 0 0 0 -> 0 0 -> 0 0
+ {.offset = -123, .whence = 0}, // 0 -123 0 -> EINVAL 22 -> EINVAL 22
+ {.offset = 123456, .whence = 0}, // 0 123456 0 -> 123456 0 -> 123456 0
+ {.offset = 60, .whence = 0}, // 0 60 0 -> 60 0 -> 60 0
+ {.offset = 0, .whence = 1}, // 123456 0 1 -> 60 0 -> 60 0
+ {.offset = 24, .whence = 1}, // 60 24 1 -> 84 0 -> 84 0
+ {.offset = -24, .whence = 1}, // 60 -24 1 -> 60 0 -> 60 0
+ {.offset = -6666, .whence = 1}, // 84 -6666 1 -> EINVAL 22 -> EINVAL 22
+ {.offset = 123456, .whence = 1}, // 60 123456 1 -> 123516 0 -> 123516 0
+ {.offset = 0, .whence = 2}, // 60 0 2 -> 65536 0 -> 65536 0
+ {.offset = 123456, .whence = 2}, // 123516 123456 2 -> 188992 0 -> 188992 0
+ {.offset = 100, .whence = 2}, // 65536 100 2 -> 65636 0 -> 65636 0
+ {.offset = -100, .whence = 2}, // 188992 -100 2 -> 65436 0 -> 65436 0
+ {.offset = -100000, .whence = 2}, // 65636 -100000 2 -> EINVAL 22 -> EINVAL 22
+ {.offset = 0, .whence = 3}, // 56832 0 3 -> ENOTTY 25 -> ENOTTY 25
+ {.offset = 8, .whence = 3}, // 56833 8 3 -> ENOTTY 25 -> ENOTTY 25
+ {.offset = 16, .whence = 3}, // 56833 16 3 -> ENOTTY 25 -> ENOTTY 25
+ {.offset = 24, .whence = 3}, // 56833 24 3 -> ENOTTY 25 -> ENOTTY 25
+ {.offset = 32, .whence = 3}, // 56833 32 3 -> ENOTTY 25 -> ENOTTY 25
+ {.offset = 40, .whence = 3}, // 56833 40 3 -> ENOTTY 25 -> ENOTTY 25
+ {.offset = 10240, .whence = 3}, // 56833 10240 3 -> ENOTTY 25 -> ENOTTY 25
+ {.offset = -1024, .whence = 3}, // 56833 -1024 3 -> ENOTTY 25 -> ENOTTY 25
+ {.offset = -10240, .whence = 3}, // 56833 -10240 3 -> ENOTTY 25 -> ENOTTY 25 25
+ {.offset = 0, .whence = 4}, // 56833 0 4 -> ENOTTY 25 -> ENOTTY 25
+ {.offset = 8, .whence = 4}, // 56833 8 4 -> ENOTTY 25 -> ENOTTY 25
+ {.offset = 16, .whence = 4}, // 56833 16 4 -> ENOTTY 25 -> ENOTTY 25
+ {.offset = 24, .whence = 4}, // 56833 24 4 -> ENOTTY 25 -> ENOTTY 25
+ {.offset = 32, .whence = 4}, // 56833 32 4 -> ENOTTY 25 -> ENOTTY 25
+ {.offset = 40, .whence = 4}, // 56833 40 4 -> ENOTTY 25 -> ENOTTY 25
+ {.offset = 10240, .whence = 4}, // 56833 10240 4 -> ENOTTY 25 -> ENOTTY 25
+ {.offset = -1024, .whence = 4}, // 56833 -1024 4 -> ENOTTY 25 -> ENOTTY 25
+ {.offset = -10240, .whence = 4}, // 56833 -10240 4 -> ENOTTY 25 -> ENOTTY 25
+ {.offset = s64(0xFFFFFFFFFFFFFFFF), .whence = 0}, // 56833 -1 0 -> EINVAL 22 -> EINVAL 22
+ {.offset = s64(0xFFFFFFFFFFFFFFFE), .whence = 0}, // 56833 -2 0 -> EINVAL 22 -> EINVAL 22
+ {.offset = 0xFFFFFFFFFFFFFF, .whence = 0}, // 56833 72057594037927935 0 -> 72057594037927935 0 -> 72057594037927935 0
+ {.offset = 0xFFFFFFFFFFFFFE, .whence = 0}, // 56833 72057594037927934 0 -> 72057594037927934 0 -> 72057594037927934 0
+ {.offset = 0xFFFFFFFFFFFF, .whence = 0}, // 72057594037927935 281474976710655 0 -> 281474976710655 0 -> 281474976710655 0
+ {.offset = 0xFFFFFFFFFFFE, .whence = 0}, // 72057594037927934 281474976710654 0 -> 281474976710654 0 -> 281474976710654 0
+ {.offset = 0xFFFFFFFFFF, .whence = 0}, // 281474976710655 1099511627775 0 -> 1099511627775 0 -> 1099511627775 0
+ {.offset = 0xFFFFFFFFFE, .whence = 0}, // 281474976710654 1099511627774 0 -> 1099511627774 0 -> 1099511627774 0
+ {.offset = 0xFFFFFFFF, .whence = 0}, // 1099511627775 4294967295 0 -> 4294967295 0 -> 4294967295 0
+ {.offset = 0xFFFFFFFE, .whence = 0}, // 1099511627774 4294967294 0 -> 4294967294 0 -> 4294967294 0
+ {.offset = 0xEFFFFFFF, .whence = 0}, // 4294967295 4026531839 0 -> 4026531839 0 -> 4026531839 0
+ {.offset = 0xEFFFFFFE, .whence = 0}, // 4294967294 4026531838 0 -> 4026531838 0 -> 4026531838 0
+ {.offset = 0xDFFFFFFF, .whence = 0}, // 4026531839 3758096383 0 -> 3758096383 0 -> 3758096383 0
+ {.offset = 0xDFFFFFFE, .whence = 0}, // 4026531838 3758096382 0 -> 3758096382 0 -> 3758096382 0
+ {.offset = 0xCFFFFFFF, .whence = 0}, // 3758096383 3489660927 0 -> 3489660927 0 -> 3489660927 0
+ {.offset = 0xCFFFFFFE, .whence = 0}, // 3758096382 3489660926 0 -> 3489660926 0 -> 3489660926 0
+ {.offset = 0xBFFFFFFF, .whence = 0}, // 3489660927 3221225471 0 -> 3221225471 0 -> 3221225471 0
+ {.offset = 0xBFFFFFFE, .whence = 0}, // 3489660926 3221225470 0 -> 3221225470 0 -> 3221225470 0
+ {.offset = 0xAFFFFFFF, .whence = 0}, // 3221225471 2952790015 0 -> 2952790015 0 -> 2952790015 0
+ {.offset = 0xAFFFFFFE, .whence = 0}, // 3221225470 2952790014 0 -> 2952790014 0 -> 2952790014 0
+ {.offset = 0xA0000000, .whence = 0}, // 2952790015 2684354560 0 -> 2684354560 0 -> 2684354560 0
+ {.offset = 0x9FFFFFFF, .whence = 0}, // 2952790014 2684354559 0 -> 2684354559 0 -> 2684354559 0
+ {.offset = 0x9FFFFFFE, .whence = 0}, // 2684354560 2684354558 0 -> 2684354558 0 -> 2684354558 0
+ {.offset = 0x90000000, .whence = 0}, // 2684354559 2415919104 0 -> 2415919104 0 -> 2415919104 0
+ {.offset = 0x8FFFFFFF, .whence = 0}, // 2684354558 2415919103 0 -> 2415919103 0 -> 2415919103 0
+ {.offset = 0x8FFFFFFE, .whence = 0}, // 2415919104 2415919102 0 -> 2415919102 0 -> 2415919102 0
+ {.offset = 0x80000000, .whence = 0}, // 2415919103 2147483648 0 -> 2147483648 0 -> 2147483648 0
+ {.offset = 0x7FFFFFFF, .whence = 0}, // 2415919102 2147483647 0 -> 2147483647 0 -> 2147483647 0
+ {.offset = 0x7FFFFFFE, .whence = 0}, // 2147483648 2147483646 0 -> 2147483646 0 -> 2147483646 0
+ {.offset = 0x70000000, .whence = 0}, // 2147483647 1879048192 0 -> 1879048192 0 -> 1879048192 0
+ {.offset = 0x6FFFFFFF, .whence = 0}, // 2147483646 1879048191 0 -> 1879048191 0 -> 1879048191 0
+ {.offset = 0x6FFFFFFE, .whence = 0}, // 1879048192 1879048190 0 -> 1879048190 0 -> 1879048190 0
+ {.offset = 0xFFFFFF, .whence = 0}, // 1879048191 16777215 0 -> 16777215 0 -> 16777215 0
+ {.offset = 0xFFFFFE, .whence = 0}, // 1879048190 16777214 0 -> 16777214 0 -> 16777214 0
+ {.offset = 0xFFFF, .whence = 0}, // 16777215 65535 0 -> 65535 0 -> 65535 0
+ {.offset = 0xFFFE, .whence = 0}, // 16777214 65534 0 -> 65534 0 -> 65534 0
+ {.offset = 0xFF, .whence = 0}, // 65535 255 0 -> 255 0 -> 255 0
+ {.offset = 0xFE, .whence = 0}, // 65534 254 0 -> 254 0 -> 254 0
+};
+
+#endif // PFS_LSEEK_H
diff --git a/tests/code/filesystem_dirents/code/read_variants/pfs_read.h b/tests/code/filesystem_dirents/code/read_variants/pfs_read.h
new file mode 100644
index 00000000..e9ef104b
--- /dev/null
+++ b/tests/code/filesystem_dirents/code/read_variants/pfs_read.h
@@ -0,0 +1,38 @@
+#include "../fs_test.h"
+
+#include
+
+// read size, read offset // HW return, HW end position
+std::vector pfs_read_variants = {
+ {.size = 0, .offset = 0}, // 0 0 -> 0 0 0 -> 0 0 0 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+ {.size = 64, .offset = 0}, // 64 0 -> 0 64 64 -> 0 64 64 07000000040000000100000018000000
+ {.size = 128, .offset = 0}, // 128 0 -> 0 128 128 -> 0 128 128 07000000040000000100000018000000
+ {.size = 256, .offset = 0}, // 256 0 -> 0 256 256 -> 0 256 256 07000000040000000100000018000000
+ {.size = 511, .offset = 0}, // 511 0 -> 0 511 511 -> 0 511 511 07000000040000000100000018000000
+ {.size = 511, .offset = 1}, // 511 1 -> 1 511 512 -> 1 511 512 0000000400000001000000180000002e
+ {.size = 511, .offset = 2}, // 511 2 -> 2 511 513 -> 2 511 513 00000400000001000000180000002e00
+ {.size = 512, .offset = 0}, // 512 0 -> 0 512 512 -> 0 512 512 07000000040000000100000018000000
+ {.size = 2048, .offset = 1245}, // 2048 1245 -> 1245 2048 3293 -> 1245 2048 3293 74323500000000000000002d00000002
+ {.size = 7257, .offset = 1245}, // 7257 1245 -> 1245 7257 8502 -> 1245 7257 8502 74323500000000000000002d00000002
+ {.size = 418, .offset = 574}, // 418 574 -> 574 418 992 -> 574 418 992 00001c00000002000000100000002800
+ {.size = 9363, .offset = 1111}, // 9363 1111 -> 1111 9363 10474 -> 1111 9363 10474 0066696c656e616d65646f7465787432
+ {.size = 37865, .offset = 936}, // 37865 936 -> 936 37865 38801 -> 936 37865 38801 25000000020000001000000028000000
+ {.size = 17543, .offset = 1245}, // 17543 1245 -> 1245 17543 18788 -> 1245 17543 18788 74323500000000000000002d00000002
+ {.size = 1024, .offset = 35565}, // 1024 35565 -> 35565 1024 36589 -> 35565 1024 36589 00000000000000000000000000000000
+ {.size = 512, .offset = 65534}, // 512 65534 -> 65534 2 65536 -> 65534 2 65536 0000aaaaaaaaaaaaaaaaaaaaaaaaaaaa
+ {.size = 2048, .offset = 65534}, // 2048 65534 -> 65534 2 65536 -> 65534 2 65536 0000aaaaaaaaaaaaaaaaaaaaaaaaaaaa
+ {.size = 4096, .offset = 8192}, // 4096 8192 -> 8192 4096 12288 -> 8192 4096 12288 746865766572796f6e65313600000000
+ {.size = 1024, .offset = 8000}, // 1024 8000 -> 8000 1024 9024 -> 8000 1024 9024 340000004800000066696c6577697468
+ {.size = 1024, .offset = 10000}, // 1024 10000 -> 10000 1024 11024 -> 10000 1024 11024 6e65343100000000d300000002000000
+ {.size = 4096, .offset = 10000}, // 4096 10000 -> 10000 4096 14096 -> 10000 4096 14096 6e65343100000000d300000002000000
+
+ {.size = 1024, .offset = 65000}, //
+ {.size = 1024, .offset = 65023}, //
+ {.size = 1024, .offset = 65024}, //
+ {.size = 1024, .offset = 65025}, //
+ {.size = 1024, .offset = 65535}, //
+ {.size = 1024, .offset = 65536}, //
+ {.size = 1024, .offset = 70123}, //
+ {.size = 1024, .offset = 92616}, //
+ {.size = 1024, .offset = 92544}, //
+};
diff --git a/tests/code/filesystem_dirents/code/read_variants/variants.h b/tests/code/filesystem_dirents/code/read_variants/variants.h
new file mode 100644
index 00000000..74941c98
--- /dev/null
+++ b/tests/code/filesystem_dirents/code/read_variants/variants.h
@@ -0,0 +1,14 @@
+#pragma once
+
+/**
+ * These tests have structured test cases
+ * Add whatever you wamt that you want to see here
+ * The rest will be taken care of by fuzzing
+ */
+
+#include "normal_getdirentries.h"
+#include "normal_lseek.h"
+#include "normal_read.h"
+#include "pfs_getdirentries.h"
+#include "pfs_lseek.h"
+#include "pfs_read.h"
\ No newline at end of file
diff --git a/tests/code/filesystem_dirents/dumps/.gitkeep b/tests/code/filesystem_dirents/dumps/.gitkeep
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_dirents/dumps/1202/normal_getdirent.dump b/tests/code/filesystem_dirents/dumps/1202/normal_getdirent.dump
new file mode 100644
index 00000000..0e078fdf
Binary files /dev/null and b/tests/code/filesystem_dirents/dumps/1202/normal_getdirent.dump differ
diff --git a/tests/code/filesystem_dirents/dumps/1202/normal_read.dump b/tests/code/filesystem_dirents/dumps/1202/normal_read.dump
new file mode 100644
index 00000000..0e078fdf
Binary files /dev/null and b/tests/code/filesystem_dirents/dumps/1202/normal_read.dump differ
diff --git a/tests/code/filesystem_dirents/dumps/1202/pfs_getdirent.dump b/tests/code/filesystem_dirents/dumps/1202/pfs_getdirent.dump
new file mode 100644
index 00000000..bd8deea4
Binary files /dev/null and b/tests/code/filesystem_dirents/dumps/1202/pfs_getdirent.dump differ
diff --git a/tests/code/filesystem_dirents/dumps/1202/pfs_read.dump b/tests/code/filesystem_dirents/dumps/1202/pfs_read.dump
new file mode 100644
index 00000000..2a40e798
Binary files /dev/null and b/tests/code/filesystem_dirents/dumps/1202/pfs_read.dump differ
diff --git a/tests/code/filesystem_dirents/dumps/comp_utils.py b/tests/code/filesystem_dirents/dumps/comp_utils.py
new file mode 100644
index 00000000..21f6459e
--- /dev/null
+++ b/tests/code/filesystem_dirents/dumps/comp_utils.py
@@ -0,0 +1,42 @@
+from dataclasses import dataclass
+import hashlib
+import re
+
+
+find_buffer_end_re = re.compile(b"\x00+(\xaa+)")
+regular_dirent_query_re = re.compile(
+ b"(?P....)(?P..)(?P[\x02\x04\x08])(?P.)(?P[ -~]{1,255})(?P\x00*)"
+)
+pfs_query_getdents_re = re.compile(
+ b"(?P.{4})(?P[\x02\x04\x08]\x00{3})(?P....)(?P....)(?P[ -~]{1,255})(?P\x00*)"
+)
+
+@dataclass(kw_only=True)
+class Dirent:
+ chk: bytes
+ offset: int
+ end: int
+ entry_type: bytes # 4 for pfs, 1 for reg
+ fileno: bytes # 4 for pfs, 4 for reg
+ namelen: bytes # 4 for pfs, 1 for reg
+ reclen: bytes # 4 for pfs, 2 for reg
+ name: bytes # up to 255 characters + null terminator
+ padding: bytes
+
+ def is_dirent(self):
+ pass
+
+ def hash(self) -> bytes:
+ if not self.chk:
+ self.chk = hashlib.md5(
+ self.entry_type + self.namelen + self.reclen + self.name
+ ).digest()
+ return self.chk
+
+ def __repr__(self) -> bytes:
+ return self.hash()
+
+ def __eq__(self, other):
+ if isinstance(other, Dirent):
+ return False
+ return self.hash() == other.hash()
\ No newline at end of file
diff --git a/tests/code/filesystem_dirents/dumps/comparator.py b/tests/code/filesystem_dirents/dumps/comparator.py
new file mode 100644
index 00000000..eaf599b5
--- /dev/null
+++ b/tests/code/filesystem_dirents/dumps/comparator.py
@@ -0,0 +1,179 @@
+import os
+import sys
+import re
+import comp_utils as cu
+
+if len(sys.argv) < 3:
+ print(f"comparator.py [PS4] [Emulator] [--debug]")
+ print("Compare dirent dumps between console and dump")
+ print("Add `--debug` at the end for verbose output")
+ sys.exit(0)
+
+dir_left = sys.argv[1]
+dir_right = sys.argv[2]
+debug_enabled = "--debug" in sys.argv
+
+dir_left_contents = None
+dir_right_contents = None
+
+try:
+ dir_left_contents = os.listdir(dir_left)
+ dir_right_contents = os.listdir(dir_right)
+except:
+ print("Error during listing directories")
+ sys.exit(-1)
+
+
+error_badf = []
+error_bad_size = []
+error_bad_len = []
+error_mismatch_order = []
+
+counter = 0
+counter_completed = 0
+for filename in dir_left_contents:
+ if filename.endswith(".cue"):
+ continue
+ counter += 1
+ file_left_path = os.path.join(os.path.abspath(dir_left), filename)
+ file_left_cue_path = os.path.join(os.path.abspath(dir_left), filename[:-4] + ".cue")
+ file_right_path = os.path.join(os.path.abspath(dir_right), filename)
+ file_right_cue_path = os.path.join(
+ os.path.abspath(dir_right), filename[:-4] + ".cue"
+ )
+ is_pfs = "PFS" in filename
+ is_read = "read" in filename
+ is_getdents = "dirent" in filename
+
+ if not (is_read or is_getdents):
+ print(f"File cannot be used: {filename}")
+ error_badf.append(filename)
+ continue
+
+ print()
+ print(f"<<<< Testing file {filename} >>>>")
+
+ size_left = os.path.getsize(file_left_path)
+ size_right = os.path.getsize(file_right_path)
+
+ content_left = None
+ content_left_cue = None
+ content_right = None
+ content_right_cue = None
+ with open(file_left_path, "rb") as lhsf:
+ content_left = lhsf.read()
+ with open(file_right_path, "rb") as rhsf:
+ content_right = rhsf.read()
+ with open(file_left_cue_path, "rb") as lhsfc:
+ content_left_cue = lhsfc.read()
+ with open(file_right_cue_path, "rb") as rhsfc:
+ content_right_cue = rhsfc.read()
+
+ ### Verify size
+
+ if size_left == 0 and size_right == 0:
+ left_last_read_size = 0
+ left_last_read_basep = 0
+ right_last_read_size = 0
+ right_last_read_basep = 0
+
+ if is_read:
+ left_last_read_size = content_left_cue[-8:]
+ right_last_read_size = content_right_cue[-8:]
+ pass
+ elif is_getdents:
+ left_last_read_size = content_left_cue[-16:-8]
+ left_last_read_basep = content_right_cue[-8:]
+ right_last_read_size = content_left_cue[-16:-8]
+ right_last_read_basep = content_right_cue[-8:]
+ pass
+
+ if debug_enabled:
+ print(f"Last read size L:{left_last_read_size} R:{right_last_read_size}")
+ if is_getdents:
+ print(f"Last basep L:{left_last_read_basep} R:{right_last_read_basep}")
+
+ if left_last_read_size != right_last_read_size:
+ print(f"Read ended with L:{left_last_read_size} R:{right_last_read_size}")
+ continue
+
+ if debug_enabled:
+ print("Read result seems OK")
+
+ print(f"Size:\t{size_left}\t{size_right}")
+
+ if size_left != size_right:
+ print("Error: sizes don't match. Continuing...")
+ error_bad_size.append(filename)
+ continue
+
+ #
+ ### Search for entries
+ ### Search for entry offsets
+ ### Search for skipped bytes (0-fills, cut off data)
+ #
+ left_dirent_list: list[cu.Dirent] = []
+ right_dirent_list: list[cu.Dirent] = []
+ search_query = None
+
+ lsresult = None
+ if is_pfs and is_read:
+ search_query = cu.pfs_query_getdents_re.finditer(content_left)
+ else:
+ search_query = cu.regular_dirent_query_re.finditer(content_left)
+ for lsresult in search_query:
+ dirent_init_dict = lsresult.groupdict()
+ dirent_init_dict["offset"] = lsresult.start()
+ dirent_init_dict["end"] = lsresult.end()
+ dirent_init_dict["chk"] = ""
+ new_dirent = cu.Dirent(**dirent_init_dict)
+ new_dirent.hash()
+ left_dirent_list.append(new_dirent)
+ if lsresult is None:
+ print(f"Left: can't match dirents in {file_left_path}")
+ continue
+
+ lsresult = None
+ if is_pfs and is_read:
+ search_query = cu.pfs_query_getdents_re.finditer(content_right)
+ else:
+ search_query = cu.regular_dirent_query_re.finditer(content_right)
+ for lsresult in search_query:
+ dirent_init_dict = lsresult.groupdict()
+ dirent_init_dict["offset"] = lsresult.start()
+ dirent_init_dict["end"] = lsresult.end()
+ dirent_init_dict["chk"] = ""
+ new_dirent = cu.Dirent(**dirent_init_dict)
+ new_dirent.hash()
+ right_dirent_list.append(new_dirent)
+ if lsresult is None:
+ print(f"Right: can't match dirents in {file_right_path}")
+
+ left_dirent_list_len = len(left_dirent_list)
+ right_dirent_list_len = len(right_dirent_list)
+
+ if left_dirent_list_len != right_dirent_list_len:
+ error_bad_len.append(filename)
+ print(
+ f"Error: Different amount of dirents: L:{left_dirent_list_len} R:{right_dirent_list_len}. Continuing..."
+ )
+ continue
+
+ counter_completed += 1
+ print("Tests complete")
+ pass
+
+print()
+print(f"Error: Incompatible file: {len(error_badf)}/{counter}")
+# for err_item in error_badf:print(f"{err_item} ",end='')
+# print()
+print(f"Error: Mismatched size: {len(error_bad_size)}/{counter}")
+# for err_item in error_bad_size:print(f"{err_item} ",end='')
+# print()
+print(f"Error: Mismatched amount of dirents: {len(error_bad_len)}/{counter}")
+# for err_item in error_bad_len:print(f"{err_item} ",end='')
+# print()
+print(f"Error: Mismatched dirent order: {len(error_mismatch_order)}/{counter}")
+# for err_item in error_mismatch_order:print(f"{err_item} ",end='')
+# print()
+print(f"Passed: {counter_completed}/{counter}")
diff --git a/tests/code/filesystem_dirents/dumps/log.txt b/tests/code/filesystem_dirents/dumps/log.txt
new file mode 100644
index 00000000..23190689
--- /dev/null
+++ b/tests/code/filesystem_dirents/dumps/log.txt
@@ -0,0 +1,433 @@
+<118>[ main ] [INFO]
+<118>[ main ] [INFO] <<<< TESTS START >>>>
+<118>[ main ] [INFO]
+<118>[ Obliterate ] [INFO] << rm -rf [ /data/enderman ] >>
+<118>[ Obliterate ] [SUCC] >> rm -rf [ /data/enderman ] <<
+<118>[ PrepareTests ] [INFO] Cloned into 208 elements
+<118>[ testBody ] [TEST] <<<< Dump everything >>>>
+<118>[ testBody ] [TEST] PFS read got 65536 bytes
+<118>[ testBody ] [TEST] PFS read got 0 bytes
+<118>[ testBody ] [TEST] PFS sceKernelGetdirentries got 10656 bytes
+<118>[ testBody ] [TEST] PFS sceKernelGetdirentries got 0 bytes
+<118>[ testBody ] [TEST] Normal read got 8704 bytes
+<118>[ testBody ] [TEST] Normal read got 0 bytes
+<118>[ testBody ] [TEST] Normal sceKernelGetdirentries got 8704 bytes
+<118>[ testBody ] [TEST] Normal sceKernelGetdirentries got 0 bytes
+<118>.[ testBody ] [TEST] <<<< Dirent structure validation >>>>
+<118>[ testBody ] [TEST] Normal read
+<118>[ testBody ] [TEST] Normal getdirentries
+<118>[ testBody ] [TEST] PFS read
+<118>[ testBody ] [TEST] PFS getdirentries
+<118>.[ testBody ] [TEST] <<<< PFS read and getdirentries consistency >>>>
+<118>[ testBody ] [INFO] Note: 210 files are supposed to be compared
+<118>[ testBody ] [WARN] Note: This function does not translate d_type between PFS and user filesystems ( /home/user/github/integration_tests/tests/code/filesystem_dirents/code/log.h:59 )
+<118>[ PFSComparator ] [INFO] Compared 210 entries
+<118>.[ testBody ] [TEST] <<<< Normal read and getdirentries consistency >>>>
+<118>[ testBody ] [INFO] Note: 210 files are supposed to be compared
+<118>[ NormalComparator ] [INFO] Compared 210 entries
+<118>.[ testBody ] [TEST] <<<< Normal lseek tests >>>>
+<118>[ testBody ] [TEST] 0 0 0 -> 0 0 -> 0 0
+<118>[ testBody ] [TEST] 0 -123 0 -> EINVAL 22 -> EINVAL 22
+<118>[ testBody ] [TEST] 0 123456 0 -> 123456 0 -> 123456 0
+<118>[ testBody ] [TEST] 0 60 0 -> 60 0 -> 60 0
+<118>[ testBody ] [TEST] 123456 0 1 -> 60 0 -> 60 0
+<118>[ testBody ] [TEST] 60 24 1 -> 84 0 -> 84 0
+<118>[ testBody ] [TEST] 60 -24 1 -> 60 0 -> 60 0
+<118>[ testBody ] [TEST] 84 -6666 1 -> EINVAL 22 -> EINVAL 22
+<118>[ testBody ] [TEST] 60 123456 1 -> 123516 0 -> 123516 0
+<118>[ testBody ] [TEST] 60 0 2 -> 8704 0 -> 8704 0
+<118>[ testBody ] [TEST] 123516 123456 2 -> 132160 0 -> 132160 0
+<118>[ testBody ] [TEST] 8704 100 2 -> 8804 0 -> 8804 0
+<118>[ testBody ] [TEST] 132160 -100 2 -> 8604 0 -> 8604 0
+<118>[ testBody ] [TEST] 8804 -100000 2 -> EINVAL 22 -> EINVAL 22
+<118>[ testBody ] [TEST] 8604 -8705 2 -> EINVAL 22 -> EINVAL 22
+<118>[ testBody ] [TEST] 8604 -8704 2 -> 0 0 -> 0 0
+<118>[ testBody ] [TEST] 8604 -8703 2 -> 1 0 -> 1 0
+<118>[ testBody ] [TEST] 0 0 3 -> ENOTTY 25 -> ENOTTY 25
+<118>[ testBody ] [TEST] 1 8 3 -> ENOTTY 25 -> ENOTTY 25
+<118>[ testBody ] [TEST] 1 16 3 -> ENOTTY 25 -> ENOTTY 25
+<118>[ testBody ] [TEST] 1 24 3 -> ENOTTY 25 -> ENOTTY 25
+<118>[ testBody ] [TEST] 1 32 3 -> ENOTTY 25 -> ENOTTY 25
+<118>[ testBody ] [TEST] 1 40 3 -> ENOTTY 25 -> ENOTTY 25
+<118>[ testBody ] [TEST] 1 10240 3 -> ENOTTY 25 -> ENOTTY 25
+<118>[ testBody ] [TEST] 1 -1024 3 -> ENOTTY 25 -> ENOTTY 25
+<118>[ testBody ] [TEST] 1 -10240 3 -> ENOTTY 25 -> ENOTTY 25
+<118>[ testBody ] [TEST] 1 -10657 3 -> ENOTTY 25 -> ENOTTY 25
+<118>[ testBody ] [TEST] 1 -10656 3 -> ENOTTY 25 -> ENOTTY 25
+<118>[ testBody ] [TEST] 1 -10655 3 -> ENOTTY 25 -> ENOTTY 25
+<118>[ testBody ] [TEST] 1 -8705 3 -> ENOTTY 25 -> ENOTTY 25
+<118>[ testBody ] [TEST] 1 -8704 3 -> ENOTTY 25 -> ENOTTY 25
+<118>[ testBody ] [TEST] 1 -8703 3 -> ENOTTY 25 -> ENOTTY 25
+<118>[ testBody ] [TEST] 1 0 4 -> ENOTTY 25 -> ENOTTY 25
+<118>[ testBody ] [TEST] 1 8 4 -> ENOTTY 25 -> ENOTTY 25
+<118>[ testBody ] [TEST] 1 16 4 -> ENOTTY 25 -> ENOTTY 25
+<118>[ testBody ] [TEST] 1 24 4 -> ENOTTY 25 -> ENOTTY 25
+<118>[ testBody ] [TEST] 1 32 4 -> ENOTTY 25 -> ENOTTY 25
+<118>[ testBody ] [TEST] 1 40 4 -> ENOTTY 25 -> ENOTTY 25
+<118>[ testBody ] [TEST] 1 10240 4 -> ENOTTY 25 -> ENOTTY 25
+<118>[ testBody ] [TEST] 1 -1024 4 -> ENOTTY 25 -> ENOTTY 25
+<118>[ testBody ] [TEST] 1 -10240 4 -> ENOTTY 25 -> ENOTTY 25
+<118>[ testBody ] [TEST] 1 -10657 4 -> ENOTTY 25 -> ENOTTY 25
+<118>[ testBody ] [TEST] 1 -10656 4 -> ENOTTY 25 -> ENOTTY 25
+<118>[ testBody ] [TEST] 1 -10655 4 -> ENOTTY 25 -> ENOTTY 25
+<118>[ testBody ] [TEST] 1 -8705 4 -> ENOTTY 25 -> ENOTTY 25
+<118>[ testBody ] [TEST] 1 -8704 4 -> ENOTTY 25 -> ENOTTY 25
+<118>[ testBody ] [TEST] 1 -8703 4 -> ENOTTY 25 -> ENOTTY 25
+<118>[ testBody ] [TEST] 1 -1 0 -> EINVAL 22 -> EINVAL 22
+<118>[ testBody ] [TEST] 1 -2 0 -> EINVAL 22 -> EINVAL 22
+<118>[ testBody ] [TEST] 1 72057594037927935 0 -> 72057594037927935 0 -> 72057594037927935 0
+<118>[ testBody ] [TEST] 1 72057594037927934 0 -> 72057594037927934 0 -> 72057594037927934 0
+<118>[ testBody ] [TEST] 72057594037927935 281474976710655 0 -> 281474976710655 0 -> 281474976710655 0
+<118>[ testBody ] [TEST] 72057594037927934 281474976710654 0 -> 281474976710654 0 -> 281474976710654 0
+<118>[ testBody ] [TEST] 281474976710655 1099511627775 0 -> 1099511627775 0 -> 1099511627775 0
+<118>[ testBody ] [TEST] 281474976710654 1099511627774 0 -> 1099511627774 0 -> 1099511627774 0
+<118>[ testBody ] [TEST] 1099511627775 4294967295 0 -> 4294967295 0 -> 4294967295 0
+<118>[ testBody ] [TEST] 1099511627774 4294967294 0 -> 4294967294 0 -> 4294967294 0
+<118>[ testBody ] [TEST] 4294967295 4026531839 0 -> 4026531839 0 -> 4026531839 0
+<118>[ testBody ] [TEST] 4294967294 4026531838 0 -> 4026531838 0 -> 4026531838 0
+<118>[ testBody ] [TEST] 4026531839 3758096383 0 -> 3758096383 0 -> 3758096383 0
+<118>[ testBody ] [TEST] 4026531838 3758096382 0 -> 3758096382 0 -> 3758096382 0
+<118>[ testBody ] [TEST] 3758096383 3489660927 0 -> 3489660927 0 -> 3489660927 0
+<118>[ testBody ] [TEST] 3758096382 3489660926 0 -> 3489660926 0 -> 3489660926 0
+<118>[ testBody ] [TEST] 3489660927 3221225471 0 -> 3221225471 0 -> 3221225471 0
+<118>[ testBody ] [TEST] 3489660926 3221225470 0 -> 3221225470 0 -> 3221225470 0
+<118>[ testBody ] [TEST] 3221225471 2952790015 0 -> 2952790015 0 -> 2952790015 0
+<118>[ testBody ] [TEST] 3221225470 2952790014 0 -> 2952790014 0 -> 2952790014 0
+<118>[ testBody ] [TEST] 2952790015 2684354560 0 -> 2684354560 0 -> 2684354560 0
+<118>[ testBody ] [TEST] 2952790014 2684354559 0 -> 2684354559 0 -> 2684354559 0
+<118>[ testBody ] [TEST] 2684354560 2684354558 0 -> 2684354558 0 -> 2684354558 0
+<118>[ testBody ] [TEST] 2684354559 2415919104 0 -> 2415919104 0 -> 2415919104 0
+<118>[ testBody ] [TEST] 2684354558 2415919103 0 -> 2415919103 0 -> 2415919103 0
+<118>[ testBody ] [TEST] 2415919104 2415919102 0 -> 2415919102 0 -> 2415919102 0
+<118>[ testBody ] [TEST] 2415919103 2147483648 0 -> 2147483648 0 -> 2147483648 0
+<118>[ testBody ] [TEST] 2415919102 2147483647 0 -> 2147483647 0 -> 2147483647 0
+<118>[ testBody ] [TEST] 2147483648 2147483646 0 -> 2147483646 0 -> 2147483646 0
+<118>[ testBody ] [TEST] 2147483647 1879048192 0 -> 1879048192 0 -> 1879048192 0
+<118>[ testBody ] [TEST] 2147483646 1879048191 0 -> 1879048191 0 -> 1879048191 0
+<118>[ testBody ] [TEST] 1879048192 1879048190 0 -> 1879048190 0 -> 1879048190 0
+<118>[ testBody ] [TEST] 1879048191 16777215 0 -> 16777215 0 -> 16777215 0
+<118>[ testBody ] [TEST] 1879048190 16777214 0 -> 16777214 0 -> 16777214 0
+<118>[ testBody ] [TEST] 16777215 65535 0 -> 65535 0 -> 65535 0
+<118>[ testBody ] [TEST] 16777214 65534 0 -> 65534 0 -> 65534 0
+<118>[ testBody ] [TEST] 65535 255 0 -> 255 0 -> 255 0
+<118>[ testBody ] [TEST] 65534 254 0 -> 254 0 -> 254 0
+<118>.[ testBody ] [TEST] <<<< PFS lseek tests >>>>
+<118>[ testBody ] [TEST] 0 0 0 -> 0 0 -> 0 0
+<118>[ testBody ] [TEST] 0 -123 0 -> EINVAL 22 -> EINVAL 22
+<118>[ testBody ] [TEST] 0 123456 0 -> 123456 0 -> 123456 0
+<118>[ testBody ] [TEST] 0 60 0 -> 60 0 -> 60 0
+<118>[ testBody ] [TEST] 123456 0 1 -> 60 0 -> 60 0
+<118>[ testBody ] [TEST] 60 24 1 -> 84 0 -> 84 0
+<118>[ testBody ] [TEST] 60 -24 1 -> 60 0 -> 60 0
+<118>[ testBody ] [TEST] 84 -6666 1 -> EINVAL 22 -> EINVAL 22
+<118>[ testBody ] [TEST] 60 123456 1 -> 123516 0 -> 123516 0
+<118>[ testBody ] [TEST] 60 0 2 -> 65536 0 -> 65536 0
+<118>[ testBody ] [TEST] 123516 123456 2 -> 188992 0 -> 188992 0
+<118>[ testBody ] [TEST] 65536 100 2 -> 65636 0 -> 65636 0
+<118>[ testBody ] [TEST] 188992 -100 2 -> 65436 0 -> 65436 0
+<118>[ testBody ] [TEST] 65636 -100000 2 -> EINVAL 22 -> EINVAL 22
+<118>[ testBody ] [TEST] 65436 -8705 2 -> 56831 0 -> 56831 0
+<118>[ testBody ] [TEST] 65436 -8704 2 -> 56832 0 -> 56832 0
+<118>[ testBody ] [TEST] 56831 -8703 2 -> 56833 0 -> 56833 0
+<118>[ testBody ] [TEST] 56832 0 3 -> ENOTTY 25 -> ENOTTY 25
+<118>[ testBody ] [TEST] 56833 8 3 -> ENOTTY 25 -> ENOTTY 25
+<118>[ testBody ] [TEST] 56833 16 3 -> ENOTTY 25 -> ENOTTY 25
+<118>[ testBody ] [TEST] 56833 24 3 -> ENOTTY 25 -> ENOTTY 25
+<118>[ testBody ] [TEST] 56833 32 3 -> ENOTTY 25 -> ENOTTY 25
+<118>[ testBody ] [TEST] 56833 40 3 -> ENOTTY 25 -> ENOTTY 25
+<118>[ testBody ] [TEST] 56833 10240 3 -> ENOTTY 25 -> ENOTTY 25
+<118>[ testBody ] [TEST] 56833 -1024 3 -> ENOTTY 25 -> ENOTTY 25
+<118>[ testBody ] [TEST] 56833 -10240 3 -> ENOTTY 25 -> ENOTTY 25
+<118>[ testBody ] [TEST] 56833 -10657 3 -> ENOTTY 25 -> ENOTTY 25
+<118>[ testBody ] [TEST] 56833 -10656 3 -> ENOTTY 25 -> ENOTTY 25
+<118>[ testBody ] [TEST] 56833 -10655 3 -> ENOTTY 25 -> ENOTTY 25
+<118>[ testBody ] [TEST] 56833 -8705 3 -> ENOTTY 25 -> ENOTTY 25
+<118>[ testBody ] [TEST] 56833 -8704 3 -> ENOTTY 25 -> ENOTTY 25
+<118>[ testBody ] [TEST] 56833 -8703 3 -> ENOTTY 25 -> ENOTTY 25
+<118>[ testBody ] [TEST] 56833 0 4 -> ENOTTY 25 -> ENOTTY 25
+<118>[ testBody ] [TEST] 56833 8 4 -> ENOTTY 25 -> ENOTTY 25
+<118>[ testBody ] [TEST] 56833 16 4 -> ENOTTY 25 -> ENOTTY 25
+<118>[ testBody ] [TEST] 56833 24 4 -> ENOTTY 25 -> ENOTTY 25
+<118>[ testBody ] [TEST] 56833 32 4 -> ENOTTY 25 -> ENOTTY 25
+<118>[ testBody ] [TEST] 56833 40 4 -> ENOTTY 25 -> ENOTTY 25
+<118>[ testBody ] [TEST] 56833 10240 4 -> ENOTTY 25 -> ENOTTY 25
+<118>[ testBody ] [TEST] 56833 -1024 4 -> ENOTTY 25 -> ENOTTY 25
+<118>[ testBody ] [TEST] 56833 -10240 4 -> ENOTTY 25 -> ENOTTY 25
+<118>[ testBody ] [TEST] 56833 -10657 4 -> ENOTTY 25 -> ENOTTY 25
+<118>[ testBody ] [TEST] 56833 -10656 4 -> ENOTTY 25 -> ENOTTY 25
+<118>[ testBody ] [TEST] 56833 -10655 4 -> ENOTTY 25 -> ENOTTY 25
+<118>[ testBody ] [TEST] 56833 -8705 4 -> ENOTTY 25 -> ENOTTY 25
+<118>[ testBody ] [TEST] 56833 -8704 4 -> ENOTTY 25 -> ENOTTY 25
+<118>[ testBody ] [TEST] 56833 -8703 4 -> ENOTTY 25 -> ENOTTY 25
+<118>[ testBody ] [TEST] 56833 -1 0 -> EINVAL 22 -> EINVAL 22
+<118>[ testBody ] [TEST] 56833 -2 0 -> EINVAL 22 -> EINVAL 22
+<118>[ testBody ] [TEST] 56833 72057594037927935 0 -> 72057594037927935 0 -> 72057594037927935 0
+<118>[ testBody ] [TEST] 56833 72057594037927934 0 -> 72057594037927934 0 -> 72057594037927934 0
+<118>[ testBody ] [TEST] 72057594037927935 281474976710655 0 -> 281474976710655 0 -> 281474976710655 0
+<118>[ testBody ] [TEST] 72057594037927934 281474976710654 0 -> 281474976710654 0 -> 281474976710654 0
+<118>[ testBody ] [TEST] 281474976710655 1099511627775 0 -> 1099511627775 0 -> 1099511627775 0
+<118>[ testBody ] [TEST] 281474976710654 1099511627774 0 -> 1099511627774 0 -> 1099511627774 0
+<118>[ testBody ] [TEST] 1099511627775 4294967295 0 -> 4294967295 0 -> 4294967295 0
+<118>[ testBody ] [TEST] 1099511627774 4294967294 0 -> 4294967294 0 -> 4294967294 0
+<118>[ testBody ] [TEST] 4294967295 4026531839 0 -> 4026531839 0 -> 4026531839 0
+<118>[ testBody ] [TEST] 4294967294 4026531838 0 -> 4026531838 0 -> 4026531838 0
+<118>[ testBody ] [TEST] 4026531839 3758096383 0 -> 3758096383 0 -> 3758096383 0
+<118>[ testBody ] [TEST] 4026531838 3758096382 0 -> 3758096382 0 -> 3758096382 0
+<118>[ testBody ] [TEST] 3758096383 3489660927 0 -> 3489660927 0 -> 3489660927 0
+<118>[ testBody ] [TEST] 3758096382 3489660926 0 -> 3489660926 0 -> 3489660926 0
+<118>[ testBody ] [TEST] 3489660927 3221225471 0 -> 3221225471 0 -> 3221225471 0
+<118>[ testBody ] [TEST] 3489660926 3221225470 0 -> 3221225470 0 -> 3221225470 0
+<118>[ testBody ] [TEST] 3221225471 2952790015 0 -> 2952790015 0 -> 2952790015 0
+<118>[ testBody ] [TEST] 3221225470 2952790014 0 -> 2952790014 0 -> 2952790014 0
+<118>[ testBody ] [TEST] 2952790015 2684354560 0 -> 2684354560 0 -> 2684354560 0
+<118>[ testBody ] [TEST] 2952790014 2684354559 0 -> 2684354559 0 -> 2684354559 0
+<118>[ testBody ] [TEST] 2684354560 2684354558 0 -> 2684354558 0 -> 2684354558 0
+<118>[ testBody ] [TEST] 2684354559 2415919104 0 -> 2415919104 0 -> 2415919104 0
+<118>[ testBody ] [TEST] 2684354558 2415919103 0 -> 2415919103 0 -> 2415919103 0
+<118>[ testBody ] [TEST] 2415919104 2415919102 0 -> 2415919102 0 -> 2415919102 0
+<118>[ testBody ] [TEST] 2415919103 2147483648 0 -> 2147483648 0 -> 2147483648 0
+<118>[ testBody ] [TEST] 2415919102 2147483647 0 -> 2147483647 0 -> 2147483647 0
+<118>[ testBody ] [TEST] 2147483648 2147483646 0 -> 2147483646 0 -> 2147483646 0
+<118>[ testBody ] [TEST] 2147483647 1879048192 0 -> 1879048192 0 -> 1879048192 0
+<118>[ testBody ] [TEST] 2147483646 1879048191 0 -> 1879048191 0 -> 1879048191 0
+<118>[ testBody ] [TEST] 1879048192 1879048190 0 -> 1879048190 0 -> 1879048190 0
+<118>[ testBody ] [TEST] 1879048191 16777215 0 -> 16777215 0 -> 16777215 0
+<118>[ testBody ] [TEST] 1879048190 16777214 0 -> 16777214 0 -> 16777214 0
+<118>[ testBody ] [TEST] 16777215 65535 0 -> 65535 0 -> 65535 0
+<118>[ testBody ] [TEST] 16777214 65534 0 -> 65534 0 -> 65534 0
+<118>[ testBody ] [TEST] 65535 255 0 -> 255 0 -> 255 0
+<118>[ testBody ] [TEST] 65534 254 0 -> 254 0 -> 254 0
+<118>.[ testBody ] [TEST] <<<< Normal lseek fuzzing test >>>>
+<118>[ testBody ] [TEST] Note: Only first 20 bad entries are shown
+<118>[ testBody ] [SUCC] Fuzzing passed!
+<118>.[ testBody ] [TEST] <<<< PFS lseek fuzzing test >>>>
+<118>[ testBody ] [TEST] Note: Only first 20 bad entries are shown
+<118>[ testBody ] [SUCC] Fuzzing passed!
+<118>.[ testBody ] [TEST] <<<< Normal read tests >>>>
+<118>[ testBody ] [TEST] Master Normal read length is 8704
+<118>[ testBody ] [TEST] 0 0 -> 0 0 0 0 -> 0 0 0 0 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+<118>[ testBody ] [TEST] 64 0 -> 0 64 64 0 -> 0 64 64 0 d9d50c010c0004012e000000d8d50c01
+<118>[ testBody ] [TEST] 128 0 -> 0 128 128 0 -> 0 128 128 0 d9d50c010c0004012e000000d8d50c01
+<118>[ testBody ] [TEST] 256 0 -> 0 256 256 0 -> 0 256 256 0 d9d50c010c0004012e000000d8d50c01
+<118>[ testBody ] [TEST] 511 0 -> 0 511 511 0 -> 0 511 511 0 d9d50c010c0004012e000000d8d50c01
+<118>[ testBody ] [TEST] 511 1 -> 1 511 512 0 -> 1 511 512 0 d50c010c0004012e000000d8d50c010c
+<118>[ testBody ] [TEST] 511 2 -> 2 511 513 0 -> 2 511 513 0 0c010c0004012e000000d8d50c010c00
+<118>[ testBody ] [TEST] 512 0 -> 0 512 512 0 -> 0 512 512 0 d9d50c010c0004012e000000d8d50c01
+<118>[ testBody ] [TEST] 2048 1245 -> 1245 2048 3293 0 -> 1245 2048 3293 0 0000000dd60c011c00081066696c656e
+<118>[ testBody ] [TEST] 7257 1245 -> 1245 7257 8502 0 -> 1245 7257 8502 0 0000000dd60c011c00081066696c656e
+<118>[ testBody ] [TEST] 418 574 -> 574 418 992 0 -> 574 418 992 0 081066696c656e616d65646f74657874
+<118>[ testBody ] [TEST] 9363 1111 -> 1111 7593 8704 0 -> 1111 7593 8704 0 011c00081066696c656e616d65646f74
+<118>[ testBody ] [TEST] 37865 936 -> 936 7768 8704 0 -> 936 7768 8704 0 1c00081066696c656e616d65646f7465
+<118>[ testBody ] [TEST] 17543 1245 -> 1245 7459 8704 0 -> 1245 7459 8704 0 0000000dd60c011c00081066696c656e
+<118>[ testBody ] [TEST] 1024 35565 -> 35565 0 35565 0 -> 35565 0 35565 0 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+<118>[ testBody ] [TEST] 512 65534 -> 65534 0 65534 0 -> 65534 0 65534 0 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+<118>[ testBody ] [TEST] 2048 65534 -> 65534 0 65534 0 -> 65534 0 65534 0 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+<118>[ testBody ] [TEST] 4096 8192 -> 8192 512 8704 0 -> 8192 512 8704 0 a6d60c014000083466696c6577697468
+<118>[ testBody ] [TEST] 1024 8000 -> 8000 704 8704 0 -> 8000 704 8704 0 a3d60c014000083466696c6577697468
+<118>[ testBody ] [TEST] 1024 10000 -> 10000 0 10000 0 -> 10000 0 10000 0 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+<118>[ testBody ] [TEST] 4096 10000 -> 10000 0 10000 0 -> 10000 0 10000 0 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+<118>.[ testBody ] [TEST] <<<< PFS read tests >>>>
+<118>[ testBody ] [TEST] Master PFS read length is 65536
+<118>[ testBody ] [TEST] 0 0 -> 0 0 0 0 -> 0 0 0 0 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+<118>[ testBody ] [TEST] 64 0 -> 0 64 64 0 -> 0 64 64 0 07000000040000000100000018000000
+<118>[ testBody ] [TEST] 128 0 -> 0 128 128 0 -> 0 128 128 0 07000000040000000100000018000000
+<118>[ testBody ] [TEST] 256 0 -> 0 256 256 0 -> 0 256 256 0 07000000040000000100000018000000
+<118>[ testBody ] [TEST] 511 0 -> 0 511 511 0 -> 0 511 511 0 07000000040000000100000018000000
+<118>[ testBody ] [TEST] 511 1 -> 1 511 512 0 -> 1 511 512 0 0000000400000001000000180000002e
+<118>[ testBody ] [TEST] 511 2 -> 2 511 513 0 -> 2 511 513 0 00000400000001000000180000002e00
+<118>[ testBody ] [TEST] 512 0 -> 0 512 512 0 -> 0 512 512 0 07000000040000000100000018000000
+<118>[ testBody ] [TEST] 2048 1245 -> 1245 2048 3293 0 -> 1245 2048 3293 0 74323500000000000000002d00000002
+<118>[ testBody ] [TEST] 7257 1245 -> 1245 7257 8502 0 -> 1245 7257 8502 0 74323500000000000000002d00000002
+<118>[ testBody ] [TEST] 418 574 -> 574 418 992 0 -> 574 418 992 0 00001c00000002000000100000002800
+<118>[ testBody ] [TEST] 9363 1111 -> 1111 9363 10474 0 -> 1111 9363 10474 0 0066696c656e616d65646f7465787432
+<118>[ testBody ] [TEST] 37865 936 -> 936 37865 38801 0 -> 936 37865 38801 0 25000000020000001000000028000000
+<118>[ testBody ] [TEST] 17543 1245 -> 1245 17543 18788 0 -> 1245 17543 18788 0 74323500000000000000002d00000002
+<118>[ testBody ] [TEST] 1024 35565 -> 35565 1024 36589 0 -> 35565 1024 36589 0 00000000000000000000000000000000
+<118>[ testBody ] [TEST] 512 65534 -> 65534 2 65536 0 -> 65534 2 65536 0 0000aaaaaaaaaaaaaaaaaaaaaaaaaaaa
+<118>[ testBody ] [TEST] 2048 65534 -> 65534 2 65536 0 -> 65534 2 65536 0 0000aaaaaaaaaaaaaaaaaaaaaaaaaaaa
+<118>[ testBody ] [TEST] 4096 8192 -> 8192 4096 12288 0 -> 8192 4096 12288 0 746865766572796f6e65313600000000
+<118>[ testBody ] [TEST] 1024 8000 -> 8000 1024 9024 0 -> 8000 1024 9024 0 340000004800000066696c6577697468
+<118>[ testBody ] [TEST] 1024 10000 -> 10000 1024 11024 0 -> 10000 1024 11024 0 6e65343100000000d300000002000000
+<118>[ testBody ] [TEST] 4096 10000 -> 10000 4096 14096 0 -> 10000 4096 14096 0 6e65343100000000d300000002000000
+<118>.[ testBody ] [TEST] <<<< Normal read fuzzing test >>>>
+<118>[ testBody ] [TEST] Note: Only first 20 bad entries are shown
+<118>[ testBody ] [TEST] Note: This may take a while
+<118>[ testBody ] [TEST] Master Normal read length is 8704 , testing 200000 samples , max 20 bad returns are shown
+<118>[ testBody ] [SUCC] Fuzzing passed!
+<118>.[ testBody ] [TEST] <<<< PFS read fuzzing test >>>>
+<118>[ testBody ] [TEST] Note: Only first 20 bad entries are shown
+<118>[ testBody ] [TEST] Note: This may take a while
+<118>[ testBody ] [TEST] Master PFS read length is 65536 , testing 200000 samples , max 20 bad returns are shown
+<118>[ testBody ] [SUCC] Fuzzing passed!
+<118>.[ testBody ] [TEST] <<<< Normal getdirentries tests >>>>
+<118>[ testBody ] [TEST] Master Normal getdirentries length is 8704
+<118>[ testBody ] [TEST] 0 0 -> -1 EINVAL 0 22 -> 170 EINVAL 0 22 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+<118>[ testBody ] [TEST] 128 128 -> -1 EINVAL 128 22 -> 170 EINVAL 128 22 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+<118>[ testBody ] [TEST] 512 1024 -> 1024 512 1536 0 -> 1024 512 1536 0 05d60c011c00081066696c656e616d65
+<118>[ testBody ] [TEST] 128 128 -> -1 EINVAL 128 22 -> 170 EINVAL 128 22 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+<118>[ testBody ] [TEST] 512 0 -> 0 512 512 0 -> 0 512 512 0 d9d50c010c0004012e000000d8d50c01
+<118>[ testBody ] [TEST] 512 16 -> 16 496 512 0 -> 16 496 512 0 0c0004022e2e0000ddd50c010c000801
+<118>[ testBody ] [TEST] 512 24 -> 24 488 512 0 -> 24 488 512 0 ddd50c010c00080161000000dfd50c01
+<118>[ testBody ] [TEST] 512 28 -> 28 484 512 0 -> 28 484 512 0 0c00080161000000dfd50c010c000802
+<118>[ testBody ] [TEST] 512 32 -> 32 480 512 0 -> 32 480 512 0 61000000dfd50c010c00080261610000
+<118>[ testBody ] [TEST] 512 40 -> 40 472 512 0 -> 40 472 512 0 0c00080261610000e0d50c010c000803
+<118>[ testBody ] [TEST] 512 47 -> 47 465 512 0 -> 47 465 512 0 00e0d50c010c00080361616100e1d50c
+<118>[ testBody ] [TEST] 512 48 -> 48 464 512 0 -> 48 464 512 0 e0d50c010c00080361616100e1d50c01
+<118>[ testBody ] [TEST] 512 49 -> 49 463 512 0 -> 49 463 512 0 d50c010c00080361616100e1d50c0110
+<118>[ testBody ] [TEST] 512 50 -> 50 462 512 0 -> 50 462 512 0 0c010c00080361616100e1d50c011000
+<118>[ testBody ] [TEST] 512 51 -> 51 461 512 0 -> 51 461 512 0 010c00080361616100e1d50c01100008
+<118>[ testBody ] [TEST] 512 52 -> 52 460 512 0 -> 52 460 512 0 0c00080361616100e1d50c0110000804
+<118>[ testBody ] [TEST] 512 53 -> 53 459 512 0 -> 53 459 512 0 00080361616100e1d50c011000080461
+<118>[ testBody ] [TEST] 512 54 -> 54 458 512 0 -> 54 458 512 0 080361616100e1d50c01100008046161
+<118>[ testBody ] [TEST] 512 55 -> 55 457 512 0 -> 55 457 512 0 0361616100e1d50c0110000804616161
+<118>[ testBody ] [TEST] 512 56 -> 56 456 512 0 -> 56 456 512 0 61616100e1d50c011000080461616161
+<118>[ testBody ] [TEST] 512 57 -> 57 455 512 0 -> 57 455 512 0 616100e1d50c01100008046161616100
+<118>[ testBody ] [TEST] 512 64 -> 64 448 512 0 -> 64 448 512 0 100008046161616100000000e2d50c01
+<118>[ testBody ] [TEST] 512 128 -> 128 384 512 0 -> 128 384 512 0 e5d50c011400080a6161616161616161
+<118>[ testBody ] [TEST] 512 512 -> 512 512 1024 0 -> 512 512 1024 0 f3d50c011c00081066696c656e616d65
+<118>[ testBody ] [TEST] 513 0 -> 0 512 512 0 -> 0 512 512 0 d9d50c010c0004012e000000d8d50c01
+<118>[ testBody ] [TEST] 536 0 -> 0 512 512 0 -> 0 512 512 0 d9d50c010c0004012e000000d8d50c01
+<118>[ testBody ] [TEST] 64 1008 -> 1008 16 1024 0 -> 1008 16 1024 0 78743331000000000000000000000000
+<118>[ testBody ] [TEST] 64 1011 -> 1011 13 1024 0 -> 1011 13 1024 0 31000000000000000000000000aaaaaa
+<118>[ testBody ] [TEST] 64 1012 -> 1012 12 1024 0 -> 1012 12 1024 0 000000000000000000000000aaaaaaaa
+<118>[ testBody ] [TEST] 64 1015 -> 1015 9 1024 0 -> 1015 9 1024 0 000000000000000000aaaaaaaaaaaaaa
+<118>[ testBody ] [TEST] 64 1016 -> 1016 8 1024 0 -> 1016 8 1024 0 0000000000000000aaaaaaaaaaaaaaaa
+<118>[ testBody ] [TEST] 64 1017 -> 1017 7 1024 0 -> 1017 7 1024 0 00000000000000aaaaaaaaaaaaaaaaaa
+<118>[ testBody ] [TEST] 80 1015 -> 1015 9 1024 0 -> 1015 9 1024 0 000000000000000000aaaaaaaaaaaaaa
+<118>[ testBody ] [TEST] 80 1016 -> 1016 8 1024 0 -> 1016 8 1024 0 0000000000000000aaaaaaaaaaaaaaaa
+<118>[ testBody ] [TEST] 80 1017 -> 1017 7 1024 0 -> 1017 7 1024 0 00000000000000aaaaaaaaaaaaaaaaaa
+<118>[ testBody ] [TEST] 1023 0 -> 0 512 512 0 -> 0 512 512 0 d9d50c010c0004012e000000d8d50c01
+<118>[ testBody ] [TEST] 1024 0 -> 0 1024 1024 0 -> 0 1024 1024 0 d9d50c010c0004012e000000d8d50c01
+<118>[ testBody ] [TEST] 1024 511 -> 511 513 1024 0 -> 511 513 1024 0 00f3d50c011c00081066696c656e616d
+<118>[ testBody ] [TEST] 1024 512 -> 512 1024 1536 0 -> 512 1024 1536 0 f3d50c011c00081066696c656e616d65
+<118>[ testBody ] [TEST] 1024 513 -> 513 1023 1536 0 -> 513 1023 1536 0 d50c011c00081066696c656e616d6564
+<118>[ testBody ] [TEST] 1025 513 -> 513 1023 1536 0 -> 513 1023 1536 0 d50c011c00081066696c656e616d6564
+<118>[ testBody ] [TEST] 1026 513 -> 513 1023 1536 0 -> 513 1023 1536 0 d50c011c00081066696c656e616d6564
+<118>[ testBody ] [TEST] 256 256 -> 256 256 512 0 -> 256 256 512 0 00000000ead50c011c00081066696c65
+<118>[ testBody ] [TEST] 23 511 -> 511 1 512 0 -> 511 1 512 0 00aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+<118>[ testBody ] [TEST] 24 511 -> 511 1 512 0 -> 511 1 512 0 00aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+<118>[ testBody ] [TEST] 25 511 -> 511 1 512 0 -> 511 1 512 0 00aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+<118>[ testBody ] [TEST] 8 504 -> 504 8 512 0 -> 504 8 512 0 7874313300000000aaaaaaaaaaaaaaaa
+<118>[ testBody ] [TEST] 16 496 -> 496 16 512 0 -> 496 16 512 0 6e616d65646f74657874313300000000
+<118>[ testBody ] [TEST] 24 488 -> 488 24 512 0 -> 488 24 512 0 1c00081066696c656e616d65646f7465
+<118>[ testBody ] [TEST] 48 464 -> 464 48 512 0 -> 464 48 512 0 66696c656e616d65646f746578743132
+<118>[ testBody ] [TEST] 64 448 -> 448 64 512 0 -> 448 64 512 0 7874313100000000f1d50c011c000810
+<118>[ testBody ] [TEST] 128 384 -> 384 128 512 0 -> 384 128 512 0 6e616d65646f74657874303900000000
+<118>[ testBody ] [TEST] 256 256 -> 256 256 512 0 -> 256 256 512 0 00000000ead50c011c00081066696c65
+<118>[ testBody ] [TEST] 511 1 -> 1 511 512 0 -> 1 511 512 0 d50c010c0004012e000000d8d50c010c
+<118>[ testBody ] [TEST] 32 4064 -> 4064 32 4096 0 -> 4064 32 4096 0 676e616d653037000000000000000000
+<118>[ testBody ] [TEST] 64 4064 -> 4064 32 4096 0 -> 4064 32 4096 0 676e616d653037000000000000000000
+<118>[ testBody ] [TEST] 80 4064 -> 4064 32 4096 0 -> 4064 32 4096 0 676e616d653037000000000000000000
+<118>[ testBody ] [TEST] 112 4064 -> 4064 32 4096 0 -> 4064 32 4096 0 676e616d653037000000000000000000
+<118>[ testBody ] [TEST] 128 4064 -> 4064 32 4096 0 -> 4064 32 4096 0 676e616d653037000000000000000000
+<118>[ testBody ] [TEST] 256 4064 -> 4064 32 4096 0 -> 4064 32 4096 0 676e616d653037000000000000000000
+<118>[ testBody ] [TEST] 544 4064 -> 4064 544 4608 0 -> 4064 544 4608 0 676e616d653037000000000000000000
+<118>[ testBody ] [TEST] 1024 0 -> 0 1024 1024 0 -> 0 1024 1024 0 d9d50c010c0004012e000000d8d50c01
+<118>[ testBody ] [TEST] 32 480 -> 480 32 512 0 -> 480 32 512 0 00000000f2d50c011c00081066696c65
+<118>[ testBody ] [TEST] 1024 10000 -> 10000 0 10000 0 -> 10000 0 10000 0 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+<118>[ testBody ] [TEST] 8192 10000 -> 10000 0 10000 0 -> 10000 0 10000 0 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+<118>[ testBody ] [TEST] 8192 35565 -> 35565 0 35565 0 -> 35565 0 35565 0 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+<118>[ testBody ] [TEST] 511 1024 -> -1 EINVAL 1024 22 -> 170 EINVAL 1024 22 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+<118>[ testBody ] [TEST] 128 4096 -> -1 EINVAL 4096 22 -> 170 EINVAL 4096 22 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+<118>[ testBody ] [TEST] 1024 255 -> 255 769 1024 0 -> 255 769 1024 0 3400000000ead50c011c00081066696c
+<118>[ testBody ] [TEST] 1024 65280 -> 65280 0 65280 0 -> 65280 0 65280 0 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+<118>[ testBody ] [TEST] 1024 16711680 -> 16711680 0 16711680 0 -> 16711680 0 16711680 0 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+<118>[ testBody ] [TEST] 1024 4278190080 -> 4278190080 0 4278190080 0 -> 4278190080 0 4278190080 0 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+<118>[ testBody ] [TEST] 1024 1095216660480 -> 1095216660480 0 1095216660480 0 -> 1095216660480 0 1095216660480 0 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+<118>[ testBody ] [TEST] 1024 280375465082880 -> 280375465082880 0 280375465082880 0 -> 280375465082880 0 280375465082880 0 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+<118>[ testBody ] [TEST] 1024 71776119061217280 -> 71776119061217280 0 71776119061217280 0 -> 71776119061217280 0 71776119061217280 0 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+<118>[ testBody ] [TEST] 1024 -72057594037927936 -> 0 1024 1024 0 -> 0 1024 1024 0 d9d50c010c0004012e000000d8d50c01
+<118>.[ testBody ] [TEST] <<<< PFS getdirentries tests >>>>
+<118>[ testBody ] [TEST] Master PFS getdirentries length is 10656
+<118>[ testBody ] [TEST] 0 0 -> -1 ( 0 ) EINVAL 0 22 -> 170 EINVAL 0 22 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+<118>[ testBody ] [TEST] 128 128 -> -1 ( 128 ) EINVAL 128 22 -> 170 EINVAL 128 22 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+<118>[ testBody ] [TEST] 512 1024 -> 1024 ( 1056 ) 480 1504 0 -> 1024 480 1504 0 280000002800081066696c656e616d65
+<118>[ testBody ] [TEST] 128 128 -> -1 ( 128 ) EINVAL 128 22 -> 170 EINVAL 128 22 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+<118>[ testBody ] [TEST] 512 0 -> 0 ( 0 ) 496 496 0 -> 0 496 496 0 07000000180004012e00000000000000
+<118>[ testBody ] [TEST] 512 16 -> 16 ( 24 ) 472 488 0 -> 16 472 488 0 03000000180004022e2e000000000000
+<118>[ testBody ] [TEST] 512 24 -> 24 ( 24 ) 472 496 0 -> 24 472 496 0 03000000180004022e2e000000000000
+<118>[ testBody ] [TEST] 512 28 -> 28 ( 48 ) 448 476 0 -> 28 448 476 0 0c000000180008016100000000000000
+<118>[ testBody ] [TEST] 512 32 -> 32 ( 48 ) 448 480 0 -> 32 448 480 0 0c000000180008016100000000000000
+<118>[ testBody ] [TEST] 512 40 -> 40 ( 48 ) 448 488 0 -> 40 448 488 0 0c000000180008016100000000000000
+<118>[ testBody ] [TEST] 512 47 -> 47 ( 48 ) 448 495 0 -> 47 448 495 0 0c000000180008016100000000000000
+<118>[ testBody ] [TEST] 512 48 -> 48 ( 48 ) 448 496 0 -> 48 448 496 0 0c000000180008016100000000000000
+<118>[ testBody ] [TEST] 512 49 -> 49 ( 72 ) 424 473 0 -> 49 424 473 0 0d000000180008026161000000000000
+<118>[ testBody ] [TEST] 512 50 -> 50 ( 72 ) 424 474 0 -> 50 424 474 0 0d000000180008026161000000000000
+<118>[ testBody ] [TEST] 512 51 -> 51 ( 72 ) 424 475 0 -> 51 424 475 0 0d000000180008026161000000000000
+<118>[ testBody ] [TEST] 512 52 -> 52 ( 72 ) 424 476 0 -> 52 424 476 0 0d000000180008026161000000000000
+<118>[ testBody ] [TEST] 512 53 -> 53 ( 72 ) 424 477 0 -> 53 424 477 0 0d000000180008026161000000000000
+<118>[ testBody ] [TEST] 512 54 -> 54 ( 72 ) 424 478 0 -> 54 424 478 0 0d000000180008026161000000000000
+<118>[ testBody ] [TEST] 512 55 -> 55 ( 72 ) 424 479 0 -> 55 424 479 0 0d000000180008026161000000000000
+<118>[ testBody ] [TEST] 512 56 -> 56 ( 72 ) 424 480 0 -> 56 424 480 0 0d000000180008026161000000000000
+<118>[ testBody ] [TEST] 512 57 -> 57 ( 72 ) 424 481 0 -> 57 424 481 0 0d000000180008026161000000000000
+<118>[ testBody ] [TEST] 512 64 -> 64 ( 72 ) 424 488 0 -> 64 424 488 0 0d000000180008026161000000000000
+<118>[ testBody ] [TEST] 512 128 -> 128 ( 144 ) 352 480 0 -> 128 352 480 0 10000000180008056161616161000000
+<118>[ testBody ] [TEST] 512 512 -> 512 ( 536 ) 480 992 0 -> 512 480 992 0 1b0000002800081066696c656e616d65
+<118>[ testBody ] [TEST] 513 0 -> 0 ( 0 ) 496 496 0 -> 0 496 496 0 07000000180004012e00000000000000
+<118>[ testBody ] [TEST] 536 0 -> 0 ( 0 ) 496 496 0 -> 0 496 496 0 07000000180004012e00000000000000
+<118>[ testBody ] [TEST] 64 1008 -> 1008 ( 1016 ) 0 1008 0 -> 1008 0 1008 0 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+<118>[ testBody ] [TEST] 64 1011 -> 1011 ( 1016 ) 0 1011 0 -> 1011 0 1011 0 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+<118>[ testBody ] [TEST] 64 1012 -> 1012 ( 1016 ) 0 1012 0 -> 1012 0 1012 0 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+<118>[ testBody ] [TEST] 64 1015 -> 1015 ( 1016 ) 0 1015 0 -> 1015 0 1015 0 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+<118>[ testBody ] [TEST] 64 1016 -> 1016 ( 1016 ) 0 1016 0 -> 1016 0 1016 0 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+<118>[ testBody ] [TEST] 64 1017 -> 1017 ( 1056 ) 0 1017 0 -> 1017 0 1017 0 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+<118>[ testBody ] [TEST] 80 1015 -> 1015 ( 1016 ) 0 1015 0 -> 1015 0 1015 0 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+<118>[ testBody ] [TEST] 80 1016 -> 1016 ( 1016 ) 0 1016 0 -> 1016 0 1016 0 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+<118>[ testBody ] [TEST] 80 1017 -> 1017 ( 1056 ) 0 1017 0 -> 1017 0 1017 0 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+<118>[ testBody ] [TEST] 1023 0 -> 0 ( 0 ) 496 496 0 -> 0 496 496 0 07000000180004012e00000000000000
+<118>[ testBody ] [TEST] 1024 0 -> 0 ( 0 ) 1016 1016 0 -> 0 1016 1016 0 07000000180004012e00000000000000
+<118>[ testBody ] [TEST] 1024 511 -> 511 ( 536 ) 480 991 0 -> 511 480 991 0 1b0000002800081066696c656e616d65
+<118>[ testBody ] [TEST] 1024 512 -> 512 ( 536 ) 1000 1512 0 -> 512 1000 1512 0 1b0000002800081066696c656e616d65
+<118>[ testBody ] [TEST] 1024 513 -> 513 ( 536 ) 1000 1513 0 -> 513 1000 1513 0 1b0000002800081066696c656e616d65
+<118>[ testBody ] [TEST] 1025 513 -> 513 ( 536 ) 1000 1513 0 -> 513 1000 1513 0 1b0000002800081066696c656e616d65
+<118>[ testBody ] [TEST] 1026 513 -> 513 ( 536 ) 1000 1513 0 -> 513 1000 1513 0 1b0000002800081066696c656e616d65
+<118>[ testBody ] [TEST] 256 256 -> 256 ( 256 ) 240 496 0 -> 256 240 496 0 140000002800081066696c656e616d65
+<118>[ testBody ] [TEST] 23 511 -> 511 ( 536 ) 0 511 0 -> 511 0 511 0 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+<118>[ testBody ] [TEST] 24 511 -> 511 ( 536 ) 0 511 0 -> 511 0 511 0 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+<118>[ testBody ] [TEST] 25 511 -> 511 ( 536 ) 0 511 0 -> 511 0 511 0 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+<118>[ testBody ] [TEST] 8 504 -> 504 ( 536 ) 0 504 0 -> 504 0 504 0 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+<118>[ testBody ] [TEST] 16 496 -> 496 ( 496 ) 0 496 0 -> 496 0 496 0 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+<118>[ testBody ] [TEST] 24 488 -> 488 ( 496 ) 0 488 0 -> 488 0 488 0 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+<118>[ testBody ] [TEST] 48 464 -> 464 ( 496 ) 40 504 0 -> 464 40 504 0 1a0000002800081066696c656e616d65
+<118>[ testBody ] [TEST] 64 448 -> 448 ( 456 ) 40 488 0 -> 448 40 488 0 190000002800081066696c656e616d65
+<118>[ testBody ] [TEST] 128 384 -> 384 ( 416 ) 120 504 0 -> 384 120 504 0 180000002800081066696c656e616d65
+<118>[ testBody ] [TEST] 256 256 -> 256 ( 256 ) 240 496 0 -> 256 240 496 0 140000002800081066696c656e616d65
+<118>[ testBody ] [TEST] 511 1 -> 1 ( 24 ) 472 473 0 -> 1 472 473 0 03000000180004022e2e000000000000
+<118>[ testBody ] [TEST] 32 4064 -> 4064 ( 4104 ) 0 4064 0 -> 4064 0 4064 0 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+<118>[ testBody ] [TEST] 64 4064 -> 4064 ( 4104 ) 0 4064 0 -> 4064 0 4064 0 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+<118>[ testBody ] [TEST] 80 4064 -> 4064 ( 4104 ) 0 4064 0 -> 4064 0 4064 0 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+<118>[ testBody ] [TEST] 112 4064 -> 4064 ( 4104 ) 0 4064 0 -> 4064 0 4064 0 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+<118>[ testBody ] [TEST] 128 4064 -> 4064 ( 4104 ) 0 4064 0 -> 4064 0 4064 0 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+<118>[ testBody ] [TEST] 256 4064 -> 4064 ( 4104 ) 0 4064 0 -> 4064 0 4064 0 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+<118>[ testBody ] [TEST] 544 4064 -> 4064 ( 4104 ) 504 4568 0 -> 4064 504 4568 0 670000003800082066696c6577697468
+<118>[ testBody ] [TEST] 1024 0 -> 0 ( 0 ) 1016 1016 0 -> 0 1016 1016 0 07000000180004012e00000000000000
+<118>[ testBody ] [TEST] 32 480 -> 480 ( 496 ) 0 480 0 -> 480 0 480 0 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+<118>[ testBody ] [TEST] 1024 10000 -> 10000 ( 10008 ) 648 65536 0 -> 10000 648 65536 0 d30000004800083466696c6577697468
+<118>[ testBody ] [TEST] 8192 10000 -> 10000 ( 10008 ) 648 65536 0 -> 10000 648 65536 0 d30000004800083466696c6577697468
+<118>[ testBody ] [TEST] 8192 35565 -> 35565 ( 35565 ) 0 65536 0 -> 35565 0 65536 0 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+<118>[ testBody ] [TEST] 511 1024 -> -1 ( 1024 ) EINVAL 1024 22 -> 170 EINVAL 1024 22 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+<118>[ testBody ] [TEST] 128 4096 -> -1 ( 4096 ) EINVAL 4096 22 -> 170 EINVAL 4096 22 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+<118>[ testBody ] [TEST] 1024 255 -> 255 ( 256 ) 760 1015 0 -> 255 760 1015 0 140000002800081066696c656e616d65
+<118>[ testBody ] [TEST] 1024 65280 -> 65280 ( 65280 ) 0 65536 0 -> 65280 0 65536 0 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+<118>[ testBody ] [TEST] 1024 16711680 -> 16711680 ( 16711680 ) 0 16711680 0 -> 16711680 0 16711680 0 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+<118>[ testBody ] [TEST] 1024 4278190080 -> 4278190080 ( 4278190080 ) 0 4278190080 0 -> 4278190080 0 4278190080 0 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+<118>[ testBody ] [TEST] 1024 1095216660480 -> 1095216660480 ( 1095216660480 ) 0 1095216660480 0 -> 1095216660480 0 1095216660480 0 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+<118>[ testBody ] [TEST] 1024 280375465082880 -> 280375465082880 ( 280375465082880 ) 0 280375465082880 0 -> 280375465082880 0 280375465082880 0 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+<118>[ testBody ] [TEST] 1024 71776119061217280 -> 71776119061217280 ( 71776119061217280 ) 0 71776119061217280 0 -> 71776119061217280 0 71776119061217280 0 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+<118>[ testBody ] [TEST] 1024 -72057594037927936 -> 0 ( 0 ) 1016 1016 0 -> 0 1016 1016 0 07000000180004012e00000000000000
+<118>.[ testBody ] [TEST] <<<< Normal getdirentries fuzzing test >>>>
+<118>[ testBody ] [TEST] Note: Only first 20 bad entries are shown
+<118>[ testBody ] [TEST] Note: This may take a while
+<118>[ testBody ] [TEST] Master Normal getdirentries length is 8704 , testing 200000 samples , max 20 bad returns are shown
+<118>[ testBody ] [SUCC] Fuzzing passed!
+<118>.[ testBody ] [TEST] <<<< PFS getdirentries fuzzing test >>>>
+<118>[ testBody ] [TEST] Note: Only first 20 bad entries are shown
+<118>[ testBody ] [TEST] Note: This may take a while
+<118>[ testBody ] [TEST] Master PFS getdirentries length is 10656 , testing 200000 samples , max 20 bad returns are shown
+<118>[ testBody ] [SUCC] Fuzzing passed!
+<118>.
+<118>OK (16 tests, 16 ran, 32 checks, 0 ignored, 0 filtered out, 48031 ms)
+<118>
+<118>[ main ] [INFO]
+<118>[ main ] [INFO] <<<< TESTS END >>>>
+<118>[ main ] [INFO]
\ No newline at end of file
diff --git a/tests/code/filesystem_dirents/dumps/requirements.txt b/tests/code/filesystem_dirents/dumps/requirements.txt
new file mode 100644
index 00000000..79a829bf
--- /dev/null
+++ b/tests/code/filesystem_dirents/dumps/requirements.txt
@@ -0,0 +1 @@
+black==26.1.0
\ No newline at end of file
diff --git a/tests/code/filesystem_dirents/sce_sys/icon0.png b/tests/code/filesystem_dirents/sce_sys/icon0.png
new file mode 100644
index 00000000..a94ec83c
Binary files /dev/null and b/tests/code/filesystem_dirents/sce_sys/icon0.png differ
diff --git a/tests/code/filesystem_speed_test/CMakeLists.txt b/tests/code/filesystem_speed_test/CMakeLists.txt
new file mode 100644
index 00000000..81537cd4
--- /dev/null
+++ b/tests/code/filesystem_speed_test/CMakeLists.txt
@@ -0,0 +1,8 @@
+project(Amphitheathre VERSION 0.0.1)
+
+link_libraries(SceSystemService)
+
+create_pkg(TEST00666 5 50 "code/log.cpp;code/fs_test_tools.cpp;code/fs_test.cpp;code/main.cpp")
+set_target_properties(TEST00666 PROPERTIES OO_PKG_TITLE "Amphitheathre")
+set_target_properties(TEST00666 PROPERTIES OO_PKG_APPVER "1.02")
+finalize_pkg(TEST00666)
diff --git a/tests/code/filesystem_speed_test/LICENSE b/tests/code/filesystem_speed_test/LICENSE
new file mode 100644
index 00000000..f288702d
--- /dev/null
+++ b/tests/code/filesystem_speed_test/LICENSE
@@ -0,0 +1,674 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc.
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The GNU General Public License is a free, copyleft license for
+software and other kinds of works.
+
+ The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works. By contrast,
+the GNU General Public License is intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users. We, the Free Software Foundation, use the
+GNU General Public License for most of our software; it applies also to
+any other work released this way by its authors. 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
+them 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 prevent others from denying you
+these rights or asking you to surrender the rights. Therefore, you have
+certain responsibilities if you distribute copies of the software, or if
+you modify it: responsibilities to respect the freedom of others.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must pass on to the recipients the same
+freedoms that you received. 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.
+
+ Developers that use the GNU GPL protect your rights with two steps:
+(1) assert copyright on the software, and (2) offer you this License
+giving you legal permission to copy, distribute and/or modify it.
+
+ For the developers' and authors' protection, the GPL clearly explains
+that there is no warranty for this free software. For both users' and
+authors' sake, the GPL requires that modified versions be marked as
+changed, so that their problems will not be attributed erroneously to
+authors of previous versions.
+
+ Some devices are designed to deny users access to install or run
+modified versions of the software inside them, although the manufacturer
+can do so. This is fundamentally incompatible with the aim of
+protecting users' freedom to change the software. The systematic
+pattern of such abuse occurs in the area of products for individuals to
+use, which is precisely where it is most unacceptable. Therefore, we
+have designed this version of the GPL to prohibit the practice for those
+products. If such problems arise substantially in other domains, we
+stand ready to extend this provision to those domains in future versions
+of the GPL, as needed to protect the freedom of users.
+
+ Finally, every program is threatened constantly by software patents.
+States should not allow patents to restrict development and use of
+software on general-purpose computers, but in those that do, we wish to
+avoid the special danger that patents applied to a free program could
+make it effectively proprietary. To prevent this, the GPL assures that
+patents cannot be used to render the program non-free.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ TERMS AND CONDITIONS
+
+ 0. Definitions.
+
+ "This License" refers to version 3 of the GNU General Public License.
+
+ "Copyright" also means copyright-like laws that apply to other kinds of
+works, such as semiconductor masks.
+
+ "The Program" refers to any copyrightable work licensed under this
+License. Each licensee is addressed as "you". "Licensees" and
+"recipients" may be individuals or organizations.
+
+ To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy. The resulting work is called a "modified version" of the
+earlier work or a work "based on" the earlier work.
+
+ A "covered work" means either the unmodified Program or a work based
+on the Program.
+
+ To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy. Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+ To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies. Mere interaction with a user through
+a computer network, with no transfer of a copy, is not conveying.
+
+ An interactive user interface displays "Appropriate Legal Notices"
+to the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License. If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+ 1. Source Code.
+
+ The "source code" for a work means the preferred form of the work
+for making modifications to it. "Object code" means any non-source
+form of a work.
+
+ A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+ The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form. A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+ The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities. However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work. For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+ The Corresponding Source need not include anything that users
+can regenerate automatically from other parts of the Corresponding
+Source.
+
+ The Corresponding Source for a work in source code form is that
+same work.
+
+ 2. Basic Permissions.
+
+ All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met. This License explicitly affirms your unlimited
+permission to run the unmodified Program. The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work. This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+ You may make, run and propagate covered works that you do not
+convey, without conditions so long as your license otherwise remains
+in force. You may convey covered works to others for the sole purpose
+of having them make modifications exclusively for you, or provide you
+with facilities for running those works, provided that you comply with
+the terms of this License in conveying all material for which you do
+not control copyright. Those thus making or running the covered works
+for you must do so exclusively on your behalf, under your direction
+and control, on terms that prohibit them from making any copies of
+your copyrighted material outside their relationship with you.
+
+ Conveying under any other circumstances is permitted solely under
+the conditions stated below. Sublicensing is not allowed; section 10
+makes it unnecessary.
+
+ 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+ No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+ When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such circumvention
+is effected by exercising rights under this License with respect to
+the covered work, and you disclaim any intention to limit operation or
+modification of the work as a means of enforcing, against the work's
+users, your or third parties' legal rights to forbid circumvention of
+technological measures.
+
+ 4. Conveying Verbatim Copies.
+
+ You may convey 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;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+ You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+ 5. Conveying Modified Source Versions.
+
+ You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these conditions:
+
+ a) The work must carry prominent notices stating that you modified
+ it, and giving a relevant date.
+
+ b) The work must carry prominent notices stating that it is
+ released under this License and any conditions added under section
+ 7. This requirement modifies the requirement in section 4 to
+ "keep intact all notices".
+
+ c) You must license the entire work, as a whole, under this
+ License to anyone who comes into possession of a copy. This
+ License will therefore apply, along with any applicable section 7
+ additional terms, to the whole of the work, and all its parts,
+ regardless of how they are packaged. This License gives no
+ permission to license the work in any other way, but it does not
+ invalidate such permission if you have separately received it.
+
+ d) If the work has interactive user interfaces, each must display
+ Appropriate Legal Notices; however, if the Program has interactive
+ interfaces that do not display Appropriate Legal Notices, your
+ work need not make them do so.
+
+ A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit. Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+ 6. Conveying Non-Source Forms.
+
+ You may convey a covered work in object code form under the terms
+of sections 4 and 5, provided that you also convey the
+machine-readable Corresponding Source under the terms of this License,
+in one of these ways:
+
+ a) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by the
+ Corresponding Source fixed on a durable physical medium
+ customarily used for software interchange.
+
+ b) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by a
+ written offer, valid for at least three years and valid for as
+ long as you offer spare parts or customer support for that product
+ model, to give anyone who possesses the object code either (1) a
+ copy of the Corresponding Source for all the software in the
+ product that is covered by this License, on a durable physical
+ medium customarily used for software interchange, for a price no
+ more than your reasonable cost of physically performing this
+ conveying of source, or (2) access to copy the
+ Corresponding Source from a network server at no charge.
+
+ c) Convey individual copies of the object code with a copy of the
+ written offer to provide the Corresponding Source. This
+ alternative is allowed only occasionally and noncommercially, and
+ only if you received the object code with such an offer, in accord
+ with subsection 6b.
+
+ d) Convey the object code by offering access from a designated
+ place (gratis or for a charge), and offer equivalent access to the
+ Corresponding Source in the same way through the same place at no
+ further charge. You need not require recipients to copy the
+ Corresponding Source along with the object code. If the place to
+ copy the object code is a network server, the Corresponding Source
+ may be on a different server (operated by you or a third party)
+ that supports equivalent copying facilities, provided you maintain
+ clear directions next to the object code saying where to find the
+ Corresponding Source. Regardless of what server hosts the
+ Corresponding Source, you remain obligated to ensure that it is
+ available for as long as needed to satisfy these requirements.
+
+ e) Convey the object code using peer-to-peer transmission, provided
+ you inform other peers where the object code and Corresponding
+ Source of the work are being offered to the general public at no
+ charge under subsection 6d.
+
+ A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+ A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal, family,
+or household purposes, or (2) anything designed or sold for incorporation
+into a dwelling. In determining whether a product is a consumer product,
+doubtful cases shall be resolved in favor of coverage. For a particular
+product received by a particular user, "normally used" refers to a
+typical or common use of that class of product, regardless of the status
+of the particular user or of the way in which the particular user
+actually uses, or expects or is expected to use, the product. A product
+is a consumer product regardless of whether the product has substantial
+commercial, industrial or non-consumer uses, unless such uses represent
+the only significant mode of use of the product.
+
+ "Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to install
+and execute modified versions of a covered work in that User Product from
+a modified version of its Corresponding Source. The information must
+suffice to ensure that the continued functioning of the modified object
+code is in no case prevented or interfered with solely because
+modification has been made.
+
+ If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information. But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+ The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or updates
+for a work that has been modified or installed by the recipient, or for
+the User Product in which it has been modified or installed. Access to a
+network may be denied when the modification itself materially and
+adversely affects the operation of the network or violates the rules and
+protocols for communication across the network.
+
+ Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+ 7. Additional Terms.
+
+ "Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law. If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+ When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it. (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.) You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+ Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders of
+that material) supplement the terms of this License with terms:
+
+ a) Disclaiming warranty or limiting liability differently from the
+ terms of sections 15 and 16 of this License; or
+
+ b) Requiring preservation of specified reasonable legal notices or
+ author attributions in that material or in the Appropriate Legal
+ Notices displayed by works containing it; or
+
+ c) Prohibiting misrepresentation of the origin of that material, or
+ requiring that modified versions of such material be marked in
+ reasonable ways as different from the original version; or
+
+ d) Limiting the use for publicity purposes of names of licensors or
+ authors of the material; or
+
+ e) Declining to grant rights under trademark law for use of some
+ trade names, trademarks, or service marks; or
+
+ f) Requiring indemnification of licensors and authors of that
+ material by anyone who conveys the material (or modified versions of
+ it) with contractual assumptions of liability to the recipient, for
+ any liability that these contractual assumptions directly impose on
+ those licensors and authors.
+
+ All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10. If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term. If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+ If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+ Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions;
+the above requirements apply either way.
+
+ 8. Termination.
+
+ You may not propagate or modify a covered work except as expressly
+provided under this License. Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+ However, if you cease all violation of this License, then your
+license from a particular copyright holder is reinstated (a)
+provisionally, unless and until the copyright holder explicitly and
+finally terminates your license, and (b) permanently, if the copyright
+holder fails to notify you of the violation by some reasonable means
+prior to 60 days after the cessation.
+
+ Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+ Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License. If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+ 9. Acceptance Not Required for Having Copies.
+
+ You are not required to accept this License in order to receive or
+run a copy of the Program. Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance. However,
+nothing other than this License grants you permission to propagate or
+modify any covered work. These actions infringe copyright if you do
+not accept this License. Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+ 10. Automatic Licensing of Downstream Recipients.
+
+ Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License. You are not responsible
+for enforcing compliance by third parties with this License.
+
+ An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations. If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+ You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License. For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+ 11. Patents.
+
+ A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based. The
+work thus licensed is called the contributor's "contributor version".
+
+ A contributor's "essential patent claims" are all patent claims
+owned or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version. For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+ Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+ In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement). To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+ If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients. "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+ If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+ A patent license is "discriminatory" if it does not include within
+the scope of its coverage, prohibits the exercise of, or is
+conditioned on the non-exercise of one or more of the rights that are
+specifically granted under this License. You may not convey a covered
+work if you are a party to an arrangement with a third party that is
+in the business of distributing software, under which you make payment
+to the third party based on the extent of your activity of conveying
+the work, and under which the third party grants, to any of the
+parties who would receive the covered work from you, a discriminatory
+patent license (a) in connection with copies of the covered work
+conveyed by you (or copies made from those copies), or (b) primarily
+for and in connection with specific products or compilations that
+contain the covered work, unless you entered into that arrangement,
+or that patent license was granted, prior to 28 March 2007.
+
+ Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+ 12. No Surrender of Others' Freedom.
+
+ If 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 convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you may
+not convey it at all. For example, if you agree to terms that obligate you
+to collect a royalty for further conveying from those to whom you convey
+the Program, the only way you could satisfy both those terms and this
+License would be to refrain entirely from conveying the Program.
+
+ 13. Use with the GNU Affero General Public License.
+
+ Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU Affero General Public License into a single
+combined work, and to convey the resulting work. The terms of this
+License will continue to apply to the part which is the covered work,
+but the special requirements of the GNU Affero General Public License,
+section 13, concerning interaction through a network will apply to the
+combination as such.
+
+ 14. Revised Versions of this License.
+
+ The Free Software Foundation may publish revised and/or new versions of
+the GNU 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 that a certain numbered version of the GNU General
+Public License "or any later version" applies to it, you have the
+option of following the terms and conditions either of that numbered
+version or of any later version published by the Free Software
+Foundation. If the Program does not specify a version number of the
+GNU General Public License, you may choose any version ever published
+by the Free Software Foundation.
+
+ If the Program specifies that a proxy can decide which future
+versions of the GNU General Public License can be used, that proxy's
+public statement of acceptance of a version permanently authorizes you
+to choose that version for the Program.
+
+ Later license versions may give you additional or different
+permissions. However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+ 15. Disclaimer of Warranty.
+
+ 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.
+
+ 16. Limitation of Liability.
+
+ IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+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.
+
+ 17. Interpretation of Sections 15 and 16.
+
+ If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+
+ 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
+state the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+
+ Copyright (C)
+
+ 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 3 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, see .
+
+Also add information on how to contact you by electronic and paper mail.
+
+ If the program does terminal interaction, make it output a short
+notice like this when it starts in an interactive mode:
+
+ Copyright (C)
+ This program 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, your program's commands
+might be different; for a GUI interface, you would use an "about box".
+
+ You should also get your employer (if you work as a programmer) or school,
+if any, to sign a "copyright disclaimer" for the program, if necessary.
+For more information on this, and how to apply and follow the GNU GPL, see
+.
+
+ The GNU 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. But first, please read
+.
diff --git a/tests/code/filesystem_speed_test/README.md b/tests/code/filesystem_speed_test/README.md
new file mode 100644
index 00000000..3788e9cc
--- /dev/null
+++ b/tests/code/filesystem_speed_test/README.md
@@ -0,0 +1,11 @@
+# OpenOrbis CMake project
+
+This is a template for quick start with PS4 development using OpenOrbis toolchain.
+
+## Usage
+
+```bash
+cmake -B./build/ -S./ -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DCMAKE_TOOLCHAIN_FILE=OpenOrbis-tc.cmake
+cmake --build ./build/ -j8
+cmake --install .
+```
diff --git a/tests/code/filesystem_speed_test/assets/misc/big_directory/.gitkeep b/tests/code/filesystem_speed_test/assets/misc/big_directory/.gitkeep
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_speed_test/code/fs_test.cpp b/tests/code/filesystem_speed_test/code/fs_test.cpp
new file mode 100644
index 00000000..33b1f895
--- /dev/null
+++ b/tests/code/filesystem_speed_test/code/fs_test.cpp
@@ -0,0 +1,120 @@
+#include "fs_test.h"
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+namespace fs = std::filesystem;
+
+namespace FS_Test {
+namespace oi = OrbisInternals;
+
+#define ITER_ACTION 2500
+#define ITER_READS 5
+#define ITER_WRITES 5
+
+// chunk = 8, order = 1 -> 8b, multiples - how many chunks to write for testing
+// =4, =3 -> 4MB
+void testWrite(u64 base, u64 order, u64 multiples, const char* path) {
+ u64 test_start = 0;
+ u64 test_end = 0;
+ u64 write_test_chunk = base * (std::pow(1024, order));
+ u64 write_test_bytes = multiples * write_test_chunk;
+ u64 write_test_start = 0;
+ u64 write_test_total = 0;
+ u8* write_test_buffer = new u8[write_test_chunk] {255};
+
+ char size_str[3] = {'x', 'B', 0};
+ switch (order) {
+ case 0: size_str[0] = 'b'; break;
+ case 1: size_str[0] = 'k'; break;
+ case 2: size_str[0] = 'M'; break;
+ case 3: size_str[0] = 'G'; break;
+ }
+
+ test_start = tick();
+ for (auto i = ITER_WRITES; i; i--) {
+ sceKernelUnlink(path);
+ int fd = sceKernelOpen(path, O_WRONLY | O_CREAT, 0777);
+ write_test_start = tick();
+ for (u32 i = 0; i < write_test_bytes; i += write_test_chunk) {
+ sceKernelWrite(fd, write_test_buffer, write_test_chunk);
+ }
+ sceKernelFsync(fd);
+ write_test_total += tick() - write_test_start;
+ }
+ test_end = tick();
+
+ double write_test_throughput = ITER_WRITES * double(write_test_bytes) / double(write_test_total);
+ Log("write() in /data:", write_test_total / (ITER_WRITES * 1000), "us/it");
+ Log("write+sync speed:", write_test_throughput * 1000000000.0 / (1024 * 1024), "MB/s");
+ Log("write+sync duration:", write_test_total / 1000000000.0, "s");
+ Log("Test duration:", (test_end - test_start) / 1000000000.0, "s");
+ delete[] write_test_buffer;
+}
+
+void RunTests() {
+ RegenerateDir("/data/amphitheathre");
+
+ Log();
+ Log("<<<< TEST SUITE STARTING >>>>");
+ Log("Function iterations:", ITER_ACTION);
+ Log("Read iterations:", ITER_READS);
+ Log("Write iterations:", ITER_WRITES);
+
+ u64 test_start = 0;
+ u64 test_end = 0;
+ double test_duration = 0;
+ int fd = 0;
+
+ Log();
+ Log("\t<<<< open() >>>>");
+ Log();
+
+ u64 open_start = 0;
+ u64 open_total = 0;
+ test_start = tick();
+ touch("/data/amphitheathre/open_file");
+ for (auto i = ITER_ACTION; i; i--) {
+ open_start = tick();
+ fd = sceKernelOpen("/data/amphitheathre/open_file", O_RDONLY, 0777);
+ open_total += tick() - open_start;
+ sceKernelClose(fd);
+ }
+ test_end = tick();
+ test_duration = (test_end - test_start) / 1000;
+ Log("open() in /data, one file:", open_total / ITER_ACTION, "ns/it");
+ Log("Action duration:", open_total / 1000, "us");
+ Log("Test duration:", test_duration, "us");
+
+ Log();
+ Log("\t<<<< write() 4KB speed test >>>>");
+ Log("\tNormalized to 1GB") Log();
+ testWrite(4, 1, 262144, "/data/amphitheathre/write_benchmark_4kB");
+ Log();
+ Log("\t<<<< write() 8KB speed test >>>>");
+ Log("\tNormalized to 1GB") Log();
+ testWrite(8, 1, 131072, "/data/amphitheathre/write_benchmark_8kB");
+ Log();
+ Log("\t<<<< write() 64kB speed test >>>>");
+ Log("\tNormalized to 1GB") Log();
+ testWrite(64, 1, 16384, "/data/amphitheathre/write_benchmark_64kB");
+ Log();
+ Log("\t<<<< write() 1MB speed test >>>>");
+ Log("\tNormalized to 1GB") Log();
+ testWrite(1, 2, 1024, "/data/amphitheathre/write_benchmark_1MB");
+ Log();
+ Log("\t<<<< write() 4MB speed test >>>>");
+ Log("\tNormalized to 1GB") Log();
+ testWrite(4, 2, 256, "/data/amphitheathre/write_benchmark_4MB");
+ Log();
+ Log("\t<<<< write() 8MB speed test >>>>");
+ Log("\tNormalized to 1GB") Log();
+ testWrite(8, 2, 128, "/data/amphitheathre/write_benchmark_8MB");
+}
+} // namespace FS_Test
\ No newline at end of file
diff --git a/tests/code/filesystem_speed_test/code/fs_test.h b/tests/code/filesystem_speed_test/code/fs_test.h
new file mode 100644
index 00000000..f229c0ad
--- /dev/null
+++ b/tests/code/filesystem_speed_test/code/fs_test.h
@@ -0,0 +1,61 @@
+#ifndef FS_TEST_H
+#define FS_TEST_H
+
+#include "log.h"
+
+#include
+#include
+#include
+#include
+#include
+#include
+
+namespace fs = std::filesystem;
+
+namespace FS_Test {
+#define DIRENT_PFS_BUFFER_SIZE 65536
+#define DIRENT_BUFFER_SIZE 512
+
+using s8 = int8_t;
+using s16 = int16_t;
+using s32 = int32_t;
+using s64 = int64_t;
+
+using u8 = uint8_t;
+using u16 = uint16_t;
+using u32 = uint32_t;
+using u64 = uint64_t;
+
+namespace OrbisInternals {
+typedef struct PfsDirent {
+ s32 d_fileno;
+ s32 d_type;
+ s32 d_namlen;
+ s32 d_reclen;
+ char d_name[256];
+} PfsDirent;
+
+typedef struct FolderDirent {
+ u32 d_fileno;
+ u16 d_reclen;
+ u8 d_type;
+ u8 d_namlen;
+ char d_name[256];
+} FolderDirent;
+} // namespace OrbisInternals
+
+void RunTests(void);
+void RegenerateDir(const char* path);
+
+ino_t get_fileno(const char* path);
+ino_t get_fileno(int fd);
+void Obliterate(const char* path);
+int32_t touch(const char* path);
+off_t GetSize(const char* path);
+off_t GetSize(int fd);
+int exists(const char* path);
+
+u64 tick();
+
+} // namespace FS_Test
+#endif // FS_TEST_H
diff --git a/tests/code/filesystem_speed_test/code/fs_test_tools.cpp b/tests/code/filesystem_speed_test/code/fs_test_tools.cpp
new file mode 100644
index 00000000..35a397a4
--- /dev/null
+++ b/tests/code/filesystem_speed_test/code/fs_test_tools.cpp
@@ -0,0 +1,101 @@
+#include "fs_test.h"
+
+#include
+#include
+#include
+#include
+#include
+#include
+
+namespace FS_Test {
+namespace oi = OrbisInternals;
+
+void RegenerateDir(const char* path) {
+ Obliterate(path);
+ sceKernelMkdir(path, 0777);
+}
+
+off_t GetSize(int fd) {
+ OrbisKernelStat st;
+ if (int status = sceKernelFstat(fd, &st); status < 0) return status;
+ return st.st_size;
+}
+
+off_t GetSize(const char* path) {
+ OrbisKernelStat st;
+ if (int status = sceKernelStat(path, &st); status < 0) return status;
+ return st.st_size;
+}
+
+int32_t touch(const char* path) {
+ return sceKernelClose(sceKernelOpen(path, O_RDWR | O_CREAT | O_TRUNC, 0777));
+}
+
+ino_t get_fileno(int fd) {
+ struct OrbisKernelStat st {};
+ int status = sceKernelFstat(fd, &st);
+ return (status == 0) * st.st_ino;
+}
+
+ino_t get_fileno(const char* path) {
+ struct OrbisKernelStat st {};
+ int fd = sceKernelOpen(path, O_RDONLY, 0777);
+ if (fd < 0) return 0;
+ int status = sceKernelFstat(fd, &st);
+ sceKernelClose(fd);
+ return (status == 0) * st.st_ino;
+}
+
+int exists(const char* path) {
+ struct OrbisKernelStat ost {};
+ return sceKernelStat(path, &ost);
+}
+
+void Obliterate(const char* path) {
+ Log("<< rm -rf [", path, "] >>");
+ std::error_code ec {};
+
+ std::vector entries;
+ for (auto& p: fs::recursive_directory_iterator(path, fs::directory_options::skip_permission_denied, ec))
+ entries.push_back(p.path().string());
+
+ for (auto it = entries.rbegin(); it != entries.rend(); ++it) {
+ if (ec) {
+ LogError("Exception: [", ec.value(), "] :", ec.message());
+ ec.clear();
+ continue;
+ }
+
+ const char* pp = it->c_str();
+
+ // see what sticks
+
+ struct OrbisKernelStat st {0};
+
+ errno = 0;
+ sceKernelStat(pp, &st);
+ if (2 == errno)
+ // not found, good
+ continue;
+
+ errno = 0;
+ if (S_ISDIR(st.st_mode)) sceKernelRmdir(pp);
+ if (S_ISREG(st.st_mode)) sceKernelUnlink(pp);
+
+ if (errno != 0) LogError("Cannot remove [", pp, "] ( errno =", errno, ")");
+ }
+
+ errno = 0;
+ sceKernelRmdir(path);
+
+ if (!(ENOENT == errno || 0 == errno)) LogError("Cannot remove [", path, "] ( errno =", errno, ")");
+
+ LogSuccess(">> rm -rf [", path, "] <<");
+ return;
+}
+
+u64 tick() {
+ using namespace std::chrono;
+ return duration_cast(high_resolution_clock::now().time_since_epoch()).count();
+}
+} // namespace FS_Test
\ No newline at end of file
diff --git a/tests/code/filesystem_speed_test/code/log.cpp b/tests/code/filesystem_speed_test/code/log.cpp
new file mode 100644
index 00000000..3381d8da
--- /dev/null
+++ b/tests/code/filesystem_speed_test/code/log.cpp
@@ -0,0 +1,62 @@
+#include "log.h"
+
+#include
+#include
+
+int error_counter = 0;
+
+int GetErrorCounter(void) {
+ return error_counter;
+}
+
+void ResetErrorCounter(void) {
+ error_counter = 0;
+}
+
+std::ostream& center(std::ostream& os, const std::string& s, int width) {
+ int len = (int)s.size();
+ if (width <= len) return os << s.substr(0, width);
+ int left = (width - len) / 2;
+ int right = width - len - left;
+ return os << std::string(left, ' ') << s << std::string(right, ' ');
+}
+
+std::ostream& right(std::ostream& os, const std::string& s, int width) {
+ int len = (int)s.size();
+ if (width <= len) return os << s.substr(0, width);
+ int left = (width - len);
+ return os << std::string(left, ' ') << s;
+}
+
+std::string center(const std::string& s, int width) {
+ int len = (int)s.size();
+ if (width <= len) return s.substr(0, width);
+ int left = (width - len) / 2;
+ int right = width - len - left;
+ return std::string(left, ' ') + s + std::string(right, ' ');
+}
+
+std::string right(const std::string& s, int width) {
+ int len = (int)s.size();
+ if (width <= len) return s.substr(0, width);
+ int left = (width - len);
+ return std::string(left, ' ') + s;
+}
+
+std::string to_decimal(int value) {
+ std::ostringstream oss;
+ oss << std::dec << value;
+ return oss.str();
+}
+
+std::string to_octal(int value) {
+ std::ostringstream oss;
+ oss << std::oct << value;
+ return oss.str();
+}
+
+std::string to_hex(int value) {
+ std::ostringstream oss;
+ oss << std::hex << value;
+ return oss.str();
+}
\ No newline at end of file
diff --git a/tests/code/filesystem_speed_test/code/log.h b/tests/code/filesystem_speed_test/code/log.h
new file mode 100644
index 00000000..989e5c75
--- /dev/null
+++ b/tests/code/filesystem_speed_test/code/log.h
@@ -0,0 +1,61 @@
+#pragma once
+
+#ifndef LOG_H
+#define LOG_H
+
+#include
+#include
+
+#define STR(x) std::to_string(x)
+
+std::ostream& center(std::ostream& os, const std::string& s, int width);
+std::string center(const std::string& s, int width);
+std::ostream& right(std::ostream& os, const std::string& s, int width);
+std::string right(const std::string& s, int width);
+std::string to_decimal(int value);
+std::string to_octal(int value);
+std::string to_hex(int value);
+
+template
+void LogCustom(const char* fn, const char* msg, Args&&... args) {
+ std::cout << "[" << center(fn, 20) << "] " << msg;
+ ((std::cout << " " << args), ...);
+ std::cout << std::endl;
+}
+
+extern int error_counter;
+
+int GetErrorCounter(void);
+void ResetErrorCounter(void);
+
+#define Log(...) \
+ { \
+ LogCustom(__FUNCTION__, "[INFO]", ##__VA_ARGS__); \
+ }
+
+#define LogTest(...) \
+ { \
+ LogCustom(__FUNCTION__, "\033[34;1m[TEST_CASE]\033[0m", ##__VA_ARGS__); \
+ }
+
+#define LogError(...) \
+ { \
+ error_counter++; \
+ LogCustom(__FUNCTION__, "\033[31;1m[FAIL]\033[0m", ##__VA_ARGS__, "( " __FILE__ ":", __LINE__, ")"); \
+ }
+
+#define LogSuccess(...) \
+ { \
+ LogCustom(__FUNCTION__, "\033[32;1m[SUCC]\033[0m", ##__VA_ARGS__); \
+ }
+
+#define TEST_CASE(cond, success_str, fail_str, ...) \
+ { \
+ if (cond) { \
+ LogSuccess(success_str, ##__VA_ARGS__); \
+ } else { \
+ LogError(fail_str, ##__VA_ARGS__); \
+ } \
+ }
+
+#endif
\ No newline at end of file
diff --git a/tests/code/filesystem_speed_test/code/main.cpp b/tests/code/filesystem_speed_test/code/main.cpp
new file mode 100644
index 00000000..b8c48236
--- /dev/null
+++ b/tests/code/filesystem_speed_test/code/main.cpp
@@ -0,0 +1,25 @@
+#include "fs_test.h"
+#include "log.h"
+
+#include
+
+int main(int ac, char** av) {
+ // No buffering
+ setvbuf(stdout, NULL, _IONBF, 0);
+
+ // Log tests start
+ Log();
+ Log("<<<< TESTS START >>>>");
+ Log();
+
+ // Run file system tests
+ FS_Test::RunTests();
+
+ // Log tests end
+ Log();
+ Log("<<<< TESTS END >>>>");
+ Log();
+
+ sceSystemServiceLoadExec("EXIT", nullptr);
+ return 0;
+}
diff --git a/tests/code/filesystem_speed_test/sce_sys/icon0.png b/tests/code/filesystem_speed_test/sce_sys/icon0.png
new file mode 100644
index 00000000..20a851ef
Binary files /dev/null and b/tests/code/filesystem_speed_test/sce_sys/icon0.png differ
diff --git a/tests/code/filesystem_test/01.35.log b/tests/code/filesystem_test/01.35.log
new file mode 100644
index 00000000..a5863480
--- /dev/null
+++ b/tests/code/filesystem_test/01.35.log
@@ -0,0 +1,838 @@
+<118>[ main ] [INFO]
+<118>[ main ] [INFO] <<<< TESTS START >>>>
+<118>[ main ] [INFO]
+<118>[ Obliterate ] [INFO] << rm -rf [ /data/therapist ] >>
+<118>[ Obliterate ] [SUCC] >> rm -rf [ /data/therapist ] <<
+<118>[ RunTests ] [INFO]
+<118>[ RunTests ] [INFO] <<<< TEST SUITE STARTING >>>>
+<118>[ RunTests ] [INFO] Some test components may (and will) fail. This is expected.
+<118>[ RunTests ] [INFO] Validity of the test is determined by last message emitted by test case.
+<118>[ RunTests ] [INFO]
+<118>[ RunTests ] [INFO]
+<118>[ RunTests ] [INFO] <<<< DUMP DIRENTS >>>>
+<118>[ RunTests ] [INFO]
+<118>[ dumpDirRecursive ] [INFO] Listing dirents of [ /app0 ]
+<118>[ dumpDirRecursive ] [INFO] [ DIR ][ 2 ][ 1 ][ 24 ] |->.
+<118>[ dumpDirRecursive ] [INFO] [ DIR ][ 2 ][ 2 ][ 24 ] |->..
+<118>[ dumpDirRecursive ] [INFO] [ DIR ][ 3 ][ 6 ][ 24 ] |->assets
+<118>[ dumpDirRecursive ] [INFO] [ DIR ][ 3 ][ 1 ][ 24 ] |--|->.
+<118>[ dumpDirRecursive ] [INFO] [ DIR ][ 2 ][ 2 ][ 24 ] |--|->..
+<118>[ dumpDirRecursive ] [INFO] [ DIR ][ 4 ][ 5 ][ 24 ] |--|->audio
+<118>[ dumpDirRecursive ] [INFO] [ DIR ][ 4 ][ 1 ][ 24 ] |--|--|->.
+<118>[ dumpDirRecursive ] [INFO] [ DIR ][ 3 ][ 2 ][ 24 ] |--|--|->..
+<118>[ dumpDirRecursive ] [INFO] [ DIR ][ 5 ][ 5 ][ 24 ] |--|->fonts
+<118>[ dumpDirRecursive ] [INFO] [ DIR ][ 5 ][ 1 ][ 24 ] |--|--|->.
+<118>[ dumpDirRecursive ] [INFO] [ DIR ][ 3 ][ 2 ][ 24 ] |--|--|->..
+<118>[ dumpDirRecursive ] [INFO] [ DIR ][ 6 ][ 6 ][ 24 ] |--|->images
+<118>[ dumpDirRecursive ] [INFO] [ DIR ][ 6 ][ 1 ][ 24 ] |--|--|->.
+<118>[ dumpDirRecursive ] [INFO] [ DIR ][ 3 ][ 2 ][ 24 ] |--|--|->..
+<118>[ dumpDirRecursive ] [INFO] [ DIR ][ 7 ][ 4 ][ 24 ] |--|->misc
+<118>[ dumpDirRecursive ] [INFO] [ DIR ][ 7 ][ 1 ][ 24 ] |--|--|->.
+<118>[ dumpDirRecursive ] [INFO] [ DIR ][ 3 ][ 2 ][ 24 ] |--|--|->..
+<118>[ dumpDirRecursive ] [INFO] [ FIL ][ 12 ][ 20 ][ 40 ] |--|--|->cAsEinSEnsITiVE.HwDp
+<118>[ dumpDirRecursive ] [INFO] [ FIL ][ 13 ][ 8 ][ 32 ] |--|--|->file.txt
+<118>[ dumpDirRecursive ] [INFO] [ FIL ][ 14 ][ 14 ][ 32 ] |--|--|->file_empty.txt
+<118>[ dumpDirRecursive ] [INFO] [ DIR ][ 8 ][ 6 ][ 24 ] |--|->videos
+<118>[ dumpDirRecursive ] [INFO] [ DIR ][ 8 ][ 1 ][ 24 ] |--|--|->.
+<118>[ dumpDirRecursive ] [INFO] [ DIR ][ 3 ][ 2 ][ 24 ] |--|--|->..
+<118>[ dumpDirRecursive ] [INFO] [ DIR ][ 9 ][ 10 ][ 32 ] |->sce_module
+<118>[ dumpDirRecursive ] [INFO] [ DIR ][ 9 ][ 1 ][ 24 ] |--|->.
+<118>[ dumpDirRecursive ] [INFO] [ DIR ][ 2 ][ 2 ][ 24 ] |--|->..
+<118>[ dumpDirRecursive ] [INFO] [ FIL ][ 16 ][ 15 ][ 32 ] |--|->libSceFios2.prx
+<118>[ dumpDirRecursive ] [INFO] [ FIL ][ 17 ][ 8 ][ 32 ] |--|->libc.prx
+<118>[ dumpDirRecursive ] [INFO] [ DIR ][ 10 ][ 7 ][ 24 ] |->sce_sys
+<118>[ dumpDirRecursive ] [INFO] [ DIR ][ 10 ][ 1 ][ 24 ] |--|->.
+<118>[ dumpDirRecursive ] [INFO] [ DIR ][ 2 ][ 2 ][ 24 ] |--|->..
+<118>[ dumpDirRecursive ] [INFO] [ DIR ][ 11 ][ 5 ][ 24 ] |--|->about
+<118>[ dumpDirRecursive ] [INFO] [ DIR ][ 11 ][ 1 ][ 24 ] |--|--|->.
+<118>[ dumpDirRecursive ] [INFO] [ DIR ][ 10 ][ 2 ][ 24 ] |--|--|->..
+<118>[ dumpDirRecursive ] [INFO] [ FIL ][ 18 ][ 10 ][ 32 ] |--|--|->right.sprx
+<118>[ dumpDirRecursive ] [INFO] [ FIL ][ 19 ][ 8 ][ 32 ] |--|->keystone
+<118>[ dumpDirRecursive ] [INFO] [ FIL ][ 15 ][ 9 ][ 32 ] |->eboot.bin
+<118>[ dumpDirRecursive ] [SUCC] Listing dirents of [ /app0 ]
+<118>[ RunTests ] [INFO]
+<118>[ RunTests ] [INFO] <<<< RELATIVE FILENO >>>>
+<118>[ RunTests ] [INFO]
+<118>[ TestRelatives ] [TEST_CASE] Testing relative fileno perception of [ / ]
+<118>[ TestRelatives ] [INFO] / sees itself with fileno= 781
+<118>[ TestRelatives ] [INFO] / sees its parent with fileno= 3
+<118>[ TestRelatives ] [INFO] / is seen with fileno= -2
+<118>[ TestRelatives ] [INFO] It's not a mountpoint
+<118>[ RunTests ] [SUCC] Test complete. Expected values: ~700, 3, -2
+<118>[ TestRelatives ] [TEST_CASE] Testing relative fileno perception of [ /app0 ]
+<118>[ TestRelatives ] [INFO] /app0 sees itself with fileno= 2
+<118>[ TestRelatives ] [INFO] /app0 sees its parent with fileno= 2
+<118>[ TestRelatives ] [INFO] /app0 is seen with fileno= 784
+<118>[ TestRelatives ] [SUCC] It's a mountpoint
+<118>[ RunTests ] [SUCC] Test complete
+<118>[ TestRelatives ] [TEST_CASE] Testing relative fileno perception of [ /app0/sce_sys ]
+<118>[ TestRelatives ] [INFO] /app0/sce_sys sees itself with fileno= 10
+<118>[ TestRelatives ] [INFO] /app0/sce_sys sees its parent with fileno= 2
+<118>[ TestRelatives ] [INFO] /app0/sce_sys is seen with fileno= 10
+<118>[ TestRelatives ] [INFO] It's not a mountpoint
+<118>[ RunTests ] [SUCC] Test complete
+<118>[ TestRelatives ] [TEST_CASE] Testing relative fileno perception of [ /av_contents ]
+<118>[ TestRelatives ] [INFO] /av_contents sees itself with fileno= 808
+<118>[ TestRelatives ] [INFO] /av_contents sees its parent with fileno= 781
+<118>[ TestRelatives ] [INFO] /av_contents is seen with fileno= 808
+<118>[ TestRelatives ] [INFO] It's not a mountpoint
+<118>[ RunTests ] [SUCC] Test complete
+<118>[ TestRelatives ] [TEST_CASE] Testing relative fileno perception of [ /data ]
+<118>[ TestRelatives ] [INFO] /data sees itself with fileno= 15202560
+<118>[ TestRelatives ] [INFO] /data sees its parent with fileno= 2
+<118>[ TestRelatives ] [INFO] /data is seen with fileno= 790
+<118>[ TestRelatives ] [SUCC] It's a mountpoint
+<118>[ RunTests ] [SUCC] Test complete
+<118>[ TestRelatives ] [TEST_CASE] Testing relative fileno perception of [ /dev ]
+<118>[ TestRelatives ] [FAIL] Cannot get [ . ] from /dev ( /home/user/github/integration_tests/tests/code/filesystem_test/code/fs_test.cpp: 1107 )
+<118>[ TestRelatives ] [FAIL] Cannot get [ .. ] from /dev ( /home/user/github/integration_tests/tests/code/filesystem_test/code/fs_test.cpp: 1115 )
+<118>[ TestRelatives ] [INFO] /dev sees itself with fileno= -2
+<118>[ TestRelatives ] [INFO] /dev sees its parent with fileno= -2
+<118>[ TestRelatives ] [INFO] /dev is seen with fileno= 788
+<118>[ TestRelatives ] [INFO] It's not a mountpoint
+<118>[ RunTests ] [SUCC] Test complete. Expected values: -2, -2, ~800
+<118>[ TestRelatives ] [TEST_CASE] Testing relative fileno perception of [ /host ]
+<118>[ TestRelatives ] [INFO] /host sees itself with fileno= 9
+<118>[ TestRelatives ] [INFO] /host sees its parent with fileno= 1
+<118>[ TestRelatives ] [INFO] /host is seen with fileno= 791
+<118>[ TestRelatives ] [SUCC] It's a mountpoint
+<118>[ RunTests ] [SUCC] /host is a superblock partition. Expected values: 9, 1, ~700
+<118>[ TestRelatives ] [TEST_CASE] Testing relative fileno perception of [ /hostapp ]
+<118>[ TestRelatives ] [INFO] /hostapp sees itself with fileno= 10
+<118>[ TestRelatives ] [INFO] /hostapp sees its parent with fileno= 1
+<118>[ TestRelatives ] [INFO] /hostapp is seen with fileno= 792
+<118>[ TestRelatives ] [SUCC] It's a mountpoint
+<118>[ RunTests ] [SUCC] /hostapp is a superblock partition. Expected values: 10, 1, ~700
+<118>[ TestRelatives ] [TEST_CASE] Testing relative fileno perception of [ /system_tmp ]
+<118>[ TestRelatives ] [INFO] /system_tmp sees itself with fileno= 2
+<118>[ TestRelatives ] [INFO] /system_tmp sees its parent with fileno= 2
+<118>[ TestRelatives ] [INFO] /system_tmp is seen with fileno= 789
+<118>[ TestRelatives ] [SUCC] It's a mountpoint
+<118>[ RunTests ] [SUCC] Test complete
+<118>[ TestRelatives ] [TEST_CASE] Testing relative fileno perception of [ /this_should_fail ]
+<118>[ GetDir ] [FAIL] [Normal] Cannot open [ . ] ( /home/user/github/integration_tests/tests/code/filesystem_test/code/fs_test_tools.cpp: 474 )
+<118>[ GetDir ] [FAIL] [Normal] Cannot open [ .. ] ( /home/user/github/integration_tests/tests/code/filesystem_test/code/fs_test_tools.cpp: 474 )
+<118>[ TestRelatives ] [FAIL] Cannot get [ this_should_fail ] from /this_should_fail ( /home/user/github/integration_tests/tests/code/filesystem_test/code/fs_test.cpp: 1124 )
+<118>[ TestRelatives ] [INFO] /this_should_fail sees itself with fileno= 0
+<118>[ TestRelatives ] [INFO] /this_should_fail sees its parent with fileno= 0
+<118>[ TestRelatives ] [INFO] /this_should_fail is seen with fileno= -2
+<118>[ TestRelatives ] [INFO] It's not a mountpoint
+<118>[ RunTests ] [SUCC] Test complete
+<118>[ RunTests ] [INFO]
+<118>[ RunTests ] [INFO] <<<< NORMAL AND PFS DIRENT >>>>
+<118>[ RunTests ] [INFO] Normal dirents are on LHS, PFS is on RHS.
+<118>[ RunTests ] [INFO] The last element of the path is the accessed dirent,
+<118>[ RunTests ] [INFO] so it can refer to a file, directory or relative entry [ . ], [ .. ]
+<118>[ RunTests ] [INFO]
+<118>[ CompareNormalVsPFS ] [TEST_CASE] Compare Normal and PFS dirent for /.
+<118>[ CompareNormalVsPFS ] [FAIL] /. fileno 781 != 0 ( /home/user/github/integration_tests/tests/code/filesystem_test/code/fs_test.cpp: 1173 )
+<118>[ CompareNormalVsPFS ] [FAIL] /. namlen 1 != 0 ( /home/user/github/integration_tests/tests/code/filesystem_test/code/fs_test.cpp: 1181 )
+<118>[ CompareNormalVsPFS ] [FAIL] /. reclen 12 != 0 ( /home/user/github/integration_tests/tests/code/filesystem_test/code/fs_test.cpp: 1193 )
+<118>[ CompareNormalVsPFS ] [FAIL] Names are not equal (memcmp) ( /home/user/github/integration_tests/tests/code/filesystem_test/code/fs_test.cpp: 1197 )
+<118>[ CompareNormalVsPFS ] [INFO] Normal: .
+<118>[ CompareNormalVsPFS ] [INFO] PFS:
+<118>[ RunTests ] [SUCC] Test complete [PFS should fail]
+<118>[ CompareNormalVsPFS ] [TEST_CASE] Compare Normal and PFS dirent for /app0
+<118>[ CompareNormalVsPFS ] [FAIL] /app0 fileno 784 != 0 ( /home/user/github/integration_tests/tests/code/filesystem_test/code/fs_test.cpp: 1173 )
+<118>[ CompareNormalVsPFS ] [FAIL] /app0 namlen 4 != 0 ( /home/user/github/integration_tests/tests/code/filesystem_test/code/fs_test.cpp: 1181 )
+<118>[ CompareNormalVsPFS ] [FAIL] /app0 reclen 16 != 0 ( /home/user/github/integration_tests/tests/code/filesystem_test/code/fs_test.cpp: 1193 )
+<118>[ CompareNormalVsPFS ] [FAIL] Names are not equal (memcmp) ( /home/user/github/integration_tests/tests/code/filesystem_test/code/fs_test.cpp: 1197 )
+<118>[ CompareNormalVsPFS ] [INFO] Normal: app0
+<118>[ CompareNormalVsPFS ] [INFO] PFS:
+<118>[ RunTests ] [SUCC] Test complete [PFS should fail]
+<118>[ CompareNormalVsPFS ] [TEST_CASE] Compare Normal and PFS dirent for /data
+<118>[ CompareNormalVsPFS ] [FAIL] /data fileno 790 != 0 ( /home/user/github/integration_tests/tests/code/filesystem_test/code/fs_test.cpp: 1173 )
+<118>[ CompareNormalVsPFS ] [FAIL] /data namlen 4 != 0 ( /home/user/github/integration_tests/tests/code/filesystem_test/code/fs_test.cpp: 1181 )
+<118>[ CompareNormalVsPFS ] [FAIL] /data reclen 16 != 0 ( /home/user/github/integration_tests/tests/code/filesystem_test/code/fs_test.cpp: 1193 )
+<118>[ CompareNormalVsPFS ] [FAIL] Names are not equal (memcmp) ( /home/user/github/integration_tests/tests/code/filesystem_test/code/fs_test.cpp: 1197 )
+<118>[ CompareNormalVsPFS ] [INFO] Normal: data
+<118>[ CompareNormalVsPFS ] [INFO] PFS:
+<118>[ RunTests ] [SUCC] Test complete [PFS should fail]
+<118>[ CompareNormalVsPFS ] [TEST_CASE] Compare Normal and PFS dirent for /app0/.
+<118>[ CompareNormalVsPFS ] [SUCC] /app0/. fileno 2 == 2
+<118>[ CompareNormalVsPFS ] [SUCC] /app0/. namlen 1 == 1
+<118>[ CompareNormalVsPFS ] [SUCC] /app0/. reclen 24 == 24
+<118>[ CompareNormalVsPFS ] [SUCC] Names are equal (memcmp)
+<118>[ RunTests ] [SUCC] Test complete
+<118>[ CompareNormalVsPFS ] [TEST_CASE] Compare Normal and PFS dirent for /app0/..
+<118>[ CompareNormalVsPFS ] [SUCC] /app0/.. fileno 2 == 2
+<118>[ CompareNormalVsPFS ] [SUCC] /app0/.. namlen 2 == 2
+<118>[ CompareNormalVsPFS ] [SUCC] /app0/.. reclen 24 == 24
+<118>[ CompareNormalVsPFS ] [SUCC] Names are equal (memcmp)
+<118>[ RunTests ] [SUCC] Test complete
+<118>[ CompareNormalVsPFS ] [TEST_CASE] Compare Normal and PFS dirent for /app0/sce_sys
+<118>[ CompareNormalVsPFS ] [SUCC] /app0/sce_sys fileno 10 == 10
+<118>[ CompareNormalVsPFS ] [SUCC] /app0/sce_sys namlen 7 == 7
+<118>[ CompareNormalVsPFS ] [SUCC] /app0/sce_sys reclen 24 == 24
+<118>[ CompareNormalVsPFS ] [SUCC] Names are equal (memcmp)
+<118>[ RunTests ] [SUCC] Test complete
+<118>[ CompareNormalVsPFS ] [TEST_CASE] Compare Normal and PFS dirent for /app0/eboot.bin
+<118>[ CompareNormalVsPFS ] [SUCC] /app0/eboot.bin fileno 15 == 15
+<118>[ CompareNormalVsPFS ] [SUCC] /app0/eboot.bin namlen 9 == 9
+<118>[ CompareNormalVsPFS ] [SUCC] /app0/eboot.bin reclen 32 == 32
+<118>[ CompareNormalVsPFS ] [SUCC] Names are equal (memcmp)
+<118>[ RunTests ] [SUCC] Test complete
+<118>[ CompareNormalVsPFS ] [TEST_CASE] Compare Normal and PFS dirent for /data/therapist/.
+<118>[ CompareNormalVsPFS ] [FAIL] /data/therapist/. fileno 15581570 != 0 ( /home/user/github/integration_tests/tests/code/filesystem_test/code/fs_test.cpp: 1173 )
+<118>[ CompareNormalVsPFS ] [FAIL] /data/therapist/. namlen 1 != 0 ( /home/user/github/integration_tests/tests/code/filesystem_test/code/fs_test.cpp: 1181 )
+<118>[ CompareNormalVsPFS ] [FAIL] /data/therapist/. reclen 12 != 0 ( /home/user/github/integration_tests/tests/code/filesystem_test/code/fs_test.cpp: 1193 )
+<118>[ CompareNormalVsPFS ] [FAIL] Names are not equal (memcmp) ( /home/user/github/integration_tests/tests/code/filesystem_test/code/fs_test.cpp: 1197 )
+<118>[ CompareNormalVsPFS ] [INFO] Normal: .
+<118>[ CompareNormalVsPFS ] [INFO] PFS:
+<118>[ RunTests ] [SUCC] Test complete [PFS should fail]
+<118>[ CompareNormalVsPFS ] [TEST_CASE] Compare Normal and PFS dirent for /this_should_fail/.
+<118>[ GetDir ] [FAIL] [Normal] Cannot open [ . ] ( /home/user/github/integration_tests/tests/code/filesystem_test/code/fs_test_tools.cpp: 474 )
+<118>[ CompareNormalVsPFS ] [FAIL] Can't open /this_should_fail/. as normal ( /home/user/github/integration_tests/tests/code/filesystem_test/code/fs_test.cpp: 1155 )
+<118>[ GetDir ] [FAIL] [PFS] Cannot open [ . ] ( /home/user/github/integration_tests/tests/code/filesystem_test/code/fs_test_tools.cpp: 410 )
+<118>[ CompareNormalVsPFS ] [FAIL] Can't open /this_should_fail/. as PFS ( /home/user/github/integration_tests/tests/code/filesystem_test/code/fs_test.cpp: 1158 )
+<118>[ RunTests ] [SUCC] Test complete [All should fail]
+<118>[ RunTests ] [INFO]
+<118>[ RunTests ] [INFO] <<<< Example directory listings >>>>
+<118>[ RunTests ] [INFO] This is made to mimic `ls -la`.
+<118>[ RunTests ] [INFO] UID, GID are always 0
+<118>[ RunTests ] [INFO]
+<118>[ RunTests ] [INFO]
+<118>[ RunTests ] [INFO] <<<< DIRENTS >>>>
+<118>[ RunTests ] [INFO]
+<118>[ Obliterate ] [INFO] << rm -rf [ /data/therapist/tmp_dirent ] >>
+<118>[ Obliterate ] [SUCC] >> rm -rf [ /data/therapist/tmp_dirent ] <<
+<118>[ RunTests ] [SUCC] Prepared for dirents
+<118>[ TestDirEnts ] [TEST_CASE] Testing dirents
+<118>[ TestDirEnts ] [SUCC] Creating [ /data/therapist/tmp_dirent ] failed (EEXIST) ( errno = 17 )
+<118>[ TestDirEnts ] [SUCC] open() succeeded on [ /data/therapist/tmp_dirent ] ( errno = 0 )
+<118>[ TestDirEnts ] [SUCC] Closed [ /data/therapist/tmp_dirent ] ( errno = 0 )
+<118>[ TestDirEnts ] [SUCC] Dummy files (1-4) created ( errno = 0 )
+<118>[ TestDirEnts ] [SUCC] open() succeeded on [ /data/therapist/tmp_dirent ] ( errno = 0 )
+<118>[ TestDirEnts ] [SUCC] Seek to start (dirents, pre) ( errno = 0 )
+<118>[ TestDirEnts ] [SUCC] Direntries read correctly ( read bytes: 512 ) ( errno = 0 )
+<118>[ TestDirEnts ] [SUCC] Seek to start (dump, pre) ( errno = 0 )
+<118>[ dumpDir ] [INFO] [ DIR ][ 15581573 ][ 1 ][ 12 ] |->.
+<118>[ dumpDir ] [INFO] [ DIR ][ 15581570 ][ 2 ][ 12 ] |->..
+<118>[ dumpDir ] [INFO] [ FIL ][ 15581797 ][ 12 ][ 24 ] |->dummy_file_1
+<118>[ dumpDir ] [INFO] [ FIL ][ 15581801 ][ 12 ][ 24 ] |->dummy_file_2
+<118>[ dumpDir ] [INFO] [ FIL ][ 15581803 ][ 12 ][ 24 ] |->dummy_file_3
+<118>[ dumpDir ] [INFO] [ FIL ][ 15581906 ][ 12 ][ 416 ] |->dummy_file_4
+<118>[ TestDirEnts ] [SUCC] Read correct amount of data (dump, pre) ( last_reclen = 416 should be = 416 ) ( errno = 0 )
+<118>[ TestDirEnts ] [INFO] You should see 4 dummy files here
+<118>[ TestDirEnts ] [SUCC] Dummy files (5-8) created ( errno = 0 )
+<118>[ TestDirEnts ] [SUCC] Seek to start (dirents, post) ( errno = 0 )
+<118>[ TestDirEnts ] [SUCC] Direntries read correctly ( read bytes: 512 ) ( errno = 0 )
+<118>[ TestDirEnts ] [SUCC] Seek to start (dump, post) ( errno = 0 )
+<118>[ dumpDir ] [INFO] [ DIR ][ 15581573 ][ 1 ][ 12 ] |->.
+<118>[ dumpDir ] [INFO] [ DIR ][ 15581570 ][ 2 ][ 12 ] |->..
+<118>[ dumpDir ] [INFO] [ FIL ][ 15581797 ][ 12 ][ 24 ] |->dummy_file_1
+<118>[ dumpDir ] [INFO] [ FIL ][ 15581801 ][ 12 ][ 24 ] |->dummy_file_2
+<118>[ dumpDir ] [INFO] [ FIL ][ 15581803 ][ 12 ][ 24 ] |->dummy_file_3
+<118>[ dumpDir ] [INFO] [ FIL ][ 15581906 ][ 12 ][ 24 ] |->dummy_file_4
+<118>[ dumpDir ] [INFO] [ FIL ][ 15581907 ][ 12 ][ 24 ] |->dummy_file_5
+<118>[ dumpDir ] [INFO] [ FIL ][ 15581909 ][ 12 ][ 24 ] |->dummy_file_6
+<118>[ dumpDir ] [INFO] [ FIL ][ 15581910 ][ 12 ][ 24 ] |->dummy_file_7
+<118>[ dumpDir ] [INFO] [ FIL ][ 15581911 ][ 12 ][ 320 ] |->dummy_file_8
+<118>[ TestDirEnts ] [SUCC] Read correct amount of data (dump, post) ( last_reclen = 320 should be = 320 ) ( errno = 0 )
+<118>[ TestDirEnts ] [INFO] You should see 8 dummy files here
+<118>[ TestDirEnts ] [SUCC] Closed [ /data/therapist/tmp_dirent ] ( errno = 0 )
+<118>[ RunTests ] [SUCC] Test complete
+<118>[ RunTests ] [INFO]
+<118>[ RunTests ] [INFO] <<<< STAT >>>>
+<118>[ RunTests ] [INFO] LHS - emulated, RHS - OG
+<118>[ RunTests ] [INFO]
+<118>[ TestStat ] [TEST_CASE] Testing stat on [ "/" ]
+<118>[ TestStat ] [SUCC] Stat successful [ "/" ] ( errno = 0 )
+<118>[ StatCmp ] [INFO] ---- OrbisKernelStat comparsion ----
+<118>[ StatCmp ] [INFO] st_mode LHS = 040775 | RHS = 040777
+<118>[ StatCmp ] [INFO] st_nlink LHS = 0 | RHS = 0
+<118>[ StatCmp ] [INFO] st_uid LHS = 0 | RHS = 0
+<118>[ StatCmp ] [INFO] st_gid LHS = 0 | RHS = 0
+<118>[ StatCmp ] [INFO] st_size LHS = 360 | RHS = 320
+<118>[ StatCmp ] [INFO] st_blocks LHS = 32 | RHS = 32
+<118>[ StatCmp ] [INFO] st_blksize LHS = 16384 | RHS = 16384
+<118>[ StatCmp ] [INFO] st_flags LHS = 0 | RHS = 0
+<118>[ RunTests ] [FAIL] Stat comparsion failed ( /home/user/github/integration_tests/tests/code/filesystem_test/code/fs_test.cpp: 415 )
+<118>[ TestStat ] [TEST_CASE] Testing stat on [ "/app0" ]
+<118>[ TestStat ] [SUCC] Stat successful [ "/app0" ] ( errno = 0 )
+<118>[ StatCmp ] [INFO] ---- OrbisKernelStat comparsion ----
+<118>[ StatCmp ] [INFO] st_mode LHS = 040555 | RHS = 040555
+<118>[ StatCmp ] [INFO] st_nlink LHS = 0 | RHS = 0
+<118>[ StatCmp ] [INFO] st_uid LHS = 0 | RHS = 0
+<118>[ StatCmp ] [INFO] st_gid LHS = 0 | RHS = 0
+<118>[ StatCmp ] [INFO] st_size LHS = 65536 | RHS = 65536
+<118>[ StatCmp ] [INFO] st_blocks LHS = 128 | RHS = 128
+<118>[ StatCmp ] [INFO] st_blksize LHS = 65536 | RHS = 65536
+<118>[ StatCmp ] [INFO] st_flags LHS = 0 | RHS = 0
+<118>[ RunTests ] [SUCC] Test complete
+<118>[ TestStat ] [TEST_CASE] Testing stat on [ "/app0/eboot.bin" ]
+<118>[ TestStat ] [SUCC] Stat successful [ "/app0/eboot.bin" ] ( errno = 0 )
+<118>[ StatCmp ] [INFO] ---- OrbisKernelStat comparsion ----
+<118>[ StatCmp ] [INFO] st_mode LHS = 0100555 | RHS = 0100555
+<118>[ StatCmp ] [INFO] st_nlink LHS = 0 | RHS = 0
+<118>[ StatCmp ] [INFO] st_uid LHS = 0 | RHS = 0
+<118>[ StatCmp ] [INFO] st_gid LHS = 0 | RHS = 0
+<118>[ StatCmp ] [INFO] st_size LHS = 1921088 | RHS = 1645264
+<118>[ StatCmp ] [INFO] st_blocks LHS = 3840 | RHS = 3328
+<118>[ StatCmp ] [INFO] st_blksize LHS = 65536 | RHS = 65536
+<118>[ StatCmp ] [INFO] st_flags LHS = 0 | RHS = 0
+<118>[ RunTests ] [FAIL] Stat comparsion failed ( /home/user/github/integration_tests/tests/code/filesystem_test/code/fs_test.cpp: 417 )
+<118>[ TestStat ] [TEST_CASE] Testing stat on [ "/app0/assets/misc/file.txt" ]
+<118>[ TestStat ] [SUCC] Stat successful [ "/app0/assets/misc/file.txt" ] ( errno = 0 )
+<118>[ StatCmp ] [INFO] ---- OrbisKernelStat comparsion ----
+<118>[ StatCmp ] [INFO] st_mode LHS = 0100555 | RHS = 0100555
+<118>[ StatCmp ] [INFO] st_nlink LHS = 0 | RHS = 0
+<118>[ StatCmp ] [INFO] st_uid LHS = 0 | RHS = 0
+<118>[ StatCmp ] [INFO] st_gid LHS = 0 | RHS = 0
+<118>[ StatCmp ] [INFO] st_size LHS = 45 | RHS = 45
+<118>[ StatCmp ] [INFO] st_blocks LHS = 128 | RHS = 128
+<118>[ StatCmp ] [INFO] st_blksize LHS = 65536 | RHS = 65536
+<118>[ StatCmp ] [INFO] st_flags LHS = 0 | RHS = 0
+<118>[ RunTests ] [SUCC] Test complete
+<118>[ TestStat ] [TEST_CASE] Testing stat on [ "/data/therapist" ]
+<118>[ TestStat ] [SUCC] Stat successful [ "/data/therapist" ] ( errno = 0 )
+<118>[ StatCmp ] [INFO] ---- OrbisKernelStat comparsion ----
+<118>[ StatCmp ] [INFO] st_mode LHS = 040777 | RHS = 040777
+<118>[ StatCmp ] [INFO] st_nlink LHS = 0 | RHS = 0
+<118>[ StatCmp ] [INFO] st_uid LHS = 0 | RHS = 0
+<118>[ StatCmp ] [INFO] st_gid LHS = 0 | RHS = 0
+<118>[ StatCmp ] [INFO] st_size LHS = 512 | RHS = 512
+<118>[ StatCmp ] [INFO] st_blocks LHS = 8 | RHS = 8
+<118>[ StatCmp ] [INFO] st_blksize LHS = 32768 | RHS = 32768
+<118>[ StatCmp ] [INFO] st_flags LHS = 0 | RHS = 0
+<118>[ RunTests ] [SUCC] Test complete
+<118>[ TestStat ] [TEST_CASE] Testing stat on [ "/dev" ]
+<118>[ TestStat ] [SUCC] Stat successful [ "/dev" ] ( errno = 0 )
+<118>[ StatCmp ] [INFO] ---- OrbisKernelStat comparsion ----
+<118>[ StatCmp ] [INFO] st_mode LHS = 040555 | RHS = 040555
+<118>[ StatCmp ] [INFO] st_nlink LHS = 0 | RHS = 0
+<118>[ StatCmp ] [INFO] st_uid LHS = 0 | RHS = 0
+<118>[ StatCmp ] [INFO] st_gid LHS = 0 | RHS = 0
+<118>[ StatCmp ] [INFO] st_size LHS = 512 | RHS = 512
+<118>[ StatCmp ] [INFO] st_blocks LHS = 1 | RHS = 1
+<118>[ StatCmp ] [INFO] st_blksize LHS = 16384 | RHS = 16384
+<118>[ StatCmp ] [INFO] st_flags LHS = 0 | RHS = 0
+<118>[ RunTests ] [SUCC] Test complete
+<118>[ TestStat ] [TEST_CASE] Testing stat on [ "/dev/deci_stderr" ]
+<118>[ TestStat ] [SUCC] Stat successful [ "/dev/deci_stderr" ] ( errno = 0 )
+<118>[ StatCmp ] [INFO] ---- OrbisKernelStat comparsion ----
+<118>[ StatCmp ] [INFO] st_mode LHS = 020666 | RHS = 020666
+<118>[ StatCmp ] [INFO] st_nlink LHS = 0 | RHS = 0
+<118>[ StatCmp ] [INFO] st_uid LHS = 0 | RHS = 0
+<118>[ StatCmp ] [INFO] st_gid LHS = 0 | RHS = 0
+<118>[ StatCmp ] [INFO] st_size LHS = 0 | RHS = 0
+<118>[ StatCmp ] [INFO] st_blocks LHS = 0 | RHS = 0
+<118>[ StatCmp ] [INFO] st_blksize LHS = 16384 | RHS = 16384
+<118>[ StatCmp ] [INFO] st_flags LHS = 0 | RHS = 0
+<118>[ RunTests ] [SUCC] Test complete
+<118>[ TestLStat ] [TEST_CASE] Testing lstat on [ "/dev/deci_stderr" ]
+<118>[ RunTests ] [FAIL] Stat comparsion failed ( /home/user/github/integration_tests/tests/code/filesystem_test/code/fs_test.cpp: 422 )
+<118>[ TestStat ] [TEST_CASE] Testing stat on [ "/dev/deci_stdout" ]
+<118>[ TestStat ] [SUCC] Stat successful [ "/dev/deci_stdout" ] ( errno = 0 )
+<118>[ StatCmp ] [INFO] ---- OrbisKernelStat comparsion ----
+<118>[ StatCmp ] [INFO] st_mode LHS = 020666 | RHS = 020666
+<118>[ StatCmp ] [INFO] st_nlink LHS = 0 | RHS = 0
+<118>[ StatCmp ] [INFO] st_uid LHS = 0 | RHS = 0
+<118>[ StatCmp ] [INFO] st_gid LHS = 0 | RHS = 0
+<118>[ StatCmp ] [INFO] st_size LHS = 0 | RHS = 0
+<118>[ StatCmp ] [INFO] st_blocks LHS = 0 | RHS = 0
+<118>[ StatCmp ] [INFO] st_blksize LHS = 16384 | RHS = 16384
+<118>[ StatCmp ] [INFO] st_flags LHS = 0 | RHS = 0
+<118>[ RunTests ] [SUCC] Test complete
+<118>[ TestStat ] [TEST_CASE] Testing stat on [ "/dev/stdin" ]
+<118>[ TestStat ] [FAIL] Stat failed [ "/dev/stdin" ] ( errno = 2 ) ( /home/user/github/integration_tests/tests/code/filesystem_test/code/fs_test.cpp: 897 )
+<118>[ TestStat ] [INFO] No comparsiton target provided for [ "/dev/stdin" ]. Dumping your own :)
+<118>[ PrintStatInfo ] [INFO] stat info.st_dev = 0
+<118>[ PrintStatInfo ] [INFO] stat info.st_ino = 0
+<118>[ PrintStatInfo ] [INFO] stat info.st_mode = 00
+<118>[ PrintStatInfo ] [INFO] stat info.st_nlink = 0
+<118>[ PrintStatInfo ] [INFO] stat info.st_uid = 0
+<118>[ PrintStatInfo ] [INFO] stat info.st_gid = 0
+<118>[ PrintStatInfo ] [INFO] stat info.st_rdev = 0
+<118>[ PrintStatInfo ] [INFO] stat info.st_atim.tv_sec = 0
+<118>[ PrintStatInfo ] [INFO] stat info.st_atim.tv_nsec = 0
+<118>[ PrintStatInfo ] [INFO] stat info.st_mtim.tv_sec = 0
+<118>[ PrintStatInfo ] [INFO] stat info.st_mtim.tv_nsec = 0
+<118>[ PrintStatInfo ] [INFO] stat info.st_ctim.tv_sec = 0
+<118>[ PrintStatInfo ] [INFO] stat info.st_ctim.tv_nsec = 0
+<118>[ PrintStatInfo ] [INFO] stat info.st_size = 0
+<118>[ PrintStatInfo ] [INFO] stat info.st_blocks = 0
+<118>[ PrintStatInfo ] [INFO] stat info.st_blksize = 0
+<118>[ PrintStatInfo ] [INFO] stat info.st_flags = 0
+<118>[ PrintStatInfo ] [INFO] stat info.st_gen = 0
+<118>[ PrintStatInfo ] [INFO] stat info.st_lspare = 0
+<118>[ PrintStatInfo ] [INFO] stat info.st_birthtim.tv_sec = 0
+<118>[ PrintStatInfo ] [INFO] stat info.st_birthtim.tv_nsec = 0
+<118>[ RunTests ] [SUCC] Test complete [stat should fail]
+<118>[ TestStat ] [TEST_CASE] Testing stat on [ "/dev/stdout" ]
+<118>[ TestStat ] [FAIL] Stat failed [ "/dev/stdout" ] ( errno = 2 ) ( /home/user/github/integration_tests/tests/code/filesystem_test/code/fs_test.cpp: 897 )
+<118>[ TestStat ] [INFO] No comparsiton target provided for [ "/dev/stdout" ]. Dumping your own :)
+<118>[ PrintStatInfo ] [INFO] stat info.st_dev = 0
+<118>[ PrintStatInfo ] [INFO] stat info.st_ino = 0
+<118>[ PrintStatInfo ] [INFO] stat info.st_mode = 00
+<118>[ PrintStatInfo ] [INFO] stat info.st_nlink = 0
+<118>[ PrintStatInfo ] [INFO] stat info.st_uid = 0
+<118>[ PrintStatInfo ] [INFO] stat info.st_gid = 0
+<118>[ PrintStatInfo ] [INFO] stat info.st_rdev = 0
+<118>[ PrintStatInfo ] [INFO] stat info.st_atim.tv_sec = 0
+<118>[ PrintStatInfo ] [INFO] stat info.st_atim.tv_nsec = 0
+<118>[ PrintStatInfo ] [INFO] stat info.st_mtim.tv_sec = 0
+<118>[ PrintStatInfo ] [INFO] stat info.st_mtim.tv_nsec = 0
+<118>[ PrintStatInfo ] [INFO] stat info.st_ctim.tv_sec = 0
+<118>[ PrintStatInfo ] [INFO] stat info.st_ctim.tv_nsec = 0
+<118>[ PrintStatInfo ] [INFO] stat info.st_size = 0
+<118>[ PrintStatInfo ] [INFO] stat info.st_blocks = 0
+<118>[ PrintStatInfo ] [INFO] stat info.st_blksize = 0
+<118>[ PrintStatInfo ] [INFO] stat info.st_flags = 0
+<118>[ PrintStatInfo ] [INFO] stat info.st_gen = 0
+<118>[ PrintStatInfo ] [INFO] stat info.st_lspare = 0
+<118>[ PrintStatInfo ] [INFO] stat info.st_birthtim.tv_sec = 0
+<118>[ PrintStatInfo ] [INFO] stat info.st_birthtim.tv_nsec = 0
+<118>[ RunTests ] [SUCC] Test complete
+<118>[ TestLStat ] [TEST_CASE] Testing lstat on [ "/dev/stdout" ]
+<118>[ RunTests ] [SUCC] Test complete
+<118>[ TestStat ] [TEST_CASE] Testing stat on [ "/dev/random" ]
+<118>[ TestStat ] [SUCC] Stat successful [ "/dev/random" ] ( errno = 0 )
+<118>[ StatCmp ] [INFO] ---- OrbisKernelStat comparsion ----
+<118>[ StatCmp ] [INFO] st_mode LHS = 020666 | RHS = 020666
+<118>[ StatCmp ] [INFO] st_nlink LHS = 0 | RHS = 0
+<118>[ StatCmp ] [INFO] st_uid LHS = 0 | RHS = 0
+<118>[ StatCmp ] [INFO] st_gid LHS = 0 | RHS = 0
+<118>[ StatCmp ] [INFO] st_size LHS = 0 | RHS = 0
+<118>[ StatCmp ] [INFO] st_blocks LHS = 0 | RHS = 0
+<118>[ StatCmp ] [INFO] st_blksize LHS = 16384 | RHS = 16384
+<118>[ StatCmp ] [INFO] st_flags LHS = 0 | RHS = 0
+<118>[ RunTests ] [SUCC] Test complete
+<118>[ TestStat ] [TEST_CASE] Testing stat on [ "/dev/urandom" ]
+<118>[ TestStat ] [SUCC] Stat successful [ "/dev/urandom" ] ( errno = 0 )
+<118>[ StatCmp ] [INFO] ---- OrbisKernelStat comparsion ----
+<118>[ StatCmp ] [INFO] st_mode LHS = 020666 | RHS = 020666
+<118>[ StatCmp ] [INFO] st_nlink LHS = 0 | RHS = 0
+<118>[ StatCmp ] [INFO] st_uid LHS = 0 | RHS = 0
+<118>[ StatCmp ] [INFO] st_gid LHS = 0 | RHS = 0
+<118>[ StatCmp ] [INFO] st_size LHS = 0 | RHS = 0
+<118>[ StatCmp ] [INFO] st_blocks LHS = 0 | RHS = 0
+<118>[ StatCmp ] [INFO] st_blksize LHS = 16384 | RHS = 16384
+<118>[ StatCmp ] [INFO] st_flags LHS = 0 | RHS = 0
+<118>[ RunTests ] [SUCC] Test complete
+<118>[ TestStat ] [TEST_CASE] Testing stat on [ "/host" ]
+<118>[ TestStat ] [SUCC] Stat successful [ "/host" ] ( errno = 0 )
+<118>[ StatCmp ] [INFO] ---- OrbisKernelStat comparsion ----
+<118>[ StatCmp ] [INFO] st_mode LHS = 040777 | RHS = 040777
+<118>[ StatCmp ] [INFO] st_nlink LHS = 0 | RHS = 0
+<118>[ StatCmp ] [INFO] st_uid LHS = 0 | RHS = 0
+<118>[ StatCmp ] [INFO] st_gid LHS = 0 | RHS = 0
+<118>[ StatCmp ] [INFO] st_size LHS = 4096 | RHS = 4096
+<118>[ StatCmp ] [INFO] st_blocks LHS = 8 | RHS = 8
+<118>[ StatCmp ] [INFO] st_blksize LHS = 16384 | RHS = 16384
+<118>[ StatCmp ] [INFO] st_flags LHS = 0 | RHS = 0
+<118>[ RunTests ] [SUCC] Test complete
+<118>[ TestStat ] [TEST_CASE] Testing stat on [ "/hostapp" ]
+<118>[ TestStat ] [SUCC] Stat successful [ "/hostapp" ] ( errno = 0 )
+<118>[ StatCmp ] [INFO] ---- OrbisKernelStat comparsion ----
+<118>[ StatCmp ] [INFO] st_mode LHS = 040777 | RHS = 040777
+<118>[ StatCmp ] [INFO] st_nlink LHS = 0 | RHS = 0
+<118>[ StatCmp ] [INFO] st_uid LHS = 0 | RHS = 0
+<118>[ StatCmp ] [INFO] st_gid LHS = 0 | RHS = 0
+<118>[ StatCmp ] [INFO] st_size LHS = 4096 | RHS = 4096
+<118>[ StatCmp ] [INFO] st_blocks LHS = 8 | RHS = 8
+<118>[ StatCmp ] [INFO] st_blksize LHS = 16384 | RHS = 16384
+<118>[ StatCmp ] [INFO] st_flags LHS = 0 | RHS = 0
+<118>[ RunTests ] [SUCC] Test complete
+<118>[ TestStat ] [TEST_CASE] Testing stat on [ "/av_contents" ]
+<118>[ TestStat ] [SUCC] Stat successful [ "/av_contents" ] ( errno = 0 )
+<118>[ StatCmp ] [INFO] ---- OrbisKernelStat comparsion ----
+<118>[ StatCmp ] [INFO] st_mode LHS = 040775 | RHS = 040775
+<118>[ StatCmp ] [INFO] st_nlink LHS = 0 | RHS = 0
+<118>[ StatCmp ] [INFO] st_uid LHS = 0 | RHS = 0
+<118>[ StatCmp ] [INFO] st_gid LHS = 0 | RHS = 0
+<118>[ StatCmp ] [INFO] st_size LHS = 160 | RHS = 160
+<118>[ StatCmp ] [INFO] st_blocks LHS = 32 | RHS = 32
+<118>[ StatCmp ] [INFO] st_blksize LHS = 16384 | RHS = 16384
+<118>[ StatCmp ] [INFO] st_flags LHS = 0 | RHS = 0
+<118>[ RunTests ] [SUCC] Test complete
+<118>[ TestLStat ] [TEST_CASE] Testing lstat on [ "/av_contents" ]
+<118>[ RunTests ] [SUCC] Test complete
+<118>[ RunTests ] [INFO]
+<118>[ RunTests ] [INFO] <<<< CURSED FILE CREATION >>>>
+<118>[ RunTests ] [INFO]
+<118>[ Obliterate ] [INFO] << rm -rf [ /data/therapist/tmp_cursed ] >>
+<118>[ Obliterate ] [SUCC] >> rm -rf [ /data/therapist/tmp_cursed ] <<
+<118>[PrepareCursedFileop ] [TEST_CASE] Cursed file operations
+<118>[ RunTests ] [SUCC] Prepared for cursed fileop
+<118>[ TestFileTouch ] [TEST_CASE] Cursed file operations: [ /data/therapist/tmp_cursed/Aursed/AAursed/a_aa_file.txt ]
+<118>[ TestFileTouch ] [SUCC] touched ( errno = 0 )
+<118>[ TestFileTouch ] [SUCC] stat success ( errno = 0 )
+<118>[ RunTests ] [SUCC] Test complete
+<118>[ TestFileTouch ] [TEST_CASE] Cursed file operations: [ /data/therapist/tmp_cursed/Aursed/a_file.txt ]
+<118>[ TestFileTouch ] [SUCC] touched ( errno = 0 )
+<118>[ TestFileTouch ] [SUCC] stat success ( errno = 0 )
+<118>[ RunTests ] [SUCC] Test complete
+<118>[ TestFileTouch ] [TEST_CASE] Cursed file operations: [ /data/therapist/tmp_cursed/Aursed/././a_d_d_file.txt ]
+<118>[ TestFileTouch ] [SUCC] touched ( errno = 0 )
+<118>[ TestFileTouch ] [SUCC] stat success ( errno = 0 )
+<118>[ RunTests ] [SUCC] Test complete
+<118>[ TestFileTouch ] [TEST_CASE] Cursed file operations: [ /data/therapist/tmp_cursed/Bursed/../Aursed/AAursed/b_dd_a_aa_file.txt ]
+<118>[ TestFileTouch ] [SUCC] touched ( errno = 0 )
+<118>[ TestFileTouch ] [SUCC] stat success ( errno = 0 )
+<118>[ RunTests ] [SUCC] Test complete
+<118>[ TestFileTouch ] [TEST_CASE] Cursed file operations: [ /data/therapist/tmp_cursed/Aursed/AAursed/../../Cursed/../Bursed/aa_dd_dd_c_dd_b_file.txt ]
+<118>[ TestFileTouch ] [SUCC] touched ( errno = 0 )
+<118>[ TestFileTouch ] [SUCC] stat success ( errno = 0 )
+<118>[ RunTests ] [SUCC] Test complete
+<118>[ TestFileTouch ] [TEST_CASE] Cursed file operations: [ /data/therapist/tmp_cursed/Aursed/AAursed/../../Cursed/CCursed/../../Bursed/BBursed/a_aa_dd_dd_c_cc_dd_dd_b_bb_file.txt ]
+<118>[ TestFileTouch ] [SUCC] touched ( errno = 0 )
+<118>[ TestFileTouch ] [SUCC] stat success ( errno = 0 )
+<118>[ RunTests ] [SUCC] Test complete
+<118>[ RunTests ] [INFO] errno for tests below should equal 9 (EBADF) and 2 (ENOENT)
+<118>[ TestFileTouch ] [TEST_CASE] Cursed file operations: [ /data/therapist/tmp_cursed/../tmp_cursed/../../././data/therapist/../data/therapist/././tmp_cursed/Cursed/../../../data/therapist/tmp_cursed/Cursed/idfk.txt ]
+<118>[ TestFileTouch ] [FAIL] can'touch ( errno = 9 ) ( /home/user/github/integration_tests/tests/code/filesystem_test/code/fs_test.cpp: 867 )
+<118>[ TestFileTouch ] [FAIL] stat fail ( errno = 2 ) ( /home/user/github/integration_tests/tests/code/filesystem_test/code/fs_test.cpp: 870 )
+<118>[ RunTests ] [SUCC] Test complete
+<118>[ RunTests ] [INFO] errno for tests below should equal 9 (EBADF) and 22 (EINVAL)
+<118>[ TestFileTouch ] [TEST_CASE] Cursed file operations: [ ../../../data/therapist/tmp_cursed/escape_from_app0_file.txt ]
+<118>[ TestFileTouch ] [FAIL] can'touch ( errno = 9 ) ( /home/user/github/integration_tests/tests/code/filesystem_test/code/fs_test.cpp: 867 )
+<118>[ TestFileTouch ] [FAIL] stat fail ( errno = 22 ) ( /home/user/github/integration_tests/tests/code/filesystem_test/code/fs_test.cpp: 870 )
+<118>[ RunTests ] [SUCC] Test complete: Can't escape from curdir with relatives
+<118>[ TestFileTouch ] [TEST_CASE] Cursed file operations: [ app0_file.txt ]
+<118>[ TestFileTouch ] [FAIL] can'touch ( errno = 9 ) ( /home/user/github/integration_tests/tests/code/filesystem_test/code/fs_test.cpp: 867 )
+<118>[ TestFileTouch ] [FAIL] stat fail ( errno = 22 ) ( /home/user/github/integration_tests/tests/code/filesystem_test/code/fs_test.cpp: 870 )
+<118>[ RunTests ] [SUCC] Test complete: File not written to (RO?) curdir
+<118>[ RunTests ] [INFO]
+<118>[ RunTests ] [INFO] <<<< File ops tests >>>>
+<118>[ RunTests ] [INFO]
+<118>[ Obliterate ] [INFO] << rm -rf [ /data/therapist/tmp_rw2 ] >>
+<118>[ Obliterate ] [SUCC] >> rm -rf [ /data/therapist/tmp_rw2 ] <<
+<118>[ TestFileOps ] [TEST_CASE] Testing file operations on [ ]
+<118>[ TestFileOps ] [SUCC] Stat failed on nonexistent file ( errno = 22 )
+<118>[ TestFileOps ] [SUCC] Truncate to 0 failed on nonexistent file ( errno = 22 )
+<118>[ TestFileOps ] [SUCC] Truncate to 10 failed on nonexistent file ( errno = 22 )
+<118>[ TestFileOps ] [FAIL] Can't open file [ ] ( errno = 22 ) ( /home/user/github/integration_tests/tests/code/filesystem_test/code/fs_test.cpp: 636 )
+<118>[ RunTests ] [SUCC] Pass [open() should fail with errno = 22]
+<118>[ TestFileOps ] [TEST_CASE] Testing file operations on [ /app0/assets/misc/test.txt ]
+<118>[ TestFileOps ] [SUCC] Stat failed on nonexistent file ( errno = 2 )
+<118>[ TestFileOps ] [SUCC] Truncate to 0 failed on nonexistent file ( errno = 2 )
+<118>[ TestFileOps ] [SUCC] Truncate to 10 failed on nonexistent file ( errno = 2 )
+<118>[ TestFileOps ] [FAIL] Can't open file [ /app0/assets/misc/test.txt ] ( errno = 30 ) ( /home/user/github/integration_tests/tests/code/filesystem_test/code/fs_test.cpp: 636 )
+<118>[ RunTests ] [SUCC] Pass [open should fail with errno = 30]
+<118>[ TestFileOps ] [TEST_CASE] Testing file operations on [ /data/therapist/tmp_rw2/test.txt ]
+<118>[ TestFileOps ] [SUCC] Stat failed on nonexistent file ( errno = 2 )
+<118>[ TestFileOps ] [SUCC] Truncate to 0 failed on nonexistent file ( errno = 2 )
+<118>[ TestFileOps ] [SUCC] Truncate to 10 failed on nonexistent file ( errno = 2 )
+<118>[ TestFileOps ] [SUCC] File opened [ /data/therapist/tmp_rw2/test.txt ] ( errno = 0 )
+<118>[ TestFileOps ] [SUCC] File expanded ( errno = 0 )
+<118>[ TestFileOps ] [SUCC] File resized (current size: 10 should be: 10 ) ( errno = 0 )
+<118>[ TestFileOps ] [SUCC] ptr is valid (lseek is 0 should be 0 ) ( errno = 0 )
+<118>[ TestFileOps ] [SUCC] Write successful (Written: 38 ) should write 38 ( errno = 0 )
+<118>[ TestFileOps ] [SUCC] ptr is valid (lseek is 38 should be: 38 ) ( errno = 0 )
+<118>[ TestFileOps ] [SUCC] ok: origin+0 (lseek is 0 should be: 0 ) ( errno = 0 )
+<118>[ TestFileOps ] [SUCC] Read successful (Read: 38 should read: 38 ) ( errno = 0 )
+<118>[ TestFileOps ] [INFO] If you can read this, unused gibberish
+<118>[ TestFileOps ] [SUCC] ptr is valid (lseek is 38 should be: 38 ) ( errno = 0 )
+<118>[ TestFileOps ] [SUCC] File truncated ( errno = 0 )
+<118>[ TestFileOps ] [SUCC] File resized (current size: 20 should be: 20 ) ( errno = 0 )
+<118>[ TestFileOps ] [SUCC] file pointer not changed after resizing (lseek is 38 should be 38 ) ( errno = 0 )
+<118>[ TestFileOps ] [SUCC] ok: end+0 (lseek is 20 should be 20 ) ( errno = 0 )
+<118>[ TestFileOps ] [SUCC] 2-nd write successful (Written: 56 ) should write 56 ( errno = 0 )
+<118>[ TestFileOps ] [SUCC] ok: origin+0 (lseek is 0 should be: 0 ) ( errno = 0 )
+<118>[ TestFileOps ] [SUCC] Read successful (Read: 51 should read: 51 ) ( errno = 0 )
+<118>[ TestFileOps ] [INFO] If you can read this, remember to drink some water.
+<118>[ TestFileOps ] [SUCC] ok: end-24 (lseek is 52 should be: 52 ) ( errno = 0 )
+<118>[ TestFileOps ] [SUCC] Read successful (Read: 24 should read: 24 ) ( errno = 0 )
+<118>[ TestFileOps ] [INFO] This is saved for later.
+<118>[ TestFileOps ] [SUCC] ok: current+34 (lseek is 34 should be: 34 ) ( errno = 0 )
+<118>[ TestFileOps ] [SUCC] Read successful (Read: 5 should read: 5 ) ( errno = 0 )
+<118>[ TestFileOps ] [INFO] drink
+<118>[ TestFileOps ] [SUCC] ok: current+6 (lseek is 45 should be: 45 ) ( errno = 0 )
+<118>[ TestFileOps ] [SUCC] Read successful (Read: 5 should read: 5 ) ( errno = 0 )
+<118>[ TestFileOps ] [INFO] water
+<118>[ TestFileOps ] [SUCC] ok: current-28 (lseek is 22 should be: 22 ) ( errno = 0 )
+<118>[ TestFileOps ] [SUCC] Read successful (Read: 8 should read: 8 ) ( errno = 0 )
+<118>[ TestFileOps ] [INFO] remember
+<118>[ TestFileOps ] [SUCC] ok: origin+2137 (OOB) (lseek is 2137 should be: 2137 ) ( errno = 0 )
+<118>[ TestFileOps ] [SUCC] ok: origin-2137 (OOB) (errno should be 22 - EINVAL) ( errno = 22 )
+<118>[ TestFileOps ] [SUCC] ok: current+2137 (OOB) (lseek is 4274 should be: 4274 ) ( errno = 0 )
+<118>[ TestFileOps ] [SUCC] ok: current-1234 (OOB) (lseek is 3040 should be: 3040 ) ( errno = 0 )
+<118>[ TestFileOps ] [SUCC] ok: current-5000 (into -OOB) (errno should be 22 - EINVAL) ( errno = 22 )
+<118>[ TestFileOps ] [SUCC] ok: end+2137 (OOB) (lseek is 2213 should be: 2213 ) ( errno = 0 )
+<118>[ TestFileOps ] [SUCC] ok: end-2137 (OOB) (errno should be 22 - EINVAL) ( errno = 22 )
+<118>[ RunTests ] [SUCC] Pass
+<118>[ RunTests ] [INFO]
+<118>[ RunTests ] [INFO] <<<< File R/W tests >>>>
+<118>[ RunTests ] [INFO]
+<118>[ Obliterate ] [INFO] << rm -rf [ /data/therapist/tmp_rw3 ] >>
+<118>[ Obliterate ] [SUCC] >> rm -rf [ /data/therapist/tmp_rw3 ] <<
+<118>[ TestFileRW ] [TEST_CASE] Testing r/w on [ ]
+<118>[ TestFileRW ] [FAIL] Can't open [ ] ( errno = 22 ) ( /home/user/github/integration_tests/tests/code/filesystem_test/code/fs_test.cpp: 805 )
+<118>[ RunTests ] [SUCC] Test complete [empty path, should fail with errno = 22 (EINVAL)]
+<118>[ TestFileRW ] [TEST_CASE] Testing r/w on [ /data/therapist/tmp_rw3/rwtest.txt ]
+<118>[ TestFileRW ] [SUCC] Opened [ /data/therapist/tmp_rw3/rwtest.txt ] ( errno = 0 )
+<118>[ TestFileRW ] [SUCC] Write succeded ( 32 bytes written) ( errno = 0 )
+<118>[ TestFileRW ] [SUCC] Lseek ORIGIN+10 val = 10 should be 10 ( errno = 0 )
+<118>[ TestFileRW ] [SUCC] Lseek CURRENT+1 val = 11 should be 11 ( errno = 0 )
+<118>[ TestFileRW ] [SUCC] Lseek CURRENT-1 val = 10 should be 10 ( errno = 0 )
+<118>[ TestFileRW ] [SUCC] Lseek END val = 32 should be 32 ( errno = 0 )
+<118>[ TestFileRW ] [SUCC] Lseek END-1 val = 31 should be 31 ( errno = 0 )
+<118>[ TestFileRW ] [SUCC] Lseek END+1 val = 33 should be 33 ( errno = 0 )
+<118>[ TestFileRW ] [SUCC] Lseek ORIGIN+0 val = 0 should be 0 ( errno = 0 )
+<118>[ TestFileRW ] [SUCC] Read succeded ( 32 bytes read) ( errno = 0 )
+<118>[ TestFileRW ] [INFO] Buffers are equal? : yes
+<118>[ TestFileRW ] [INFO] Write preview: 97 98 99 100
+<118>[ TestFileRW ] [INFO] Read preview: 97 98 99 100
+<118>[ TestFileRW ] [INFO] Is reading buffer full of zeros? : no
+<118>[ RunTests ] [SUCC] Test complete [both buffers should hold the same values]
+<118>[ TestFileRW ] [TEST_CASE] Testing r/w on [ /data/therapist/tmp_rw3 ]
+<118>[ TestFileRW ] [FAIL] Can't open [ /data/therapist/tmp_rw3 ] ( errno = 21 ) ( /home/user/github/integration_tests/tests/code/filesystem_test/code/fs_test.cpp: 805 )
+<118>[ RunTests ] [SUCC] Test complete: [R/W on a directory should fail with errno = 21 (EISDIR)]
+<118>[ TestFileRW ] [TEST_CASE] Testing r/w on [ /app0/assets/misc/file_empty.txt ]
+<118>[ TestFileRW ] [FAIL] Can't open [ /app0/assets/misc/file_empty.txt ] ( errno = 30 ) ( /home/user/github/integration_tests/tests/code/filesystem_test/code/fs_test.cpp: 805 )
+<118>[ RunTests ] [SUCC] Test complete: [R/W on a file in RO directory should fail with errno = 30 (EROFS)]
+<118>[ TestFileRW ] [TEST_CASE] Testing r/w on [ /dev/stdin ]
+<118>[ TestFileRW ] [FAIL] Can't open [ /dev/stdin ] ( errno = 2 ) ( /home/user/github/integration_tests/tests/code/filesystem_test/code/fs_test.cpp: 805 )
+<118>[ RunTests ] [SUCC] Test complete [Should fail with errno = 2 (ENOENT)]
+<118>[ TestFileRW ] [TEST_CASE] Testing r/w on [ /dev/stdout ]
+<118>[ TestFileRW ] [FAIL] Can't open [ /dev/stdout ] ( errno = 2 ) ( /home/user/github/integration_tests/tests/code/filesystem_test/code/fs_test.cpp: 805 )
+<118>[ RunTests ] [SUCC] Test complete [Should fail with errno = 2 (ENOENT)]
+<118>[ TestFileRW ] [TEST_CASE] Testing r/w on [ /dev/null ]
+<118>[ TestFileRW ] [SUCC] Opened [ /dev/null ] ( errno = 0 )
+<118>[ TestFileRW ] [SUCC] Write succeded ( 32 bytes written) ( errno = 0 )
+<118>[ TestFileRW ] [SUCC] Lseek ORIGIN+10 val = 10 should be 10 ( errno = 0 )
+<118>[ TestFileRW ] [SUCC] Lseek CURRENT+1 val = 11 should be 11 ( errno = 0 )
+<118>[ TestFileRW ] [SUCC] Lseek CURRENT-1 val = 10 should be 10 ( errno = 0 )
+<118>[ TestFileRW ] [SUCC] Lseek END val = 0 should be 0 ( errno = 0 )
+<118>[ TestFileRW ] [SUCC] Lseek END-1 val = 0 should be 0 ( errno = 0 )
+<118>[ TestFileRW ] [SUCC] Lseek END+1 val = 1 should be 1 ( errno = 0 )
+<118>[ TestFileRW ] [SUCC] Lseek ORIGIN+0 val = 0 should be 0 ( errno = 0 )
+<118>[ TestFileRW ] [FAIL] Read failed ( 0 bytes read) ( errno = 0 ) ( /home/user/github/integration_tests/tests/code/filesystem_test/code/fs_test.cpp: 840 )
+<118>[ TestFileRW ] [INFO] Buffers are equal? : no
+<118>[ TestFileRW ] [INFO] Write preview: 97 98 99 100
+<118>[ TestFileRW ] [INFO] Is reading buffer full of zeros? : no
+<118>[ RunTests ] [SUCC] Test complete [Write should pass, read should return 0 bytes]
+<118>[ TestFileRW ] [TEST_CASE] Testing r/w on [ /dev/random ]
+<118>[ TestFileRW ] [SUCC] Opened [ /dev/random ] ( errno = 0 )
+<118>[ TestFileRW ] [SUCC] Write succeded ( 32 bytes written) ( errno = 0 )
+<118>[ TestFileRW ] [SUCC] Lseek ORIGIN+10 val = 10 should be 10 ( errno = 0 )
+<118>[ TestFileRW ] [SUCC] Lseek CURRENT+1 val = 11 should be 11 ( errno = 0 )
+<118>[ TestFileRW ] [SUCC] Lseek CURRENT-1 val = 10 should be 10 ( errno = 0 )
+<118>[ TestFileRW ] [SUCC] Lseek END val = 0 should be 0 ( errno = 0 )
+<118>[ TestFileRW ] [SUCC] Lseek END-1 val = 0 should be 0 ( errno = 0 )
+<118>[ TestFileRW ] [SUCC] Lseek END+1 val = 1 should be 1 ( errno = 0 )
+<118>[ TestFileRW ] [SUCC] Lseek ORIGIN+0 val = 0 should be 0 ( errno = 0 )
+<118>[ TestFileRW ] [SUCC] Read succeded ( 32 bytes read) ( errno = 0 )
+<118>[ TestFileRW ] [INFO] Buffers are equal? : no
+<118>[ TestFileRW ] [INFO] Write preview: 97 98 99 100
+<118>[ TestFileRW ] [INFO] Read preview: 112 152 152 26
+<118>[ TestFileRW ] [INFO] Is reading buffer full of zeros? : no
+<118>[ RunTests ] [SUCC] Test complete [All should pass, random reads]
+<118>[ TestFileRW ] [TEST_CASE] Testing r/w on [ /dev/urandom ]
+<118>[ TestFileRW ] [SUCC] Opened [ /dev/urandom ] ( errno = 0 )
+<118>[ TestFileRW ] [SUCC] Write succeded ( 32 bytes written) ( errno = 0 )
+<118>[ TestFileRW ] [SUCC] Lseek ORIGIN+10 val = 10 should be 10 ( errno = 0 )
+<118>[ TestFileRW ] [SUCC] Lseek CURRENT+1 val = 11 should be 11 ( errno = 0 )
+<118>[ TestFileRW ] [SUCC] Lseek CURRENT-1 val = 10 should be 10 ( errno = 0 )
+<118>[ TestFileRW ] [SUCC] Lseek END val = 0 should be 0 ( errno = 0 )
+<118>[ TestFileRW ] [SUCC] Lseek END-1 val = 0 should be 0 ( errno = 0 )
+<118>[ TestFileRW ] [SUCC] Lseek END+1 val = 1 should be 1 ( errno = 0 )
+<118>[ TestFileRW ] [SUCC] Lseek ORIGIN+0 val = 0 should be 0 ( errno = 0 )
+<118>[ TestFileRW ] [SUCC] Read succeded ( 32 bytes read) ( errno = 0 )
+<118>[ TestFileRW ] [INFO] Buffers are equal? : no
+<118>[ TestFileRW ] [INFO] Write preview: 97 98 99 100
+<118>[ TestFileRW ] [INFO] Read preview: 54 124 7 43
+<118>[ TestFileRW ] [INFO] Is reading buffer full of zeros? : no
+<118>[ RunTests ] [SUCC] Test complete [All should pass, random reads]
+<118>[ TestFileRW ] [TEST_CASE] Testing r/w on [ /dev/zero ]
+<118>[ TestFileRW ] [SUCC] Opened [ /dev/zero ] ( errno = 0 )
+<118>[ TestFileRW ] [SUCC] Write succeded ( 32 bytes written) ( errno = 0 )
+<118>[ TestFileRW ] [SUCC] Lseek ORIGIN+10 val = 10 should be 10 ( errno = 0 )
+<118>[ TestFileRW ] [SUCC] Lseek CURRENT+1 val = 11 should be 11 ( errno = 0 )
+<118>[ TestFileRW ] [SUCC] Lseek CURRENT-1 val = 10 should be 10 ( errno = 0 )
+<118>[ TestFileRW ] [SUCC] Lseek END val = 0 should be 0 ( errno = 0 )
+<118>[ TestFileRW ] [SUCC] Lseek END-1 val = 0 should be 0 ( errno = 0 )
+<118>[ TestFileRW ] [SUCC] Lseek END+1 val = 1 should be 1 ( errno = 0 )
+<118>[ TestFileRW ] [SUCC] Lseek ORIGIN+0 val = 0 should be 0 ( errno = 0 )
+<118>[ TestFileRW ] [SUCC] Read succeded ( 32 bytes read) ( errno = 0 )
+<118>[ TestFileRW ] [INFO] Buffers are equal? : no
+<118>[ TestFileRW ] [INFO] Write preview: 97 98 99 100
+<118>[ TestFileRW ] [INFO] Read preview: 0 0 0 0
+<118>[ TestFileRW ] [INFO] Is reading buffer full of zeros? : yes
+<118>[ RunTests ] [SUCC] Test complete [All should pass, read buffer zeroed out]
+<118>[ Obliterate ] [INFO] << rm -rf [ /data/therapist/tmd ] >>
+<118>[ Obliterate ] [SUCC] >> rm -rf [ /data/therapist/tmd ] <<
+<118>[ dumpDirRecursive ] [INFO] Listing dirents of [ /data/therapist/tmd ]
+<118>[ dumpDirRecursive ] [INFO] [ DIR ][ 15581929 ][ 1 ][ 12 ] |->.
+<118>[ dumpDirRecursive ] [INFO] [ DIR ][ 15581570 ][ 2 ][ 12 ] |->..
+<118>[ dumpDirRecursive ] [INFO] [ FIL ][ 15581930 ][ 26 ][ 36 ] |->AFileWithAReallyLongName-0
+<118>[ dumpDirRecursive ] [INFO] [ FIL ][ 15581931 ][ 26 ][ 36 ] |->AFileWithAReallyLongName-1
+<118>[ dumpDirRecursive ] [INFO] [ FIL ][ 15581932 ][ 26 ][ 36 ] |->AFileWithAReallyLongName-2
+<118>[ dumpDirRecursive ] [INFO] [ FIL ][ 15581933 ][ 26 ][ 36 ] |->AFileWithAReallyLongName-3
+<118>[ dumpDirRecursive ] [INFO] [ FIL ][ 15581934 ][ 26 ][ 36 ] |->AFileWithAReallyLongName-4
+<118>[ dumpDirRecursive ] [INFO] [ FIL ][ 15581935 ][ 26 ][ 36 ] |->AFileWithAReallyLongName-5
+<118>[ dumpDirRecursive ] [INFO] [ FIL ][ 15581936 ][ 26 ][ 36 ] |->AFileWithAReallyLongName-6
+<118>[ dumpDirRecursive ] [INFO] [ FIL ][ 15581937 ][ 26 ][ 36 ] |->AFileWithAReallyLongName-7
+<118>[ dumpDirRecursive ] [INFO] [ FIL ][ 15581938 ][ 26 ][ 36 ] |->AFileWithAReallyLongName-8
+<118>[ dumpDirRecursive ] [INFO] [ FIL ][ 15581939 ][ 26 ][ 36 ] |->AFileWithAReallyLongName-9
+<118>[ dumpDirRecursive ] [INFO] [ FIL ][ 15581940 ][ 27 ][ 36 ] |->AFileWithAReallyLongName-10
+<118>[ dumpDirRecursive ] [INFO] [ FIL ][ 15581941 ][ 27 ][ 36 ] |->AFileWithAReallyLongName-11
+<118>[ dumpDirRecursive ] [INFO] [ FIL ][ 15581942 ][ 27 ][ 36 ] |->AFileWithAReallyLongName-12
+<118>[ dumpDirRecursive ] [INFO] [ FIL ][ 15581946 ][ 4 ][ 20 ] |->SN-0
+<118>[ dumpDirRecursive ] [INFO] [ FIL ][ 15581943 ][ 27 ][ 36 ] |->AFileWithAReallyLongName-13
+<118>[ dumpDirRecursive ] [INFO] [ FIL ][ 15581944 ][ 27 ][ 36 ] |->AFileWithAReallyLongName-14
+<118>[ dumpDirRecursive ] [INFO] [ FIL ][ 15581945 ][ 27 ][ 36 ] |->AFileWithAReallyLongName-15
+<118>[ dumpDirRecursive ] [INFO] [ FIL ][ 15581947 ][ 4 ][ 16 ] |->SN-1
+<118>[ dumpDirRecursive ] [INFO] [ FIL ][ 15581948 ][ 4 ][ 16 ] |->SN-2
+<118>[ dumpDirRecursive ] [INFO] [ FIL ][ 15581949 ][ 4 ][ 16 ] |->SN-3
+<118>[ dumpDirRecursive ] [INFO] [ FIL ][ 15581950 ][ 4 ][ 16 ] |->SN-4
+<118>[ dumpDirRecursive ] [INFO] [ FIL ][ 15581951 ][ 4 ][ 16 ] |->SN-5
+<118>[ dumpDirRecursive ] [INFO] [ FIL ][ 15581952 ][ 4 ][ 16 ] |->SN-6
+<118>[ dumpDirRecursive ] [INFO] [ FIL ][ 15581953 ][ 4 ][ 16 ] |->SN-7
+<118>[ dumpDirRecursive ] [INFO] [ FIL ][ 15581954 ][ 4 ][ 16 ] |->SN-8
+<118>[ dumpDirRecursive ] [INFO] [ FIL ][ 15581955 ][ 4 ][ 16 ] |->SN-9
+<118>[ dumpDirRecursive ] [INFO] [ FIL ][ 15581956 ][ 5 ][ 16 ] |->SN-10
+<118>[ dumpDirRecursive ] [INFO] [ FIL ][ 15581957 ][ 5 ][ 16 ] |->SN-11
+<118>[ dumpDirRecursive ] [INFO] [ FIL ][ 15581958 ][ 5 ][ 16 ] |->SN-12
+<118>[ dumpDirRecursive ] [INFO] [ FIL ][ 15581959 ][ 5 ][ 16 ] |->SN-13
+<118>[ dumpDirRecursive ] [INFO] [ FIL ][ 15581960 ][ 5 ][ 16 ] |->SN-14
+<118>[ dumpDirRecursive ] [INFO] [ FIL ][ 15581961 ][ 5 ][ 16 ] |->SN-15
+<118>[ dumpDirRecursive ] [INFO] [ FIL ][ 15581962 ][ 5 ][ 16 ] |->SN-16
+<118>[ dumpDirRecursive ] [INFO] [ FIL ][ 15581963 ][ 5 ][ 16 ] |->SN-17
+<118>[ dumpDirRecursive ] [INFO] [ FIL ][ 15581964 ][ 5 ][ 16 ] |->SN-18
+<118>[ dumpDirRecursive ] [INFO] [ FIL ][ 15581965 ][ 5 ][ 16 ] |->SN-19
+<118>[ dumpDirRecursive ] [INFO] [ FIL ][ 15581966 ][ 5 ][ 16 ] |->SN-20
+<118>[ dumpDirRecursive ] [INFO] [ FIL ][ 15581967 ][ 5 ][ 16 ] |->SN-21
+<118>[ dumpDirRecursive ] [INFO] [ FIL ][ 15581968 ][ 5 ][ 16 ] |->SN-22
+<118>[ dumpDirRecursive ] [INFO] [ FIL ][ 15581969 ][ 5 ][ 16 ] |->SN-23
+<118>[ dumpDirRecursive ] [INFO] [ FIL ][ 15581970 ][ 5 ][ 16 ] |->SN-24
+<118>[ dumpDirRecursive ] [INFO] [ FIL ][ 15581971 ][ 5 ][ 20 ] |->SN-25
+<118>[ dumpDirRecursive ] [INFO] [ FIL ][ 15581972 ][ 5 ][ 16 ] |->SN-26
+<118>[ dumpDirRecursive ] [INFO] [ FIL ][ 15581973 ][ 5 ][ 16 ] |->SN-27
+<118>[ dumpDirRecursive ] [INFO] [ FIL ][ 15581974 ][ 5 ][ 16 ] |->SN-28
+<118>[ dumpDirRecursive ] [INFO] [ FIL ][ 15581975 ][ 5 ][ 16 ] |->SN-29
+<118>[ dumpDirRecursive ] [INFO] [ FIL ][ 15581976 ][ 5 ][ 16 ] |->SN-30
+<118>[ dumpDirRecursive ] [INFO] [ FIL ][ 15581977 ][ 5 ][ 16 ] |->SN-31
+<118>[ dumpDirRecursive ] [INFO] [ FIL ][ 15581978 ][ 5 ][ 16 ] |->SN-32
+<118>[ dumpDirRecursive ] [INFO] [ FIL ][ 15581979 ][ 5 ][ 16 ] |->SN-33
+<118>[ dumpDirRecursive ] [INFO] [ FIL ][ 15581980 ][ 5 ][ 16 ] |->SN-34
+<118>[ dumpDirRecursive ] [INFO] [ FIL ][ 15581981 ][ 5 ][ 16 ] |->SN-35
+<118>[ dumpDirRecursive ] [INFO] [ FIL ][ 15581982 ][ 5 ][ 16 ] |->SN-36
+<118>[ dumpDirRecursive ] [INFO] [ FIL ][ 15581983 ][ 5 ][ 16 ] |->SN-37
+<118>[ dumpDirRecursive ] [INFO] [ FIL ][ 15581984 ][ 5 ][ 16 ] |->SN-38
+<118>[ dumpDirRecursive ] [INFO] [ FIL ][ 15581985 ][ 5 ][ 16 ] |->SN-39
+<118>[ dumpDirRecursive ] [INFO] [ FIL ][ 15581986 ][ 5 ][ 16 ] |->SN-40
+<118>[ dumpDirRecursive ] [INFO] [ FIL ][ 15581987 ][ 5 ][ 16 ] |->SN-41
+<118>[ dumpDirRecursive ] [INFO] [ FIL ][ 15581988 ][ 5 ][ 16 ] |->SN-42
+<118>[ dumpDirRecursive ] [INFO] [ FIL ][ 15581989 ][ 5 ][ 16 ] |->SN-43
+<118>[ dumpDirRecursive ] [INFO] [ FIL ][ 15581990 ][ 5 ][ 16 ] |->SN-44
+<118>[ dumpDirRecursive ] [INFO] [ FIL ][ 15581991 ][ 5 ][ 16 ] |->SN-45
+<118>[ dumpDirRecursive ] [INFO] [ FIL ][ 15581992 ][ 5 ][ 16 ] |->SN-46
+<118>[ dumpDirRecursive ] [INFO] [ FIL ][ 15581993 ][ 5 ][ 16 ] |->SN-47
+<118>[ dumpDirRecursive ] [INFO] [ FIL ][ 15581994 ][ 5 ][ 16 ] |->SN-48
+<118>[ dumpDirRecursive ] [INFO] [ FIL ][ 15581995 ][ 5 ][ 16 ] |->SN-49
+<118>[ dumpDirRecursive ] [INFO] [ FIL ][ 15581996 ][ 5 ][ 16 ] |->SN-50
+<118>[ dumpDirRecursive ] [INFO] [ FIL ][ 15581997 ][ 5 ][ 16 ] |->SN-51
+<118>[ dumpDirRecursive ] [INFO] [ FIL ][ 15581998 ][ 5 ][ 16 ] |->SN-52
+<118>[ dumpDirRecursive ] [INFO] [ FIL ][ 15581999 ][ 5 ][ 16 ] |->SN-53
+<118>[ dumpDirRecursive ] [INFO] [ FIL ][ 15582000 ][ 5 ][ 16 ] |->SN-54
+<118>[ dumpDirRecursive ] [INFO] [ FIL ][ 15582001 ][ 5 ][ 16 ] |->SN-55
+<118>[ dumpDirRecursive ] [INFO] [ FIL ][ 15582002 ][ 5 ][ 16 ] |->SN-56
+<118>[ dumpDirRecursive ] [INFO] [ FIL ][ 15582003 ][ 5 ][ 16 ] |->SN-57
+<118>[ dumpDirRecursive ] [INFO] [ FIL ][ 15582004 ][ 5 ][ 16 ] |->SN-58
+<118>[ dumpDirRecursive ] [INFO] [ FIL ][ 15582005 ][ 5 ][ 16 ] |->SN-59
+<118>[ dumpDirRecursive ] [INFO] [ FIL ][ 15582006 ][ 5 ][ 16 ] |->SN-60
+<118>[ dumpDirRecursive ] [INFO] [ FIL ][ 15582007 ][ 5 ][ 16 ] |->SN-61
+<118>[ dumpDirRecursive ] [INFO] [ FIL ][ 15582008 ][ 5 ][ 16 ] |->SN-62
+<118>[ dumpDirRecursive ] [INFO] [ FIL ][ 15582009 ][ 5 ][ 432 ] |->SN-63
+<118>[ dumpDirRecursive ] [SUCC] Listing dirents of [ /data/therapist/tmd ]
+<118>[ RunTests ] [INFO]
+<118>[ RunTests ] [INFO] <<<< Case sensitivity tests >>>>
+<118>[ RunTests ] [INFO]
+<118>[ RunTests ] [SUCC] Test file created
+<118>[ RunTests ] [SUCC] Data: 1:1 case sensitivity passed ( /data/therapist/cAsEinSenSiTive.hwdp )
+<118>[ RunTests ] [SUCC] Data: Data: Lowercase sensitivity passed ( /data/therapist/caseinsensitive.hwdp )
+<118>[ RunTests ] [SUCC] Data: Uppercase sensitivity passed ( /DATA/THERAPIST/CASEINSENSITIVE.HWDP )
+<118>[ RunTests ] [SUCC] Data: Uppercase sensitivity (2nd half) passed ( /data/THERAPIST/CASEINSENSITIVE.HWDP )
+<118>[ RunTests ] [SUCC] app0: 1:1 case sensitivity passed ( /app0/assets/misc/cAsEinSEnsITiVE.HwDp )
+<118>[ RunTests ] [SUCC] app0: Data: Lowercase sensitivity passed ( /app0/assets/misc/caseinsensitive.hwdp )
+<118>[ RunTests ] [SUCC] app0: Uppercase (whole path) sensitivity passed ( /APP0/ASSETS/misc/CASEINSENSITIVE.HWDP )
+<118>[ RunTests ] [SUCC] app0: Uppercase (app0 path) sensitivity passed ( /app0/ASSETS/misc/CASEINSENSITIVE.HWDP )
+<118>[ RunTests ] [INFO]
+<118>[ RunTests ] [INFO] Long names (ENAMETOOLONG)
+<118>[ RunTests ] [INFO]
+<118>[ RunTests ] [SUCC] File name too long detected sceKernelOpen(RO) ( errno = 63 , should be 63 )
+<118>[ RunTests ] [SUCC] Cursed rw flags are more important than ENAMETOOLONG sceKernelOpen(RDO|WRO|RW) ( errno = 22 , should be 22 )
+<118>[ RunTests ] [SUCC] File creation flags are less important than ENAMETOOLONG sceKernelOpen(CREAT|RDO) ( errno = 63 , should be 63 )
+<118>[ RunTests ] [SUCC] File name too long detected sceKernelRename(long,normal) ( errno = 63 , should be 63 )
+<118>[ RunTests ] [SUCC] File name too long detected sceKernelRename(normal,long) ( errno = 63 , should be 63 )
+<118>[ RunTests ] [SUCC] File name too long detected sceKernelCheckReachability() ( errno = 63 , should be 63 )
+<118>[ RunTests ] [SUCC] File name too long detected sceKernelMkdir() ( errno = 63 , should be 63 )
+<118>[ RunTests ] [SUCC] File name too long detected sceKernelStat() ( errno = 63 , should be 63 )
+<118>[ RunTests ] [SUCC] File name too long detected sceKernelUnlink() ( errno = 63 , should be 63 )
+<118>[ RunTests ] [SUCC] File name too long detected open(RO) ( errno = 63 , should be 63 )
+<118>[ RunTests ] [SUCC] Cursed rw flags are more important than ENAMETOOLONG open(RDO|WRO|RW) ( errno = 22 , should be 22 )
+<118>[ RunTests ] [SUCC] File creation flags are less important than ENAMETOOLONG open(CREAT|RDO) ( errno = 63 , should be 63 )
+<118>[ RunTests ] [SUCC] File name too long detected rename(long,normal) ( errno = 63 , should be 63 )
+<118>[ RunTests ] [SUCC] File name too long detected rename(normal,long) ( errno = 63 , should be 63 )
+<118>[ RunTests ] [SUCC] File name too long detected mkdir() ( errno = 63 , should be 63 )
+<118>[ RunTests ] [SUCC] File name too long detected stat() ( errno = 63 , should be 63 )
+<118>[ RunTests ] [SUCC] File name too long detected unlink() ( errno = 63 , should be 63 )
+<118>[ testBody ] [INFO]
+<118>[ testBody ] [INFO] <<<< Open fd abuse (moving/removing files with open fd) >>>>
+<118>[ testBody ] [INFO]
+<118>.[ testBody ] [INFO]
+<118>[ testBody ] [INFO] <<<< Moving files >>>>
+<118>[ testBody ] [INFO]
+<118>[ Obliterate ] [INFO] << rm -rf [ /data/therapist/moves ] >>
+<118>[ Obliterate ] [SUCC] >> rm -rf [ /data/therapist/moves ] <<
+<118>[ testBody ] [INFO] fileno of: movingDirectoryA: 15582013
+<118>[ testBody ] [INFO] fileno of: movingDirectoryB: 15582014
+<118>[ testBody ] [INFO] fileno of: movingDirectoryC: 15582015
+<118>[ testBody ] [INFO] fileno of: movingDirectoryD: 15582016
+<118>[ testBody ] [INFO] fileno of: movingFileA: 15582017
+<118>[ testBody ] [INFO] fileno of: movingFileB: 15582019
+<118>[ testBody ] [INFO] fileno of: movingFileC: 15582021
+<118>[ testBody ] [INFO] fileno of: yeetFile: 15582021
+<118>[ testBody ] [INFO] fileno of: yeetDir: 15582015
+<118>.[ testBody ] [INFO]
+<118>[ testBody ] [INFO] <<<< File open tests >>>>
+<118>[ testBody ] [INFO] Acual flag values for Orbis are different from sys/fcntl.h
+<118>[ testBody ] [INFO] Numerical values are correct as of today, macro flags are not
+<118>[ testBody ] [INFO]
+<118>[ Obliterate ] [INFO] << rm -rf [ /data/therapist/tmp_open ] >>
+<118>[ Obliterate ] [SUCC] >> rm -rf [ /data/therapist/tmp_open ] <<
+<118>[ TestOpenFlags ] [TEST_CASE] Testing open() on [ /data/therapist/tmp_open/nonexistent_ro.txt ] with flags: 0 ( O_RDONLY )
+<118>[ TestOpenFlags ] [TEST_CASE] Testing open() on [ /data/therapist/tmp_open/nonexistent_wo.txt ] with flags: 1 ( O_WRONLY )
+<118>[ TestOpenFlags ] [TEST_CASE] Testing open() on [ /data/therapist/tmp_open/nonexistent_rw.txt ] with flags: 2 ( O_RDWR )
+<118>[ TestOpenFlags ] [TEST_CASE] Testing open() on [ /data/therapist/tmp_open/nonexistent_rowo.txt ] with flags: 3 ( O_RDONLY | O_WRONLY | O_RDWR )
+<118>[ TestOpenFlags ] [TEST_CASE] Testing open() on [ /data/therapist/tmp_open/nonexistent_rot.txt ] with flags: 400 ( O_RDONLY | O_TRUNC )
+<118>[ TestOpenFlags ] [TEST_CASE] Testing open() on [ /data/therapist/tmp_open/nonexistent_wot.txt ] with flags: 401 ( O_WRONLY | O_TRUNC )
+<118>[ TestOpenFlags ] [TEST_CASE] Testing open() on [ /data/therapist/tmp_open/nonexistent_rwt.txt ] with flags: 402 ( O_RDWR | O_TRUNC )
+<118>[ TestOpenFlags ] [TEST_CASE] Testing open() on [ /data/therapist/tmp_open/nonexistent_roc.txt ] with flags: 200 ( O_RDONLY | O_CREAT )
+<118>[ TestOpenFlags ] [TEST_CASE] Testing open() on [ /data/therapist/tmp_open/nonexistent_woc.txt ] with flags: 201 ( O_WRONLY | O_CREAT )
+<118>[ TestOpenFlags ] [TEST_CASE] Testing open() on [ /data/therapist/tmp_open/nonexistent_rwc.txt ] with flags: 202 ( O_RDWR | O_CREAT )
+<118>[ TestOpenFlags ] [TEST_CASE] Testing open() on [ /data/therapist/tmp_open/nonexistent_roc.txt ] with flags: a00 ( O_RDONLY | O_CREAT | O_EXCL )
+<118>[ TestOpenFlags ] [TEST_CASE] Testing open() on [ /data/therapist/tmp_open/nonexistent_woc.txt ] with flags: a01 ( O_WRONLY | O_CREAT | O_EXCL )
+<118>[ TestOpenFlags ] [TEST_CASE] Testing open() on [ /data/therapist/tmp_open/nonexistent_rwc.txt ] with flags: a02 ( O_RDWR | O_CREAT | O_EXCL )
+<118>[ TestOpenFlags ] [TEST_CASE] Testing open() on [ /data/therapist/tmp_open/nonexistent_roa.txt ] with flags: 8 ( O_RDONLY | O_APPEND )
+<118>[ TestOpenFlags ] [TEST_CASE] Testing open() on [ /data/therapist/tmp_open/nonexistent_woa.txt ] with flags: 9 ( O_WRONLY | O_APPEND )
+<118>[ TestOpenFlags ] [TEST_CASE] Testing open() on [ /data/therapist/tmp_open/nonexistent_rwa.txt ] with flags: a ( O_RDWR | O_APPEND )
+<118>[ TestOpenFlags ] [TEST_CASE] Testing open() on [ /data/therapist/tmp_open/nonexistent_rota.txt ] with flags: 408 ( O_RDONLY | O_TRUNC | O_APPEND )
+<118>[ TestOpenFlags ] [TEST_CASE] Testing open() on [ /data/therapist/tmp_open/nonexistent_wota.txt ] with flags: 409 ( O_WRONLY | O_TRUNC | O_APPEND )
+<118>[ TestOpenFlags ] [TEST_CASE] Testing open() on [ /data/therapist/tmp_open/nonexistent_rwta.txt ] with flags: 40a ( O_RDWR | O_TRUNC | O_APPEND )
+<118>[ TestOpenFlags ] [TEST_CASE] Testing open() on [ /data/therapist/tmp_open/nonexistent_dir_ro ] with flags: 20000 ( O_RDONLY | O_DIRECTORY )
+<118>[ TestOpenFlags ] [TEST_CASE] Testing open() on [ /data/therapist/tmp_open/nonexistent_dir_wo ] with flags: 20001 ( O_WRONLY | O_DIRECTORY )
+<118>[ TestOpenFlags ] [TEST_CASE] Testing open() on [ /data/therapist/tmp_open/nonexistent_dir_rw ] with flags: 20002 ( O_RDWR | O_DIRECTORY )
+<118>[ TestOpenFlags ] [TEST_CASE] Testing open() on [ /data/therapist/tmp_open/ ] with flags: 20000 ( O_RDONLY | O_DIRECTORY )
+<118>[ TestOpenFlags ] [TEST_CASE] Testing open() on [ /data/therapist/tmp_open/ ] with flags: 20001 ( O_WRONLY | O_DIRECTORY )
+<118>[ TestOpenFlags ] [TEST_CASE] Testing open() on [ /data/therapist/tmp_open/ ] with flags: 20002 ( O_RDWR | O_DIRECTORY )
+<118>[ TestOpenFlags ] [TEST_CASE] Testing open() on [ /data/therapist/tmp_open/nonexistent_dir_rocd ] with flags: 20200 ( O_RDONLY | O_CREAT | O_DIRECTORY )
+<118>[ TestOpenFlags ] [TEST_CASE] Testing open() on [ /data/therapist/tmp_open/nonexistent_dir_wocd ] with flags: 20201 ( O_WRONLY | O_CREAT | O_DIRECTORY )
+<118>[ TestOpenFlags ] [TEST_CASE] Testing open() on [ /data/therapist/tmp_open/nonexistent_dir_rwcd ] with flags: 20202 ( O_RDWR | O_CREAT | O_DIRECTORY )
+<118>[ TestOpenFlags ] [TEST_CASE] Testing open() on [ /app0/assets/misc/file.txt ] with flags: 0 ( O_RDONLY )
+<118>[ TestOpenFlags ] [TEST_CASE] Testing open() on [ /app0/assets/misc/file.txt ] with flags: 1 ( O_WRONLY )
+<118>[ TestOpenFlags ] [TEST_CASE] Testing open() on [ /app0/assets/misc/file.txt ] with flags: 2 ( O_RDWR )
+<118>[ TestOpenFlags ] [TEST_CASE] Testing open() on [ /app0/assets/misc/file.txt ] with flags: 3 ( O_RDONLY | O_WRONLY | O_RDWR )
+<118>[ TestOpenFlags ] [TEST_CASE] Testing open() on [ assets/misc/file.txt ] with flags: 0 ( O_RDONLY )
+<118>[ TestOpenFlags ] [TEST_CASE] Testing open() on [ ./assets/misc/file.txt ] with flags: 0 ( O_RDONLY )
+<118>[ TestOpenFlags ] [TEST_CASE] Testing open() on [ ] with flags: 0 ( O_RDONLY )
+<118>[ TestOpenFlags ] [TEST_CASE] Testing open() on [ /data/therapist/tmp_open/nonexistent_rot.txt ] with flags: 400 ( O_RDONLY | O_TRUNC )
+<118>[ TestOpenFlags ] [TEST_CASE] Testing open() on [ /data/therapist/tmp_open/nonexistent_rota.txt ] with flags: 408 ( O_RDONLY | O_TRUNC | O_APPEND )
+<118>.
+<118>OK (3 tests, 3 ran, 112 checks, 0 ignored, 0 filtered out, 1813 ms)
+<118>
+<118>[ main ] [INFO]
+<118>[ main ] [INFO] <<<< TESTS END >>>>
+<118>[ main ] [INFO]
\ No newline at end of file
diff --git a/tests/code/filesystem_test/CMakeLists.txt b/tests/code/filesystem_test/CMakeLists.txt
new file mode 100644
index 00000000..87e55725
--- /dev/null
+++ b/tests/code/filesystem_test/CMakeLists.txt
@@ -0,0 +1,8 @@
+project(Therapist VERSION 0.0.1)
+
+link_libraries(SceSystemService)
+
+create_pkg(TEST21370 5 50 "code/log.cpp;code/fs_test_tools.cpp;code/fs_test.cpp;code/main.cpp")
+set_target_properties(TEST21370 PROPERTIES OO_PKG_TITLE "Therapist")
+set_target_properties(TEST21370 PROPERTIES OO_PKG_APPVER "1.37")
+finalize_pkg(TEST21370)
diff --git a/tests/code/filesystem_test/LICENSE b/tests/code/filesystem_test/LICENSE
new file mode 100644
index 00000000..f288702d
--- /dev/null
+++ b/tests/code/filesystem_test/LICENSE
@@ -0,0 +1,674 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc.
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The GNU General Public License is a free, copyleft license for
+software and other kinds of works.
+
+ The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works. By contrast,
+the GNU General Public License is intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users. We, the Free Software Foundation, use the
+GNU General Public License for most of our software; it applies also to
+any other work released this way by its authors. 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
+them 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 prevent others from denying you
+these rights or asking you to surrender the rights. Therefore, you have
+certain responsibilities if you distribute copies of the software, or if
+you modify it: responsibilities to respect the freedom of others.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must pass on to the recipients the same
+freedoms that you received. 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.
+
+ Developers that use the GNU GPL protect your rights with two steps:
+(1) assert copyright on the software, and (2) offer you this License
+giving you legal permission to copy, distribute and/or modify it.
+
+ For the developers' and authors' protection, the GPL clearly explains
+that there is no warranty for this free software. For both users' and
+authors' sake, the GPL requires that modified versions be marked as
+changed, so that their problems will not be attributed erroneously to
+authors of previous versions.
+
+ Some devices are designed to deny users access to install or run
+modified versions of the software inside them, although the manufacturer
+can do so. This is fundamentally incompatible with the aim of
+protecting users' freedom to change the software. The systematic
+pattern of such abuse occurs in the area of products for individuals to
+use, which is precisely where it is most unacceptable. Therefore, we
+have designed this version of the GPL to prohibit the practice for those
+products. If such problems arise substantially in other domains, we
+stand ready to extend this provision to those domains in future versions
+of the GPL, as needed to protect the freedom of users.
+
+ Finally, every program is threatened constantly by software patents.
+States should not allow patents to restrict development and use of
+software on general-purpose computers, but in those that do, we wish to
+avoid the special danger that patents applied to a free program could
+make it effectively proprietary. To prevent this, the GPL assures that
+patents cannot be used to render the program non-free.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ TERMS AND CONDITIONS
+
+ 0. Definitions.
+
+ "This License" refers to version 3 of the GNU General Public License.
+
+ "Copyright" also means copyright-like laws that apply to other kinds of
+works, such as semiconductor masks.
+
+ "The Program" refers to any copyrightable work licensed under this
+License. Each licensee is addressed as "you". "Licensees" and
+"recipients" may be individuals or organizations.
+
+ To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy. The resulting work is called a "modified version" of the
+earlier work or a work "based on" the earlier work.
+
+ A "covered work" means either the unmodified Program or a work based
+on the Program.
+
+ To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy. Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+ To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies. Mere interaction with a user through
+a computer network, with no transfer of a copy, is not conveying.
+
+ An interactive user interface displays "Appropriate Legal Notices"
+to the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License. If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+ 1. Source Code.
+
+ The "source code" for a work means the preferred form of the work
+for making modifications to it. "Object code" means any non-source
+form of a work.
+
+ A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+ The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form. A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+ The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities. However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work. For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+ The Corresponding Source need not include anything that users
+can regenerate automatically from other parts of the Corresponding
+Source.
+
+ The Corresponding Source for a work in source code form is that
+same work.
+
+ 2. Basic Permissions.
+
+ All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met. This License explicitly affirms your unlimited
+permission to run the unmodified Program. The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work. This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+ You may make, run and propagate covered works that you do not
+convey, without conditions so long as your license otherwise remains
+in force. You may convey covered works to others for the sole purpose
+of having them make modifications exclusively for you, or provide you
+with facilities for running those works, provided that you comply with
+the terms of this License in conveying all material for which you do
+not control copyright. Those thus making or running the covered works
+for you must do so exclusively on your behalf, under your direction
+and control, on terms that prohibit them from making any copies of
+your copyrighted material outside their relationship with you.
+
+ Conveying under any other circumstances is permitted solely under
+the conditions stated below. Sublicensing is not allowed; section 10
+makes it unnecessary.
+
+ 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+ No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+ When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such circumvention
+is effected by exercising rights under this License with respect to
+the covered work, and you disclaim any intention to limit operation or
+modification of the work as a means of enforcing, against the work's
+users, your or third parties' legal rights to forbid circumvention of
+technological measures.
+
+ 4. Conveying Verbatim Copies.
+
+ You may convey 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;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+ You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+ 5. Conveying Modified Source Versions.
+
+ You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these conditions:
+
+ a) The work must carry prominent notices stating that you modified
+ it, and giving a relevant date.
+
+ b) The work must carry prominent notices stating that it is
+ released under this License and any conditions added under section
+ 7. This requirement modifies the requirement in section 4 to
+ "keep intact all notices".
+
+ c) You must license the entire work, as a whole, under this
+ License to anyone who comes into possession of a copy. This
+ License will therefore apply, along with any applicable section 7
+ additional terms, to the whole of the work, and all its parts,
+ regardless of how they are packaged. This License gives no
+ permission to license the work in any other way, but it does not
+ invalidate such permission if you have separately received it.
+
+ d) If the work has interactive user interfaces, each must display
+ Appropriate Legal Notices; however, if the Program has interactive
+ interfaces that do not display Appropriate Legal Notices, your
+ work need not make them do so.
+
+ A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit. Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+ 6. Conveying Non-Source Forms.
+
+ You may convey a covered work in object code form under the terms
+of sections 4 and 5, provided that you also convey the
+machine-readable Corresponding Source under the terms of this License,
+in one of these ways:
+
+ a) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by the
+ Corresponding Source fixed on a durable physical medium
+ customarily used for software interchange.
+
+ b) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by a
+ written offer, valid for at least three years and valid for as
+ long as you offer spare parts or customer support for that product
+ model, to give anyone who possesses the object code either (1) a
+ copy of the Corresponding Source for all the software in the
+ product that is covered by this License, on a durable physical
+ medium customarily used for software interchange, for a price no
+ more than your reasonable cost of physically performing this
+ conveying of source, or (2) access to copy the
+ Corresponding Source from a network server at no charge.
+
+ c) Convey individual copies of the object code with a copy of the
+ written offer to provide the Corresponding Source. This
+ alternative is allowed only occasionally and noncommercially, and
+ only if you received the object code with such an offer, in accord
+ with subsection 6b.
+
+ d) Convey the object code by offering access from a designated
+ place (gratis or for a charge), and offer equivalent access to the
+ Corresponding Source in the same way through the same place at no
+ further charge. You need not require recipients to copy the
+ Corresponding Source along with the object code. If the place to
+ copy the object code is a network server, the Corresponding Source
+ may be on a different server (operated by you or a third party)
+ that supports equivalent copying facilities, provided you maintain
+ clear directions next to the object code saying where to find the
+ Corresponding Source. Regardless of what server hosts the
+ Corresponding Source, you remain obligated to ensure that it is
+ available for as long as needed to satisfy these requirements.
+
+ e) Convey the object code using peer-to-peer transmission, provided
+ you inform other peers where the object code and Corresponding
+ Source of the work are being offered to the general public at no
+ charge under subsection 6d.
+
+ A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+ A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal, family,
+or household purposes, or (2) anything designed or sold for incorporation
+into a dwelling. In determining whether a product is a consumer product,
+doubtful cases shall be resolved in favor of coverage. For a particular
+product received by a particular user, "normally used" refers to a
+typical or common use of that class of product, regardless of the status
+of the particular user or of the way in which the particular user
+actually uses, or expects or is expected to use, the product. A product
+is a consumer product regardless of whether the product has substantial
+commercial, industrial or non-consumer uses, unless such uses represent
+the only significant mode of use of the product.
+
+ "Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to install
+and execute modified versions of a covered work in that User Product from
+a modified version of its Corresponding Source. The information must
+suffice to ensure that the continued functioning of the modified object
+code is in no case prevented or interfered with solely because
+modification has been made.
+
+ If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information. But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+ The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or updates
+for a work that has been modified or installed by the recipient, or for
+the User Product in which it has been modified or installed. Access to a
+network may be denied when the modification itself materially and
+adversely affects the operation of the network or violates the rules and
+protocols for communication across the network.
+
+ Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+ 7. Additional Terms.
+
+ "Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law. If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+ When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it. (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.) You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+ Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders of
+that material) supplement the terms of this License with terms:
+
+ a) Disclaiming warranty or limiting liability differently from the
+ terms of sections 15 and 16 of this License; or
+
+ b) Requiring preservation of specified reasonable legal notices or
+ author attributions in that material or in the Appropriate Legal
+ Notices displayed by works containing it; or
+
+ c) Prohibiting misrepresentation of the origin of that material, or
+ requiring that modified versions of such material be marked in
+ reasonable ways as different from the original version; or
+
+ d) Limiting the use for publicity purposes of names of licensors or
+ authors of the material; or
+
+ e) Declining to grant rights under trademark law for use of some
+ trade names, trademarks, or service marks; or
+
+ f) Requiring indemnification of licensors and authors of that
+ material by anyone who conveys the material (or modified versions of
+ it) with contractual assumptions of liability to the recipient, for
+ any liability that these contractual assumptions directly impose on
+ those licensors and authors.
+
+ All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10. If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term. If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+ If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+ Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions;
+the above requirements apply either way.
+
+ 8. Termination.
+
+ You may not propagate or modify a covered work except as expressly
+provided under this License. Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+ However, if you cease all violation of this License, then your
+license from a particular copyright holder is reinstated (a)
+provisionally, unless and until the copyright holder explicitly and
+finally terminates your license, and (b) permanently, if the copyright
+holder fails to notify you of the violation by some reasonable means
+prior to 60 days after the cessation.
+
+ Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+ Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License. If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+ 9. Acceptance Not Required for Having Copies.
+
+ You are not required to accept this License in order to receive or
+run a copy of the Program. Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance. However,
+nothing other than this License grants you permission to propagate or
+modify any covered work. These actions infringe copyright if you do
+not accept this License. Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+ 10. Automatic Licensing of Downstream Recipients.
+
+ Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License. You are not responsible
+for enforcing compliance by third parties with this License.
+
+ An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations. If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+ You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License. For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+ 11. Patents.
+
+ A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based. The
+work thus licensed is called the contributor's "contributor version".
+
+ A contributor's "essential patent claims" are all patent claims
+owned or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version. For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+ Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+ In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement). To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+ If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients. "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+ If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+ A patent license is "discriminatory" if it does not include within
+the scope of its coverage, prohibits the exercise of, or is
+conditioned on the non-exercise of one or more of the rights that are
+specifically granted under this License. You may not convey a covered
+work if you are a party to an arrangement with a third party that is
+in the business of distributing software, under which you make payment
+to the third party based on the extent of your activity of conveying
+the work, and under which the third party grants, to any of the
+parties who would receive the covered work from you, a discriminatory
+patent license (a) in connection with copies of the covered work
+conveyed by you (or copies made from those copies), or (b) primarily
+for and in connection with specific products or compilations that
+contain the covered work, unless you entered into that arrangement,
+or that patent license was granted, prior to 28 March 2007.
+
+ Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+ 12. No Surrender of Others' Freedom.
+
+ If 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 convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you may
+not convey it at all. For example, if you agree to terms that obligate you
+to collect a royalty for further conveying from those to whom you convey
+the Program, the only way you could satisfy both those terms and this
+License would be to refrain entirely from conveying the Program.
+
+ 13. Use with the GNU Affero General Public License.
+
+ Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU Affero General Public License into a single
+combined work, and to convey the resulting work. The terms of this
+License will continue to apply to the part which is the covered work,
+but the special requirements of the GNU Affero General Public License,
+section 13, concerning interaction through a network will apply to the
+combination as such.
+
+ 14. Revised Versions of this License.
+
+ The Free Software Foundation may publish revised and/or new versions of
+the GNU 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 that a certain numbered version of the GNU General
+Public License "or any later version" applies to it, you have the
+option of following the terms and conditions either of that numbered
+version or of any later version published by the Free Software
+Foundation. If the Program does not specify a version number of the
+GNU General Public License, you may choose any version ever published
+by the Free Software Foundation.
+
+ If the Program specifies that a proxy can decide which future
+versions of the GNU General Public License can be used, that proxy's
+public statement of acceptance of a version permanently authorizes you
+to choose that version for the Program.
+
+ Later license versions may give you additional or different
+permissions. However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+ 15. Disclaimer of Warranty.
+
+ 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.
+
+ 16. Limitation of Liability.
+
+ IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+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.
+
+ 17. Interpretation of Sections 15 and 16.
+
+ If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+
+ 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
+state the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+
+ Copyright (C)
+
+ 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 3 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, see .
+
+Also add information on how to contact you by electronic and paper mail.
+
+ If the program does terminal interaction, make it output a short
+notice like this when it starts in an interactive mode:
+
+ Copyright (C)
+ This program 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, your program's commands
+might be different; for a GUI interface, you would use an "about box".
+
+ You should also get your employer (if you work as a programmer) or school,
+if any, to sign a "copyright disclaimer" for the program, if necessary.
+For more information on this, and how to apply and follow the GNU GPL, see
+.
+
+ The GNU 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. But first, please read
+.
diff --git a/tests/code/filesystem_test/README.md b/tests/code/filesystem_test/README.md
new file mode 100644
index 00000000..3788e9cc
--- /dev/null
+++ b/tests/code/filesystem_test/README.md
@@ -0,0 +1,11 @@
+# OpenOrbis CMake project
+
+This is a template for quick start with PS4 development using OpenOrbis toolchain.
+
+## Usage
+
+```bash
+cmake -B./build/ -S./ -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DCMAKE_TOOLCHAIN_FILE=OpenOrbis-tc.cmake
+cmake --build ./build/ -j8
+cmake --install .
+```
diff --git a/tests/code/filesystem_test/assets/misc/cAsEinSEnsITiVE.HwDp b/tests/code/filesystem_test/assets/misc/cAsEinSEnsITiVE.HwDp
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_test/assets/misc/file.txt b/tests/code/filesystem_test/assets/misc/file.txt
new file mode 100644
index 00000000..a9aba45f
--- /dev/null
+++ b/tests/code/filesystem_test/assets/misc/file.txt
@@ -0,0 +1,3 @@
+~~~ Line 1 ~~~
+~~~ Line 2 ~~~
+~~~ Line 3 ~~~
diff --git a/tests/code/filesystem_test/assets/misc/file_empty.txt b/tests/code/filesystem_test/assets/misc/file_empty.txt
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/code/filesystem_test/code/fs_constants.h b/tests/code/filesystem_test/code/fs_constants.h
new file mode 100644
index 00000000..317c90a4
--- /dev/null
+++ b/tests/code/filesystem_test/code/fs_constants.h
@@ -0,0 +1,170 @@
+#include
+
+namespace DumpedConstants {
+
+// real data
+// st_dev, st_ino will differ between everything
+// size, blocks and blksize seem constant
+
+const OrbisKernelStat stat_root {
+ .st_dev = 0,
+ .st_ino = 0,
+ .st_mode = 040775,
+ .st_nlink = 0,
+ .st_uid = 0,
+ .st_gid = 0,
+ .st_rdev = 0,
+ .st_size = 360,
+ .st_blocks = 32,
+ .st_blksize = 16384,
+ .st_flags = 0,
+ .st_gen = 0,
+ .st_lspare = 0,
+};
+
+const OrbisKernelStat stat_root_app0 = {
+ .st_dev = 0,
+ .st_ino = 0,
+ .st_mode = 040555,
+ .st_nlink = 0,
+ .st_uid = 0,
+ .st_gid = 0,
+ .st_rdev = 0,
+ .st_size = 65536,
+ .st_blocks = 128,
+ .st_blksize = 65536,
+ .st_flags = 0,
+ .st_gen = 0,
+ .st_lspare = 0,
+};
+
+const OrbisKernelStat stat_root_app0_eboot = {
+ .st_dev = 0,
+ .st_ino = 0,
+ .st_mode = 0100555,
+ .st_nlink = 0,
+ .st_uid = 0,
+ .st_gid = 0,
+ .st_rdev = 0,
+ .st_size = 1645264,
+ .st_blocks = 3328,
+ .st_blksize = 65536,
+ .st_flags = 0,
+ .st_gen = 0,
+ .st_lspare = 0,
+};
+
+const OrbisKernelStat stat_root_app0_assets_misc_file = {
+ .st_dev = 0,
+ .st_ino = 0,
+ .st_mode = 0100555,
+ .st_nlink = 0,
+ .st_uid = 0,
+ .st_gid = 0,
+ .st_rdev = 0,
+ .st_size = 45,
+ .st_blocks = 128,
+ .st_blksize = 65536,
+ .st_flags = 0,
+ .st_gen = 0,
+ .st_lspare = 0,
+};
+
+const OrbisKernelStat stat_root_data = {
+ .st_dev = 0,
+ .st_ino = 0,
+ .st_mode = 040777,
+ .st_nlink = 0,
+ .st_uid = 0,
+ .st_gid = 0,
+ .st_rdev = 0,
+ .st_size = 512,
+ .st_blocks = 8,
+ .st_blksize = 32768,
+ .st_flags = 0,
+ .st_gen = 0,
+ .st_lspare = 0,
+};
+
+const OrbisKernelStat stat_root_dev = {
+ .st_dev = 0,
+ .st_ino = 0,
+ .st_mode = 040555,
+ .st_nlink = 0,
+ .st_uid = 0,
+ .st_gid = 0,
+ .st_rdev = 0,
+ .st_size = 512,
+ .st_blocks = 1,
+ .st_blksize = 16384,
+ .st_flags = 0,
+ .st_gen = 0,
+ .st_lspare = 0,
+};
+
+const OrbisKernelStat stat_blkdev = {
+ .st_dev = 0,
+ .st_ino = 0,
+ .st_mode = 020666,
+ .st_nlink = 0,
+ .st_uid = 0,
+ .st_gid = 0,
+ .st_rdev = 0,
+ .st_size = 0,
+ .st_blocks = 0,
+ .st_blksize = 16384,
+ .st_flags = 0,
+ .st_gen = 0,
+ .st_lspare = 0,
+ .st_birthtim.tv_sec = -1, // leave it alone :c
+ .st_birthtim.tv_nsec = 0,
+};
+
+const OrbisKernelStat stat_root_host = {
+ .st_dev = 0,
+ .st_ino = 0,
+ .st_mode = 040777,
+ .st_nlink = 0,
+ .st_uid = 0,
+ .st_gid = 0,
+ .st_rdev = 0,
+ .st_size = 4096,
+ .st_blocks = 8,
+ .st_blksize = 16384,
+ .st_flags = 0,
+ .st_gen = 0,
+ .st_lspare = 0,
+};
+
+const OrbisKernelStat stat_root_hostapp = {
+ .st_dev = 0,
+ .st_ino = 0,
+ .st_mode = 040777,
+ .st_nlink = 0,
+ .st_uid = 0,
+ .st_gid = 0,
+ .st_rdev = 0,
+ .st_size = 4096,
+ .st_blocks = 8,
+ .st_blksize = 16384,
+ .st_flags = 0,
+ .st_gen = 0,
+ .st_lspare = 0,
+};
+
+const OrbisKernelStat stat_root_av_contents = {
+ .st_dev = 0,
+ .st_ino = 0,
+ .st_mode = 040775,
+ .st_nlink = 0,
+ .st_uid = 0,
+ .st_gid = 0,
+ .st_rdev = 0,
+ .st_size = 160,
+ .st_blocks = 32,
+ .st_blksize = 16384,
+ .st_flags = 0,
+ .st_gen = 0,
+ .st_lspare = 0,
+};
+} // namespace DumpedConstants
\ No newline at end of file
diff --git a/tests/code/filesystem_test/code/fs_test.cpp b/tests/code/filesystem_test/code/fs_test.cpp
new file mode 100644
index 00000000..b06682f1
--- /dev/null
+++ b/tests/code/filesystem_test/code/fs_test.cpp
@@ -0,0 +1,1668 @@
+#include "fs_test.h"
+
+#include "fs_constants.h"
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+namespace fs = std::filesystem;
+namespace oi = OrbisInternals;
+
+TEST_GROUP (FilesystemTests) {
+ void setup() {}
+ void teardown() {}
+};
+
+TEST(FilesystemTests, FileOpenTests) {
+ Log();
+ Log("\t<<<< File open tests >>>>");
+ Log("\tAcual flag values for Orbis are different from sys/fcntl.h");
+ Log("\tNumerical values are correct as of today, macro flags are not");
+ Log();
+
+ RegenerateDir("/data/therapist/tmp_open");
+ int status {0};
+ int status_errno {0};
+
+ // No modifiers
+ // O_RDONLY
+ status = TestOpenFlags("/data/therapist/tmp_open/nonexistent_ro.txt", O_RDONLY, "O_RDONLY", &status_errno);
+ UNSIGNED_INT_EQUALS(ORBIS_KERNEL_ERROR_ENOENT, status);
+ UNSIGNED_INT_EQUALS(ENOENT, status_errno);
+ // O_WRONLY
+ status = TestOpenFlags("/data/therapist/tmp_open/nonexistent_wo.txt", O_WRONLY, "O_WRONLY", &status_errno);
+ UNSIGNED_INT_EQUALS(ORBIS_KERNEL_ERROR_ENOENT, status);
+ UNSIGNED_INT_EQUALS(ENOENT, status_errno);
+ // O_RDWR
+ status = TestOpenFlags("/data/therapist/tmp_open/nonexistent_rw.txt", O_RDWR, "O_RDWR", &status_errno);
+ UNSIGNED_INT_EQUALS(ORBIS_KERNEL_ERROR_ENOENT, status);
+ UNSIGNED_INT_EQUALS(ENOENT, status_errno);
+ // O_RDONLY | O_WRONLY | O_RDWR
+ status = TestOpenFlags("/data/therapist/tmp_open/nonexistent_rowo.txt", O_RDONLY | O_WRONLY | O_RDWR, "O_RDONLY | O_WRONLY | O_RDWR", &status_errno);
+ UNSIGNED_INT_EQUALS(ORBIS_KERNEL_ERROR_EINVAL, status);
+ UNSIGNED_INT_EQUALS(EINVAL, status_errno);
+
+ // O_TRUNC
+ status = TestOpenFlags("/data/therapist/tmp_open/nonexistent_rot.txt", O_TRUNC, "O_RDONLY | O_TRUNC", &status_errno);
+ UNSIGNED_INT_EQUALS(ORBIS_KERNEL_ERROR_ENOENT, status);
+ UNSIGNED_INT_EQUALS(ENOENT, status_errno);
+ status = TestOpenFlags("/data/therapist/tmp_open/nonexistent_wot.txt", O_WRONLY | O_TRUNC, "O_WRONLY | O_TRUNC", &status_errno);
+ UNSIGNED_INT_EQUALS(ORBIS_KERNEL_ERROR_ENOENT, status);
+ UNSIGNED_INT_EQUALS(ENOENT, status_errno);
+ status = TestOpenFlags("/data/therapist/tmp_open/nonexistent_rwt.txt", O_RDWR | O_TRUNC, "O_RDWR | O_TRUNC", &status_errno);
+ UNSIGNED_INT_EQUALS(ORBIS_KERNEL_ERROR_ENOENT, status);
+ UNSIGNED_INT_EQUALS(ENOENT, status_errno);
+
+ // O_CREAT
+ // these create a file
+ status = TestOpenFlags("/data/therapist/tmp_open/nonexistent_roc.txt", O_RDONLY | O_CREAT, "O_RDONLY | O_CREAT", &status_errno);
+ UNSIGNED_INT_EQUALS(0, status);
+ UNSIGNED_INT_EQUALS(0, status_errno);
+ status = TestOpenFlags("/data/therapist/tmp_open/nonexistent_woc.txt", O_WRONLY | O_CREAT, "O_WRONLY | O_CREAT", &status_errno);
+ UNSIGNED_INT_EQUALS(0, status);
+ UNSIGNED_INT_EQUALS(0, status_errno);
+ status = TestOpenFlags("/data/therapist/tmp_open/nonexistent_rwc.txt", O_RDWR | O_CREAT, "O_RDWR | O_CREAT", &status_errno);
+ UNSIGNED_INT_EQUALS(0, status);
+ UNSIGNED_INT_EQUALS(0, status_errno);
+
+ // O_CREAT | O_EXCL
+ // exists, not creating
+ status = TestOpenFlags("/data/therapist/tmp_open/nonexistent_roc.txt", O_RDONLY | O_CREAT | O_EXCL, "O_RDONLY | O_CREAT | O_EXCL", &status_errno);
+ UNSIGNED_INT_EQUALS(ORBIS_KERNEL_ERROR_EEXIST, status);
+ UNSIGNED_INT_EQUALS(EEXIST, status_errno);
+ status = TestOpenFlags("/data/therapist/tmp_open/nonexistent_woc.txt", O_WRONLY | O_CREAT | O_EXCL, "O_WRONLY | O_CREAT | O_EXCL", &status_errno);
+ UNSIGNED_INT_EQUALS(ORBIS_KERNEL_ERROR_EEXIST, status);
+ UNSIGNED_INT_EQUALS(EEXIST, status_errno);
+ status = TestOpenFlags("/data/therapist/tmp_open/nonexistent_rwc.txt", O_RDWR | O_CREAT | O_EXCL, "O_RDWR | O_CREAT | O_EXCL", &status_errno);
+ UNSIGNED_INT_EQUALS(ORBIS_KERNEL_ERROR_EEXIST, status);
+ UNSIGNED_INT_EQUALS(EEXIST, status_errno);
+
+ // O_APPEND
+ status = TestOpenFlags("/data/therapist/tmp_open/nonexistent_roa.txt", O_RDONLY | O_APPEND, "O_RDONLY | O_APPEND", &status_errno);
+ UNSIGNED_INT_EQUALS(ORBIS_KERNEL_ERROR_ENOENT, status);
+ UNSIGNED_INT_EQUALS(ENOENT, status_errno);
+ status = TestOpenFlags("/data/therapist/tmp_open/nonexistent_woa.txt", O_WRONLY | O_APPEND, "O_WRONLY | O_APPEND", &status_errno);
+ UNSIGNED_INT_EQUALS(ORBIS_KERNEL_ERROR_ENOENT, status);
+ UNSIGNED_INT_EQUALS(ENOENT, status_errno);
+ status = TestOpenFlags("/data/therapist/tmp_open/nonexistent_rwa.txt", O_RDWR | O_APPEND, "O_RDWR | O_APPEND", &status_errno);
+ UNSIGNED_INT_EQUALS(ORBIS_KERNEL_ERROR_ENOENT, status);
+ UNSIGNED_INT_EQUALS(ENOENT, status_errno);
+
+ // O_TRUNC | O_APPEND
+ status = TestOpenFlags("/data/therapist/tmp_open/nonexistent_rota.txt", O_RDONLY | O_TRUNC | O_APPEND, "O_RDONLY | O_TRUNC | O_APPEND", &status_errno);
+ UNSIGNED_INT_EQUALS(ORBIS_KERNEL_ERROR_ENOENT, status);
+ UNSIGNED_INT_EQUALS(ENOENT, status_errno);
+ status = TestOpenFlags("/data/therapist/tmp_open/nonexistent_wota.txt", O_WRONLY | O_TRUNC | O_APPEND, "O_WRONLY | O_TRUNC | O_APPEND", &status_errno);
+ UNSIGNED_INT_EQUALS(ORBIS_KERNEL_ERROR_ENOENT, status);
+ UNSIGNED_INT_EQUALS(ENOENT, status_errno);
+ status = TestOpenFlags("/data/therapist/tmp_open/nonexistent_rwta.txt", O_RDWR | O_TRUNC | O_APPEND, "O_RDWR | O_TRUNC | O_APPEND", &status_errno);
+ UNSIGNED_INT_EQUALS(ORBIS_KERNEL_ERROR_ENOENT, status);
+ UNSIGNED_INT_EQUALS(ENOENT, status_errno);
+
+ // O_DIRECTORY (nonexistent file is a target)
+ status = TestOpenFlags("/data/therapist/tmp_open/nonexistent_dir_ro", O_RDONLY | O_DIRECTORY, "O_RDONLY | O_DIRECTORY", &status_errno);
+ UNSIGNED_INT_EQUALS(ORBIS_KERNEL_ERROR_ENOENT, status);
+ UNSIGNED_INT_EQUALS(ENOENT, status_errno);
+ status = TestOpenFlags("/data/therapist/tmp_open/nonexistent_dir_wo", O_WRONLY | O_DIRECTORY, "O_WRONLY | O_DIRECTORY", &status_errno);
+ UNSIGNED_INT_EQUALS(ORBIS_KERNEL_ERROR_ENOENT, status);
+ UNSIGNED_INT_EQUALS(ENOENT, status_errno);
+ status = TestOpenFlags("/data/therapist/tmp_open/nonexistent_dir_rw", O_RDWR | O_DIRECTORY, "O_RDWR | O_DIRECTORY", &status_errno);
+ UNSIGNED_INT_EQUALS(ORBIS_KERNEL_ERROR_ENOENT, status);
+ UNSIGNED_INT_EQUALS(ENOENT, status_errno);
+
+ // O_DIRECTORY (existing directory)
+ status = TestOpenFlags("/data/therapist/tmp_open/", 0 | 0x20000, "O_RDONLY | O_DIRECTORY", &status_errno);
+ UNSIGNED_INT_EQUALS(0, status);
+ status = TestOpenFlags("/data/therapist/tmp_open/", 0x1 | 0x20000, "O_WRONLY | O_DIRECTORY", &status_errno);
+ UNSIGNED_INT_EQUALS(ORBIS_KERNEL_ERROR_EISDIR, status);
+ UNSIGNED_INT_EQUALS(EISDIR, status_errno);
+ status = TestOpenFlags("/data/therapist/tmp_open/", 0x2 | 0x20000, "O_RDWR | O_DIRECTORY", &status_errno);
+ UNSIGNED_INT_EQUALS(ORBIS_KERNEL_ERROR_EISDIR, status);
+ UNSIGNED_INT_EQUALS(EISDIR, status_errno);
+
+ // O_CREAT | O_DIRECTORY (unspecified type, directory)
+ // these create a file
+ status = TestOpenFlags("/data/therapist/tmp_open/nonexistent_dir_rocd", 0 | 0x200 | 0x20000, "O_RDONLY | O_CREAT | O_DIRECTORY", &status_errno);
+ UNSIGNED_INT_EQUALS(ORBIS_KERNEL_ERROR_ENOTDIR, status);
+ UNSIGNED_INT_EQUALS(ENOTDIR, status_errno);
+ status = TestOpenFlags("/data/therapist/tmp_open/nonexistent_dir_wocd", 0x1 | 0x200 | 0x20000, "O_WRONLY | O_CREAT | O_DIRECTORY", &status_errno);
+ UNSIGNED_INT_EQUALS(ORBIS_KERNEL_ERROR_ENOTDIR, status);
+ UNSIGNED_INT_EQUALS(ENOTDIR, status_errno);
+ status = TestOpenFlags("/data/therapist/tmp_open/nonexistent_dir_rwcd", 0x2 | 0x200 | 0x20000, "O_RDWR | O_CREAT | O_DIRECTORY", &status_errno);
+ UNSIGNED_INT_EQUALS(ORBIS_KERNEL_ERROR_ENOTDIR, status);
+ UNSIGNED_INT_EQUALS(ENOTDIR, status_errno);
+
+ // No modifiers, RO directory
+ // O_RDONLY
+ status = TestOpenFlags("/app0/assets/misc/file.txt", 0, "O_RDONLY", &status_errno);
+ UNSIGNED_INT_EQUALS(0, status);
+ UNSIGNED_INT_EQUALS(0, status_errno);
+ // O_WRONLY
+ status = TestOpenFlags("/app0/assets/misc/file.txt", 0x1, "O_WRONLY", &status_errno);
+ UNSIGNED_INT_EQUALS(ORBIS_KERNEL_ERROR_EROFS, status);
+ UNSIGNED_INT_EQUALS(EROFS, status_errno);
+ // O_RDWR
+ status = TestOpenFlags("/app0/assets/misc/file.txt", 0x2, "O_RDWR", &status_errno);
+ UNSIGNED_INT_EQUALS(ORBIS_KERNEL_ERROR_EROFS, status);
+ UNSIGNED_INT_EQUALS(EROFS, status_errno);
+ // O_RDONLY | O_WRONLY | O_RDWR
+ status = TestOpenFlags("/app0/assets/misc/file.txt", 0 | 0x1 | 0x2, "O_RDONLY | O_WRONLY | O_RDWR", &status_errno);
+ UNSIGNED_INT_EQUALS(ORBIS_KERNEL_ERROR_EINVAL, status);
+ UNSIGNED_INT_EQUALS(EINVAL, status_errno);
+
+ // Obviously bad ones, flags are irrelevant
+ status = TestOpenFlags("assets/misc/file.txt", 0, "O_RDONLY", &status_errno);
+ UNSIGNED_INT_EQUALS_TEXT(ORBIS_KERNEL_ERROR_EINVAL, status, "Relative paths = EINVAL");
+ UNSIGNED_INT_EQUALS_TEXT(EINVAL, status_errno, "Relative paths = EINVAL");
+ status = TestOpenFlags("./assets/misc/file.txt", 0, "O_RDONLY", &status_errno);
+ UNSIGNED_INT_EQUALS(ORBIS_KERNEL_ERROR_EINVAL, status);
+ UNSIGNED_INT_EQUALS(EINVAL, status_errno);
+ status = TestOpenFlags("", 0, "O_RDONLY", &status_errno);
+ UNSIGNED_INT_EQUALS(ORBIS_KERNEL_ERROR_EINVAL, status);
+ UNSIGNED_INT_EQUALS(EINVAL, status_errno);
+
+ // Edge cases - oficial behaviour is undefined
+ status = TestOpenFlags("/data/therapist/tmp_open/nonexistent_rot.txt", O_RDONLY | O_TRUNC, "O_RDONLY | O_TRUNC", &status_errno);
+ UNSIGNED_INT_EQUALS(ORBIS_KERNEL_ERROR_ENOENT, status);
+ UNSIGNED_INT_EQUALS(ENOENT, status_errno);
+ CHECK_TRUE_TEXT(exists("/data/therapist/tmp_open/nonexistent_rot.txt"), "R+TR should error but create a file");
+
+ status = TestOpenFlags("/data/therapist/tmp_open/nonexistent_rota.txt", O_RDONLY | O_TRUNC | O_APPEND, "O_RDONLY | O_TRUNC | O_APPEND", &status_errno);
+ UNSIGNED_INT_EQUALS(ORBIS_KERNEL_ERROR_ENOENT, status);
+ UNSIGNED_INT_EQUALS(ENOENT, status_errno);
+ CHECK_TRUE_TEXT(exists("/data/therapist/tmp_open/nonexistent_rota.txt"), "R+A+TR should error but create a file");
+}
+
+TEST(FilesystemTests, FileMovementTests) {
+ Log();
+ Log("\t<<<< Moving files >>>>");
+ Log();
+
+ const char* movingFileA = "/data/therapist/moves/fileA";
+ const char* movingFileB = "/data/therapist/moves/fileB";
+ const char* movingFileC = "/data/therapist/moves/fileC";
+
+ const char* movingDirectoryA = "/data/therapist/moves/dirA";
+ const char* movingDirectoryB = "/data/therapist/moves/dirB";
+ const char* movingDirectoryC = "/data/therapist/moves/dirC";
+ const char* movingDirectoryD = "/data/therapist/moves/dirD";
+
+ Obliterate("/data/therapist/moves");
+ CHECK_EQUAL_ZERO(sceKernelMkdir("/data/therapist/moves", 0777));
+ CHECK_EQUAL_ZERO(sceKernelMkdir(movingDirectoryA, 0777));
+ CHECK_EQUAL_ZERO(sceKernelMkdir(movingDirectoryB, 0777));
+ CHECK_EQUAL_ZERO(sceKernelMkdir(movingDirectoryC, 0777));
+ CHECK_EQUAL_ZERO(sceKernelMkdir(movingDirectoryD, 0777));
+ CHECK_EQUAL_ZERO(touch(movingFileA));
+ CHECK_EQUAL_ZERO(touch(movingFileB));
+ CHECK_EQUAL_ZERO(touch(movingFileC));
+
+ ino_t fileno_movingDirectoryA = get_fileno(movingDirectoryA);
+ ino_t fileno_movingDirectoryB = get_fileno(movingDirectoryB);
+ ino_t fileno_movingDirectoryC = get_fileno(movingDirectoryC);
+ ino_t fileno_movingDirectoryD = get_fileno(movingDirectoryD);
+ ino_t fileno_movingFileA = get_fileno(movingFileA);
+ ino_t fileno_movingFileB = get_fileno(movingFileB);
+ ino_t fileno_movingFileC = get_fileno(movingFileC);
+
+ Log("fileno of: movingDirectoryA:\t", fileno_movingDirectoryA);
+ Log("fileno of: movingDirectoryB:\t", fileno_movingDirectoryB);
+ Log("fileno of: movingDirectoryC:\t", fileno_movingDirectoryC);
+ Log("fileno of: movingDirectoryD:\t", fileno_movingDirectoryD);
+ Log("fileno of: movingFileA:\t", fileno_movingFileA);
+ Log("fileno of: movingFileB:\t", fileno_movingFileB);
+ Log("fileno of: movingFileC:\t", fileno_movingFileC);
+
+ const char* yeetFile = "/data/therapist/moves/yeet";
+ const char* yeetDir = "/data/therapist/moves/yeet_dir";
+
+ int status {0};
+ // file->(existent)file:
+ status = sceKernelRename(movingFileA, movingFileB);
+ CHECK_EQUAL_ZERO_TEXT(status, "If target exists, it should be overwritten");
+ UNSIGNED_LONGS_EQUAL(fileno_movingFileA, get_fileno(movingFileB));
+ fileno_movingFileB = fileno_movingFileA;
+
+ // file->(nonexistent)file
+ status = sceKernelRename(movingFileC, yeetFile);
+ CHECK_EQUAL_ZERO(status);
+ UNSIGNED_LONGS_EQUAL(fileno_movingFileC, get_fileno(yeetFile));
+ ino_t fileno_movingFileYeet = fileno_movingFileC;
+ Log("fileno of: yeetFile:\t", fileno_movingFileYeet);
+
+ // dir->(existing)dir
+ status = sceKernelRename(movingDirectoryA, movingDirectoryB);
+ CHECK_EQUAL_ZERO(status);
+ UNSIGNED_LONGS_EQUAL(fileno_movingDirectoryA, get_fileno(movingDirectoryB));
+ fileno_movingDirectoryB = fileno_movingDirectoryA;
+
+ // dir->(nonexistent)dir
+ status = sceKernelRename(movingDirectoryC, yeetDir);
+ CHECK_EQUAL_ZERO(status);
+ UNSIGNED_LONGS_EQUAL(fileno_movingDirectoryC, get_fileno(yeetDir));
+ fileno_movingDirectoryB = fileno_movingDirectoryA;
+ ino_t fileno_movingDirYeet = fileno_movingDirectoryC;
+ Log("fileno of: yeetDir:\t", fileno_movingDirYeet);
+
+ // no change in folder structure
+ // file->(existent)dir
+ status = sceKernelRename(yeetFile, yeetDir);
+ UNSIGNED_INT_EQUALS(ORBIS_KERNEL_ERROR_EISDIR, status);
+ UNSIGNED_INT_EQUALS(EISDIR, errno);
+
+ // no change either
+ // dir->(existent)file
+ status = sceKernelRename(yeetDir, yeetFile);
+ UNSIGNED_INT_EQUALS(ORBIS_KERNEL_ERROR_ENOTDIR, status);
+ UNSIGNED_INT_EQUALS(ENOTDIR, errno);
+ // file->(into existent)dir
+ status = sceKernelRename(yeetFile, "/data/therapist/moves/yeet_dir/yeeee");
+ CHECK_EQUAL_ZERO(status);
+ UNSIGNED_LONGS_EQUAL(fileno_movingFileYeet, get_fileno("/data/therapist/moves/yeet_dir/yeeee"));
+
+ // move empty to not empty dir, no change
+ // empty dir->not empty dir
+ status = sceKernelRename(movingDirectoryD, yeetDir);
+ UNSIGNED_INT_EQUALS(ORBIS_KERNEL_ERROR_ENOTEMPTY, status);
+ UNSIGNED_INT_EQUALS(ENOTEMPTY, errno);
+ UNSIGNED_LONGS_EQUAL(fileno_movingDirYeet, get_fileno(yeetDir));
+
+ // not empty to empty, changed
+ // not empty dir->empty dir
+ status = sceKernelRename(yeetDir, movingDirectoryD);
+ CHECK_EQUAL_ZERO(status);
+ UNSIGNED_LONGS_EQUAL(fileno_movingDirYeet, get_fileno(movingDirectoryD));
+ fileno_movingDirectoryD = fileno_movingDirYeet; // just to keep track
+}
+
+TEST(FilesystemTests, FileOpenAbuseTest) {
+ Log();
+ Log("\t<<<< Open fd abuse (moving/removing files with open fd) >>>>");
+ Log();
+
+ const char* abused_file = "/data/therapist/abuse.txt";
+ const char* teststring1 = "0123456789\r\n";
+ const char* teststring2 = "9876543210\r\n";
+ const char* readback_string = "0123456789\r\n9876543210\r\n";
+ int64_t readback_string_len = strlen(readback_string);
+ char* abused_buffer[256] {0};
+
+ touch(abused_file);
+ int status {0};
+ int abused_fd = sceKernelOpen(abused_file, O_RDWR, 0777);
+ auto abused_fileno = get_fileno(abused_file);
+
+ CHECK_COMPARE_TEXT(0, <, abused_fileno, "Fileno cannot be 0"); // File not created otherwise
+
+ // write to opened file
+ status = sceKernelWrite(abused_fd, teststring1, strlen(teststring1));
+ LONGLONGS_EQUAL(strlen(teststring1), status);
+ // remove that file
+ status = sceKernelUnlink(abused_file);
+ CHECK_EQUAL_ZERO(status);
+ // should be unlinked
+ CHECK_EQUAL_ZERO(get_fileno(abused_file)); // not unlinked if !=0
+
+ // should be able to r/w to it, inode remains while directory entry is deleted
+ LONGLONGS_EQUAL(strlen(teststring2), sceKernelWrite(abused_fd, teststring2, strlen(teststring2)));
+ CHECK_EQUAL_ZERO(sceKernelLseek(abused_fd, 0, 0));
+ CHECK_COMPARE(sceKernelRead(abused_fd, abused_buffer, 256), >, 0);
+ CHECK_EQUAL_ZERO(memcmp(abused_buffer, readback_string, readback_string_len));
+
+ UNSIGNED_LONGS_EQUAL_TEXT(abused_fileno, get_fileno(abused_fd), "fileno should be preserved after unlink before closing the file");
+ UNSIGNED_INT_EQUALS_TEXT(ORBIS_KERNEL_ERROR_ENOENT, exists(abused_file), "Disk entry should be removed");
+ UNSIGNED_INT_EQUALS_TEXT(ENOENT, errno, "Disk entry should be removed");
+ CHECK_EQUAL_ZERO_TEXT(sceKernelClose(abused_fd), "Descriptor should be valid up until now");
+}
+
+TEST(FilesystemTests, StatDumpTests) {
+ Log();
+ Log("\t<<<< STAT >>>>");
+ Log("\tLHS - current, RHS - original HW");
+ Log();
+
+ CHECK_TRUE(TestStat("/", &DumpedConstants::stat_root));
+ CHECK_TRUE(TestStat("/app0", &DumpedConstants::stat_root_app0));
+ CHECK_TRUE(TestStat("/app0/eboot.bin", &DumpedConstants::stat_root_app0_eboot));
+ CHECK_TRUE(TestStat("/app0/assets/misc/file.txt", &DumpedConstants::stat_root_app0_assets_misc_file));
+ CHECK_TRUE(TestStat("/data/therapist", &DumpedConstants::stat_root_data));
+ CHECK_TRUE(TestStat("/dev", &DumpedConstants::stat_root_dev));
+ CHECK_TRUE(TestStat("/dev/deci_stderr", &DumpedConstants::stat_blkdev));
+ CHECK_TRUE(TestLStat("/dev/deci_stderr"));
+ CHECK_TRUE(TestStat("/dev/deci_stdout", &DumpedConstants::stat_blkdev));
+ CHECK_TRUE(TestStat("/dev/stdin", nullptr));
+ CHECK_TRUE_TEXT(TestStat("/dev/stdout", nullptr), "Stat shouldn't work on /dev/stdout");
+ CHECK_TRUE_TEXT(!TestLStat("/dev/stdout"), "LStat shouldn't work on /dev/stdout");
+ CHECK_TRUE(TestStat("/dev/random", &DumpedConstants::stat_blkdev));
+ CHECK_TRUE(TestStat("/dev/urandom", &DumpedConstants::stat_blkdev));
+ CHECK_TRUE(TestStat("/host", &DumpedConstants::stat_root_host));
+ CHECK_TRUE(TestStat("/hostapp", &DumpedConstants::stat_root_hostapp));
+ CHECK_TRUE(TestStat("/av_contents", &DumpedConstants::stat_root_av_contents));
+ CHECK_TRUE_TEXT(!TestLStat("/av_contents"), "LStat shouldn't work on /av_contents");
+}
+
+TEST(FilesystemTests, FileResolutionTests) {
+ Log();
+ Log("\t<<<< Reachability and path resolution >>>>");
+ Log("\tSymlinks are not functional yet i think");
+ Log();
+
+ const char* dir_main = "/data/therapist/resolve";
+ // base patterns
+ const char* dirA = "/data/therapist/resolve/dirA";
+ const char* dirB = "/data/therapist/resolve/dirB";
+ const char* fileA = "/data/therapist/resolve/fileA";
+ const char* fileB = "/data/therapist/resolve/fileB";
+ // const char* symlinkFileA = "/data/therapist/resolve/symlinkFileA";
+ // const char* symlinkDirA = "/data/therapist/resolve/symlinkDirA";
+ // edge cases
+ const char* dirAslash = "/data/therapist/resolve/dirA/";
+ const char* fileAslash = "/data/therapist/resolve/fileA/";
+ // const char* symlinkFileAslash = "/data/therapist/resolve/symlinkFileA/";
+ // const char* symlinkDirAslash = "/data/therapist/resolve/symlinkDirA/";
+ //
+ const char* dirAslashd = "/data/therapist/resolve/dirA/.";
+ const char* fileAslashd = "/data/therapist/resolve/fileA/.";
+ // const char* symlinkFileAslashd = "/data/therapist/resolve/symlinkFileA/.";
+ // const char* symlinkDirAslashd = "/data/therapist/resolve/symlinkDirA/.";
+ //
+ const char* dirAslashdd = "/data/therapist/resolve/dirA/..";
+ const char* fileAslashdd = "/data/therapist/resolve/fileA/..";
+ // const char* symlinkFileAslashdd = "/data/therapist/resolve/symlinkFileA/..";
+ // const char* symlinkDirAslashdd = "/data/therapist/resolve/symlinkDirA/..";
+
+ RegenerateDir("/data/therapist/resolve");
+ CHECK_EQUAL_ZERO(sceKernelMkdir(dirA, 0777));
+ CHECK_EQUAL_ZERO(sceKernelMkdir(dirB, 0777));
+ CHECK_EQUAL_ZERO(touch(fileA));
+ CHECK_EQUAL_ZERO(touch(fileB));
+ // CHECK_EQUAL_ZERO(symlink(symlinkFileA, fileA));
+ // CHECK_EQUAL_ZERO(symlink(symlinkDirA, dirA));
+
+ struct stat dir_st {};
+ struct stat dirA_st {};
+ struct stat dirB_st {};
+ struct stat fileA_st {};
+ struct stat fileB_st {};
+ // struct stat symlinkFileA_st {};
+ // struct stat symlinkDirA_st {};
+
+ auto qcmp = [](const struct stat& left, const struct stat& right) -> bool {
+ return memcmp(&left, &right, 24) == 0; // basically everything that matters
+ };
+
+ // clang-format off
+ errno = 0; CHECK_EQUAL_ZERO(stat(dir_main, &dir_st)); CHECK_EQUAL_ZERO(errno);
+ errno = 0; CHECK_EQUAL_ZERO(stat(dirA, &dirA_st)); CHECK_EQUAL_ZERO(errno);
+ errno = 0; CHECK_EQUAL_ZERO(stat(dirB, &dirB_st)); CHECK_EQUAL_ZERO(errno);
+ errno = 0; CHECK_EQUAL_ZERO(stat(fileA, &fileA_st)); CHECK_EQUAL_ZERO(errno);
+ errno = 0; CHECK_EQUAL_ZERO(stat(fileB, &fileB_st)); CHECK_EQUAL_ZERO(errno);
+ // errno = 0; CHECK_EQUAL(-1, stat(symlinkFileA, &symlinkFileA_st)); CHECK_EQUAL(ENOENT, errno);
+ // errno = 0; CHECK_EQUAL(-1, stat(symlinkDirA, &symlinkDirA_st)); CHECK_EQUAL(ENOENT, errno);
+
+ errno = 0; CHECK_EQUAL_ZERO(sceKernelCheckReachability(dirA)); CHECK_EQUAL_ZERO(errno);
+ errno = 0; CHECK_EQUAL_ZERO(sceKernelCheckReachability(dirB)); CHECK_EQUAL_ZERO(errno);
+ errno = 0; CHECK_EQUAL_ZERO(sceKernelCheckReachability(fileA)); CHECK_EQUAL_ZERO(errno);
+ errno = 0; CHECK_EQUAL_ZERO(sceKernelCheckReachability(fileB)); CHECK_EQUAL_ZERO(errno);
+ // errno = 0; CHECK_EQUAL(ORBIS_KERNEL_ERROR_ENOENT, sceKernelCheckReachability(symlinkFileA)); CHECK_EQUAL(ENOENT, errno);
+ // errno = 0; CHECK_EQUAL(ORBIS_KERNEL_ERROR_ENOENT, sceKernelCheckReachability(symlinkDirA)); CHECK_EQUAL(ENOENT, errno);
+
+ errno = 0; CHECK_EQUAL(ORBIS_KERNEL_ERROR_ENOENT, sceKernelCheckReachability(dirAslash)); CHECK_EQUAL_ZERO(errno);
+ errno = 0; CHECK_EQUAL(ORBIS_KERNEL_ERROR_ENOENT, sceKernelCheckReachability(fileAslash)); CHECK_EQUAL_ZERO(errno);
+ // errno = 0; CHECK_EQUAL(ORBIS_KERNEL_ERROR_ENOENT, sceKernelCheckReachability(symlinkFileAslash)); CHECK_EQUAL(ENOENT, errno);
+ // errno = 0; CHECK_EQUAL(ORBIS_KERNEL_ERROR_ENOENT, sceKernelCheckReachability(symlinkDirAslash)); CHECK_EQUAL(ENOENT, errno);
+
+ errno = 0; CHECK_EQUAL_ZERO(sceKernelCheckReachability(dirAslashd)); CHECK_EQUAL_ZERO(errno);
+ errno = 0; CHECK_EQUAL(ORBIS_KERNEL_ERROR_ENOENT, sceKernelCheckReachability(fileAslashd)); CHECK_EQUAL_ZERO(errno);
+ // errno = 0; CHECK_EQUAL(ORBIS_KERNEL_ERROR_ENOENT, sceKernelCheckReachability(symlinkFileAslashd)); CHECK_EQUAL(ENOENT, errno);
+ // errno = 0; CHECK_EQUAL(ORBIS_KERNEL_ERROR_ENOENT, sceKernelCheckReachability(symlinkDirAslashd)); CHECK_EQUAL(ENOENT, errno);
+
+ errno = 0; CHECK_EQUAL_ZERO(sceKernelCheckReachability(dirAslashdd)); CHECK_EQUAL_ZERO(errno);
+ errno = 0; CHECK_EQUAL(ORBIS_KERNEL_ERROR_ENOENT, sceKernelCheckReachability(fileAslashdd)); CHECK_EQUAL_ZERO(errno);
+ // errno = 0; CHECK_EQUAL(ORBIS_KERNEL_ERROR_ENOENT, sceKernelCheckReachability(symlinkFileAslashdd)); CHECK_EQUAL(ENOENT, errno);
+ // errno = 0; CHECK_EQUAL(ORBIS_KERNEL_ERROR_ENOENT, sceKernelCheckReachability(symlinkDirAslashdd)); CHECK_EQUAL(ENOENT, errno);
+
+ struct stat st {};
+ errno = 0; CHECK_EQUAL_ZERO(stat(dirA, &st)); CHECK_EQUAL_ZERO(errno); CHECK_TRUE(qcmp(st, dirA_st));
+ errno = 0; CHECK_EQUAL_ZERO(stat(dirB, &st)); CHECK_EQUAL_ZERO(errno); CHECK_TRUE(qcmp(st, dirB_st));
+ errno = 0; CHECK_EQUAL_ZERO(stat(fileA, &st)); CHECK_EQUAL_ZERO(errno); CHECK_TRUE(qcmp(st, fileA_st));
+ errno = 0; CHECK_EQUAL_ZERO(stat(fileB, &st)); CHECK_EQUAL_ZERO(errno); CHECK_TRUE(qcmp(st, fileB_st));
+ // errno = 0; CHECK_EQUAL(-1, stat(symlinkFileA, &st)); CHECK_EQUAL(ENOENT, errno);
+ // errno = 0; CHECK_EQUAL(-1, stat(symlinkDirA, &st)); CHECK_EQUAL(ENOENT, errno);
+ errno = 0; CHECK_EQUAL_ZERO(stat(dirAslash, &st)); CHECK_EQUAL_ZERO(errno); CHECK_TRUE(qcmp(st, dirA_st));
+ errno = 0; CHECK_EQUAL(-1, stat(fileAslash, &st)); CHECK_EQUAL(ENOTDIR, errno);
+ // errno = 0; CHECK_EQUAL(-1, stat(symlinkFileAslash, &st)); CHECK_EQUAL(ENOENT, errno);
+ // errno = 0; CHECK_EQUAL(-1, stat(symlinkDirAslash, &st)); CHECK_EQUAL(ENOENT, errno);
+ errno = 0; CHECK_EQUAL_ZERO(stat(dirAslashd, &st)); CHECK_EQUAL_ZERO(errno); CHECK_TRUE(qcmp(st, dirA_st));
+ errno = 0; CHECK_EQUAL(-1, stat(fileAslashd, &st)); CHECK_EQUAL(ENOTDIR, errno);
+ // errno = 0; CHECK_EQUAL(-1, stat(symlinkFileAslashd, &st)); CHECK_EQUAL(ENOENT, errno);
+ // errno = 0; CHECK_EQUAL(-1, stat(symlinkDirAslashd, &st)); CHECK_EQUAL(ENOENT, errno);
+ errno = 0; CHECK_EQUAL_ZERO(stat(dirAslashdd, &st)); CHECK_EQUAL_ZERO(errno); CHECK_TRUE(qcmp(st, dir_st));
+ errno = 0; CHECK_EQUAL(-1, stat(fileAslashdd, &st)); CHECK_EQUAL(ENOTDIR, errno);
+ // errno = 0; CHECK_EQUAL(-1, stat(symlinkFileAslashdd, &st)); CHECK_EQUAL(ENOENT, errno);
+ // errno = 0; CHECK_EQUAL(-1, stat(symlinkDirAslashdd, &st)); CHECK_EQUAL(ENOENT, errno);
+ // clang-format on
+}
+
+TEST(FilesystemTests, InterMountRelations) {
+ Log();
+ Log("\t<<<< Intermount relations >>>>");
+ Log("\tPath resolution between mountpoints");
+ Log();
+
+ const char* dir_root = "/";
+ const char* dir_data = "/data";
+ const char* dir_data_s = "/data/";
+ const char* dir_data_sd = "/data/.";
+ const char* dir_data_sdd = "/data/..";
+
+ struct stat dir_st {};
+ struct stat dir_data_st {};
+ struct stat dir_data_s_st {};
+ struct stat dir_data_sd_st {};
+ struct stat dir_data_sdd_st {};
+ struct OrbisKernelStat dir_ost {};
+ struct OrbisKernelStat dir_data_ost {};
+ struct OrbisKernelStat dir_data_s_ost {};
+ struct OrbisKernelStat dir_data_sd_ost {};
+ struct OrbisKernelStat dir_data_sdd_ost {};
+
+ int fd;
+
+ auto qcmp = [](const struct stat& left, const struct stat& right) -> bool {
+ return memcmp(&left, &right, 24) == 0; // basically everything that matters
+ };
+
+ // clang-format off
+ errno = 0; CHECK_EQUAL_ZERO(stat(dir_root, &dir_st)); CHECK_EQUAL_ZERO(errno);
+ errno = 0; CHECK_EQUAL_ZERO(stat(dir_data, &dir_data_st)); CHECK_EQUAL_ZERO(errno);
+ errno = 0; CHECK_EQUAL_ZERO(stat(dir_data_s, &dir_data_s_st)); CHECK_EQUAL_ZERO(errno);
+ errno = 0; CHECK_EQUAL_ZERO(stat(dir_data_sd, &dir_data_sd_st)); CHECK_EQUAL_ZERO(errno);
+ errno = 0; CHECK_EQUAL_ZERO(stat(dir_data_sdd, &dir_data_sdd_st)); CHECK_EQUAL_ZERO(errno);
+
+ errno = 0; CHECK_EQUAL_ZERO(sceKernelStat(dir_root, &dir_ost)); CHECK_EQUAL_ZERO(errno);
+ errno = 0; CHECK_EQUAL_ZERO(sceKernelStat(dir_data, &dir_data_ost)); CHECK_EQUAL_ZERO(errno);
+ errno = 0; CHECK_EQUAL_ZERO(sceKernelStat(dir_data_s, &dir_data_s_ost)); CHECK_EQUAL_ZERO(errno);
+ errno = 0; CHECK_EQUAL_ZERO(sceKernelStat(dir_data_sd, &dir_data_sd_ost)); CHECK_EQUAL_ZERO(errno);
+ errno = 0; CHECK_EQUAL_ZERO(sceKernelStat(dir_data_sdd, &dir_data_sdd_ost)); CHECK_EQUAL_ZERO(errno);
+ // clang-format on
+
+ LogSuccess("stat");
+ Log(dir_root, "\t\t", dir_st.st_ino, dir_ost.st_ino);
+ Log(dir_data, "\t\t", dir_data_st.st_ino, dir_data_ost.st_ino);
+ Log(dir_data_s, "\t\t", dir_data_s_st.st_ino, dir_data_s_ost.st_ino);
+ Log(dir_data_sd, "\t\t", dir_data_sd_st.st_ino, dir_data_sd_ost.st_ino);
+ Log(dir_data_sdd, "\t\t", dir_data_sdd_st.st_ino, dir_data_sdd_ost.st_ino);
+
+ // clang-format off
+ errno = 0; fd = sceKernelOpen(dir_root, O_RDONLY, 0777); CHECK_COMPARE(0, <, fd); CHECK_EQUAL_ZERO(errno);
+ errno = 0; CHECK_EQUAL_ZERO(sceKernelFstat(fd, &dir_ost)); CHECK_EQUAL_ZERO(errno);
+ errno = 0; CHECK_EQUAL_ZERO(sceKernelClose(fd)); CHECK_EQUAL_ZERO(errno);
+ errno = 0; fd = sceKernelOpen(dir_data, O_RDONLY, 0777); CHECK_COMPARE(0, <, fd); CHECK_EQUAL_ZERO(errno);
+ errno = 0; CHECK_EQUAL_ZERO(sceKernelFstat(fd, &dir_data_ost)); CHECK_EQUAL_ZERO(errno);
+ errno = 0; CHECK_EQUAL_ZERO(sceKernelClose(fd)); CHECK_EQUAL_ZERO(errno);
+ errno = 0; fd = sceKernelOpen(dir_data_s, O_RDONLY, 0777); CHECK_COMPARE(0, <, fd); CHECK_EQUAL_ZERO(errno);
+ errno = 0; CHECK_EQUAL_ZERO(sceKernelFstat(fd, &dir_data_s_ost)); CHECK_EQUAL_ZERO(errno);
+ errno = 0; CHECK_EQUAL_ZERO(sceKernelClose(fd)); CHECK_EQUAL_ZERO(errno);
+ errno = 0; fd = sceKernelOpen(dir_data_sd, O_RDONLY, 0777); CHECK_COMPARE(0, <, fd); CHECK_EQUAL_ZERO(errno);
+ errno = 0; CHECK_EQUAL_ZERO(sceKernelFstat(fd, &dir_data_sd_ost)); CHECK_EQUAL_ZERO(errno);
+ errno = 0; CHECK_EQUAL_ZERO(sceKernelClose(fd)); CHECK_EQUAL_ZERO(errno);
+ errno = 0; fd = sceKernelOpen(dir_data_sdd, O_RDONLY, 0777); CHECK_COMPARE(0, <, fd); CHECK_EQUAL_ZERO(errno);
+ errno = 0; CHECK_EQUAL_ZERO(sceKernelFstat(fd, &dir_data_sdd_ost)); CHECK_EQUAL_ZERO(errno);
+ errno = 0; CHECK_EQUAL_ZERO(sceKernelClose(fd)); CHECK_EQUAL_ZERO(errno);
+
+ errno = 0; fd = open(dir_root, O_RDONLY, 0777); CHECK_COMPARE(0, <, fd); CHECK_EQUAL_ZERO(errno);
+ errno = 0; CHECK_EQUAL_ZERO(fstat(fd, &dir_st)); CHECK_EQUAL_ZERO(errno);
+ errno = 0; CHECK_EQUAL_ZERO(close(fd)); CHECK_EQUAL_ZERO(errno);
+ errno = 0; fd = open(dir_data, O_RDONLY, 0777); CHECK_COMPARE(0, <, fd); CHECK_EQUAL_ZERO(errno);
+ errno = 0; CHECK_EQUAL_ZERO(fstat(fd, &dir_data_st)); CHECK_EQUAL_ZERO(errno);
+ errno = 0; CHECK_EQUAL_ZERO(close(fd)); CHECK_EQUAL_ZERO(errno);
+ errno = 0; fd = open(dir_data_s, O_RDONLY, 0777); CHECK_COMPARE(0, <, fd); CHECK_EQUAL_ZERO(errno);
+ errno = 0; CHECK_EQUAL_ZERO(fstat(fd, &dir_data_s_st)); CHECK_EQUAL_ZERO(errno);
+ errno = 0; CHECK_EQUAL_ZERO(close(fd)); CHECK_EQUAL_ZERO(errno);
+ errno = 0; fd = open(dir_data_sd, O_RDONLY, 0777); CHECK_COMPARE(0, <, fd); CHECK_EQUAL_ZERO(errno);
+ errno = 0; CHECK_EQUAL_ZERO(fstat(fd, &dir_data_sd_st)); CHECK_EQUAL_ZERO(errno);
+ errno = 0; CHECK_EQUAL_ZERO(close(fd)); CHECK_EQUAL_ZERO(errno);
+ errno = 0; fd = open(dir_data_sdd, O_RDONLY, 0777); CHECK_COMPARE(0, <, fd); CHECK_EQUAL_ZERO(errno);
+ errno = 0; CHECK_EQUAL_ZERO(fstat(fd, &dir_data_sdd_st)); CHECK_EQUAL_ZERO(errno);
+ errno = 0; CHECK_EQUAL_ZERO(close(fd)); CHECK_EQUAL_ZERO(errno);
+ // clang-format on
+
+ LogSuccess("fstat");
+ Log(dir_root, "\t\t", dir_st.st_ino, dir_ost.st_ino);
+ Log(dir_data, "\t\t", dir_data_st.st_ino, dir_data_ost.st_ino);
+ Log(dir_data_s, "\t\t", dir_data_s_st.st_ino, dir_data_s_ost.st_ino);
+ Log(dir_data_sd, "\t\t", dir_data_sd_st.st_ino, dir_data_sd_ost.st_ino);
+ Log(dir_data_sdd, "\t\t", dir_data_sdd_st.st_ino, dir_data_sdd_ost.st_ino);
+
+ // clang-format off
+ errno = 0; CHECK_EQUAL_ZERO(sceKernelCheckReachability(dir_root)); CHECK_EQUAL_ZERO(errno);
+ errno = 0; CHECK_EQUAL_ZERO(sceKernelCheckReachability(dir_data)); CHECK_EQUAL_ZERO(errno);
+ errno = 0; CHECK_EQUAL(ORBIS_KERNEL_ERROR_ENOENT, sceKernelCheckReachability(dir_data_s)); CHECK_EQUAL_ZERO(errno);
+ errno = 0; CHECK_EQUAL_ZERO(sceKernelCheckReachability(dir_data_sd)); CHECK_EQUAL_ZERO(errno);
+ errno = 0; CHECK_EQUAL_ZERO(sceKernelCheckReachability(dir_data_sdd)); CHECK_EQUAL_ZERO(errno);
+ // clang-format on
+}
+
+TEST(FilesystemTests, DirectoryRelatives) {
+ // relatives only, i.e. [.] and [..]
+ Log();
+ Log("\t<<<< Dirent relatives (Therapist abridged) >>>>");
+ Log("\tHow dirents see relations with their parents");
+ Log();
+
+ /**
+ * What i think it is, is that it always looks for the beginning of the dirent.
+ * So if it would be truncated from the front, it reads it from the beginning
+ * There is a guarantee that all dirents will not be cut off
+ */
+
+ const char* dir_root = "/";
+ const char* dir_data = "/data";
+ const char* dir_data_s = "/data/";
+ const char* dir_data_sd = "/data/.";
+ const char* dir_data_sdd = "/data/..";
+
+ oi::FolderDirent dirent_root_self {};
+ oi::FolderDirent dirent_root_parent {};
+ oi::FolderDirent dirent_data_self {};
+ oi::FolderDirent dirent_data_parent {};
+ oi::FolderDirent dirent_data_s_self {};
+ oi::FolderDirent dirent_data_s_parent {};
+ oi::FolderDirent dirent_data_sd_self {};
+ oi::FolderDirent dirent_data_sd_parent {};
+ oi::FolderDirent dirent_data_sdd_self {};
+ oi::FolderDirent dirent_data_sdd_parent {};
+
+ int fd {};
+ s32 tbr {};
+ constexpr u32 buffer_size = 512;
+ constexpr u32 view_size = 48;
+ char buffer[buffer_size] {0};
+
+ auto quickprint = [vs = &view_size](std::string title, const void* array) -> void {
+ std::string out {title};
+ for (u32 idx = 0; idx < *vs; ++idx) {
+ if (!(idx % 12)) out += "\r\n\t\t\t\t\t\t";
+ auto hexed = to_hex(*(reinterpret_cast(array) + idx));
+ out += (hexed.length() == 1 ? "0" : "") + hexed + " ";
+ }
+ Log(out);
+ };
+
+ auto divide12 = [](char* buffer, oi::FolderDirent* self, oi::FolderDirent* parent) -> void {
+ memcpy(reinterpret_cast(self), buffer, 12);
+ memcpy(reinterpret_cast(parent), buffer + 12, 12);
+ };
+
+ // clang-format off
+ errno = 0; memset(buffer,0xAA,buffer_size); fd = sceKernelOpen(dir_root, O_RDONLY, 0777); CHECK_COMPARE(0, <, fd);
+ errno = 0; tbr = sceKernelGetdirentries(fd, buffer, buffer_size,nullptr); CHECK_EQUAL(180,tbr); CHECK_EQUAL_ZERO(errno);
+ quickprint("\t"+std::string{dir_root}, buffer); divide12(buffer, &dirent_root_self, &dirent_root_parent);
+ errno = 0; CHECK_EQUAL_ZERO(sceKernelClose(fd)); CHECK_EQUAL_ZERO(errno);
+
+ errno = 0; memset(buffer,0xAA,buffer_size); fd = sceKernelOpen(dir_data, O_RDONLY, 0777); CHECK_COMPARE(0, <, fd);
+ errno = 0; tbr = sceKernelGetdirentries(fd, buffer, buffer_size,nullptr); CHECK_EQUAL(512,tbr); CHECK_EQUAL_ZERO(errno);
+ quickprint("\t"+std::string{dir_data}, buffer);
+ errno = 0; CHECK_EQUAL_ZERO(sceKernelClose(fd)); CHECK_EQUAL_ZERO(errno);
+
+ errno = 0; memset(buffer,0xAA,buffer_size); fd = sceKernelOpen(dir_data_s, O_RDONLY, 0777); CHECK_COMPARE(0, <, fd);
+ errno = 0; tbr = sceKernelGetdirentries(fd, buffer, buffer_size,nullptr); CHECK_EQUAL(512,tbr); CHECK_EQUAL_ZERO(errno);
+ quickprint("\t"+std::string{dir_data_s}, buffer);
+ errno = 0; CHECK_EQUAL_ZERO(sceKernelClose(fd)); CHECK_EQUAL_ZERO(errno);
+
+ errno = 0; memset(buffer,0xAA,buffer_size); fd = sceKernelOpen(dir_data_sd, O_RDONLY, 0777); CHECK_COMPARE(0, <, fd);
+ errno = 0; tbr = sceKernelGetdirentries(fd, buffer, buffer_size,nullptr); CHECK_EQUAL(512,tbr); CHECK_EQUAL_ZERO(errno);
+ quickprint("\t"+std::string{dir_data_sd}, buffer);
+ errno = 0; CHECK_EQUAL_ZERO(sceKernelClose(fd)); CHECK_EQUAL_ZERO(errno);
+
+ errno = 0; memset(buffer,0xAA,buffer_size); fd = sceKernelOpen(dir_data_sdd, O_RDONLY, 0777); CHECK_COMPARE(0, <, fd);
+ errno = 0; tbr = sceKernelGetdirentries(fd, buffer, buffer_size,nullptr); CHECK_EQUAL(180, tbr); CHECK_EQUAL_ZERO(errno);
+ quickprint("\t"+std::string{dir_data_sdd}, buffer);
+ errno = 0; CHECK_EQUAL_ZERO(sceKernelClose(fd)); CHECK_EQUAL_ZERO(errno);
+ // clang-format on
+}
+
+TEST(FilesystemTests, PartialGetdirentries) {
+ // relatives only, i.e. [.] and [..]
+ Log();
+ Log("\t<<<< Dirent small read sizes >>>>");
+ Log("\tHow dirents see relations with their parents");
+ Log();
+
+ /**
+ * What i think it is, is that it always looks for the beginning of the dirent.
+ * So if it would be truncated from the front, it reads it from the beginning
+ * There is a guarantee that all dirents will not be cut off
+ */
+
+ const char* dir_test = "/data/therapist/partialdirents";
+ const char* dir_shortDir = "/data/therapist/partialdirents/d";
+ const char* dir_shortDir2 = "/data/therapist/partialdirents/ddddd";
+ const char* dir_shortFile = "/data/therapist/partialdirents/f";
+ const char* dir_shortFile2 = "/data/therapist/partialdirents/fffff";
+ const char* dir_shortFile3 = "/data/therapist/partialdirents/fffffffff";
+ const char* dir_shortDir3 = "/data/therapist/partialdirents/ddddddddd";
+
+ RegenerateDir(dir_test);
+ CHECK_EQUAL_ZERO(sceKernelMkdir(dir_shortDir, 0777));
+ CHECK_EQUAL_ZERO(sceKernelMkdir(dir_shortDir2, 0777));
+ CHECK_EQUAL_ZERO(touch(dir_shortFile));
+ CHECK_EQUAL_ZERO(sceKernelMkdir(dir_shortDir3, 0777));
+ CHECK_EQUAL_ZERO(touch(dir_shortFile2));
+ CHECK_EQUAL_ZERO(touch(dir_shortFile3));
+
+ int fd {};
+ s32 tbr {};
+ constexpr u32 buffer_size = 512;
+ constexpr u32 view_size = 48;
+ char buffer[buffer_size] {0};
+
+ auto quickprint = [vs = &view_size, bs = &buffer_size](std::string title, const void* array) -> void {
+ std::string out {title};
+ auto lim = (*vs) / 2;
+ for (u32 idx = 0; idx < lim; ++idx) {
+ if (!(idx % 12)) out += "\r\n\t\t\t\t\t\t";
+ auto hexed = to_hex(*(reinterpret_cast(array) + idx));
+ out += (hexed.length() == 1 ? "0" : "") + hexed + " ";
+ }
+ out += "\r\n\t\t\t\t\t\t----------";
+ for (u32 idx = 0; idx < lim; ++idx) {
+ if (!(idx % 12)) out += "\r\n\t\t\t\t\t\t";
+ auto hexed = to_hex(*(reinterpret_cast(array) + *bs - lim + idx));
+ out += (hexed.length() == 1 ? "0" : "") + hexed + " ";
+ }
+ Log(out);
+ };
+
+ // clang-format off
+ errno = 0; fd = sceKernelOpen(dir_test, O_RDONLY, 0777); CHECK_COMPARE(0, <, fd);
+
+ errno = 0; CHECK_EQUAL(0,sceKernelLseek(fd,0,0)); CHECK_EQUAL_ZERO(errno); memset(buffer,0xAA,buffer_size);
+ errno = 0; tbr = sceKernelGetdirentries(fd, buffer, buffer_size,nullptr); CHECK_EQUAL(512,tbr); CHECK_EQUAL_ZERO(errno);
+ quickprint("\tSTART+0:", buffer);
+ errno = 0; CHECK_EQUAL(8,sceKernelLseek(fd,8,0)); CHECK_EQUAL_ZERO(errno); memset(buffer,0xAA,buffer_size);
+ errno = 0; tbr = sceKernelGetdirentries(fd, buffer, buffer_size,nullptr); CHECK_EQUAL(504,tbr); CHECK_EQUAL_ZERO(errno);
+ quickprint("\tSTART+8:", buffer);
+ errno = 0; CHECK_EQUAL(11,sceKernelLseek(fd,11,0)); CHECK_EQUAL_ZERO(errno); memset(buffer,0xAA,buffer_size);
+ errno = 0; tbr = sceKernelGetdirentries(fd, buffer, buffer_size,nullptr); CHECK_EQUAL(501,tbr); CHECK_EQUAL_ZERO(errno);
+ quickprint("\tSTART+11:", buffer);
+ errno = 0; CHECK_EQUAL(12,sceKernelLseek(fd,12,0)); CHECK_EQUAL_ZERO(errno); memset(buffer,0xAA,buffer_size);
+ errno = 0; tbr = sceKernelGetdirentries(fd, buffer, buffer_size,nullptr); CHECK_EQUAL(500,tbr); CHECK_EQUAL_ZERO(errno);
+ quickprint("\tSTART+12:", buffer);
+ errno = 0; CHECK_EQUAL(13,sceKernelLseek(fd,13,0)); CHECK_EQUAL_ZERO(errno); memset(buffer,0xAA,buffer_size);
+ errno = 0; tbr = sceKernelGetdirentries(fd, buffer, buffer_size,nullptr); CHECK_EQUAL(499,tbr); CHECK_EQUAL_ZERO(errno);
+ quickprint("\tSTART+13:", buffer);
+ errno = 0; CHECK_EQUAL(23,sceKernelLseek(fd,23,0)); CHECK_EQUAL_ZERO(errno); memset(buffer,0xAA,buffer_size);
+ errno = 0; tbr = sceKernelGetdirentries(fd, buffer, buffer_size,nullptr); CHECK_EQUAL(489,tbr); CHECK_EQUAL_ZERO(errno);
+ quickprint("\tSTART+23:", buffer);
+ errno = 0; CHECK_EQUAL(24,sceKernelLseek(fd,24,0)); CHECK_EQUAL_ZERO(errno); memset(buffer,0xAA,buffer_size);
+ errno = 0; tbr = sceKernelGetdirentries(fd, buffer, buffer_size,nullptr); CHECK_EQUAL(488,tbr); CHECK_EQUAL_ZERO(errno);
+ quickprint("\tSTART+24:", buffer);
+ errno = 0; CHECK_EQUAL(25,sceKernelLseek(fd,25,0)); CHECK_EQUAL_ZERO(errno); memset(buffer,0xAA,buffer_size);
+ errno = 0; tbr = sceKernelGetdirentries(fd, buffer, buffer_size,nullptr); CHECK_EQUAL(487,tbr); CHECK_EQUAL_ZERO(errno);
+ quickprint("\tSTART+25:", buffer);
+ errno = 0; CHECK_EQUAL_ZERO(sceKernelClose(fd)); CHECK_EQUAL_ZERO(errno);
+ // clang-format on
+}
+
+TEST(FilesystemTests, TestDevSymlinks) {
+ Log();
+ Log("\t<<<< Symlink reachability and path resolution for /dev >>>>");
+ Log("\tThis is a supplement to FileResolutionTests");
+ Log("\tAlso, apparently nothing in /dev/should be accessible");
+ Log();
+
+ const char* dev_stdin = "/dev/stdin";
+ const char* dev_stdout = "/dev/stdout";
+ const char* dev_stderr = "/dev/stderr";
+ const char* dev_stdin_fd = "/dev/fd/0";
+ const char* dev_stdout_fd = "/dev/fd/1";
+ const char* dev_stderr_fd = "/dev/fd/2";
+
+ struct stat dev_stdin_st {};
+ struct stat dev_stdin_fd_st {};
+ struct stat dev_stdout_st {};
+ struct stat dev_stdout_fd_st {};
+ struct stat dev_stderr_st {};
+ struct stat dev_stderr_fd_st {};
+
+ struct OrbisKernelStat dev_stdin_ost {};
+ struct OrbisKernelStat dev_stdin_fd_ost {};
+ struct OrbisKernelStat dev_stdout_ost {};
+ struct OrbisKernelStat dev_stdout_fd_ost {};
+ struct OrbisKernelStat dev_stderr_ost {};
+ struct OrbisKernelStat dev_stderr_fd_ost {};
+
+ int fd;
+
+ // clang-format off
+ errno = 0; CHECK_EQUAL(ORBIS_KERNEL_ERROR_ENOENT, sceKernelCheckReachability(dev_stdin)); CHECK_EQUAL(ENOENT, errno);
+ errno = 0; CHECK_EQUAL(ORBIS_KERNEL_ERROR_ENOENT, sceKernelCheckReachability(dev_stdin_fd)); CHECK_EQUAL(ENOENT, errno);
+ errno = 0; CHECK_EQUAL(ORBIS_KERNEL_ERROR_ENOENT, sceKernelCheckReachability(dev_stdout)); CHECK_EQUAL(ENOENT, errno);
+ errno = 0; CHECK_EQUAL(ORBIS_KERNEL_ERROR_ENOENT, sceKernelCheckReachability(dev_stdout_fd)); CHECK_EQUAL(ENOENT, errno);
+ errno = 0; CHECK_EQUAL(ORBIS_KERNEL_ERROR_ENOENT, sceKernelCheckReachability(dev_stderr)); CHECK_EQUAL(ENOENT, errno);
+ errno = 0; CHECK_EQUAL(ORBIS_KERNEL_ERROR_ENOENT, sceKernelCheckReachability(dev_stderr_fd)); CHECK_EQUAL(ENOENT, errno);
+
+ errno = 0; CHECK_EQUAL(ORBIS_KERNEL_ERROR_ENOENT, sceKernelStat(dev_stdin, &dev_stdin_ost)); CHECK_EQUAL(ENOENT, errno);
+ errno = 0; CHECK_EQUAL(ORBIS_KERNEL_ERROR_ENOENT, sceKernelStat(dev_stdin_fd, &dev_stdin_fd_ost)); CHECK_EQUAL(ENOENT, errno);
+ errno = 0; CHECK_EQUAL(ORBIS_KERNEL_ERROR_ENOENT, sceKernelStat(dev_stdout, &dev_stdout_ost)); CHECK_EQUAL(ENOENT, errno);
+ errno = 0; CHECK_EQUAL(ORBIS_KERNEL_ERROR_ENOENT, sceKernelStat(dev_stdout_fd, &dev_stdout_fd_ost)); CHECK_EQUAL(ENOENT, errno);
+ errno = 0; CHECK_EQUAL(ORBIS_KERNEL_ERROR_ENOENT, sceKernelStat(dev_stderr, &dev_stderr_ost)); CHECK_EQUAL(ENOENT, errno);
+ errno = 0; CHECK_EQUAL(ORBIS_KERNEL_ERROR_ENOENT, sceKernelStat(dev_stderr_fd, &dev_stderr_fd_ost)); CHECK_EQUAL(ENOENT, errno);
+
+ errno = 0; fd = sceKernelOpen(dev_stdin, O_RDONLY, 0777); CHECK_EQUAL(ORBIS_KERNEL_ERROR_ENOENT, fd); CHECK_EQUAL(ENOENT, errno);
+ errno = 0; CHECK_EQUAL(ORBIS_KERNEL_ERROR_EBADF, sceKernelFstat(fd, &dev_stdin_ost)); CHECK_EQUAL(EBADF, errno);
+ errno = 0; CHECK_EQUAL(ORBIS_KERNEL_ERROR_EBADF, sceKernelClose(fd)); CHECK_EQUAL(EBADF, errno);
+ errno = 0; fd = sceKernelOpen(dev_stdin_fd, O_RDONLY, 0777); CHECK_EQUAL(ORBIS_KERNEL_ERROR_ENOENT, fd); CHECK_EQUAL(ENOENT, errno);
+ errno = 0; CHECK_EQUAL(ORBIS_KERNEL_ERROR_EBADF, sceKernelFstat(fd, &dev_stdin_fd_ost)); CHECK_EQUAL(EBADF, errno);
+ errno = 0; CHECK_EQUAL(ORBIS_KERNEL_ERROR_EBADF, sceKernelClose(fd)); CHECK_EQUAL(EBADF, errno);
+
+ errno = 0; fd = sceKernelOpen(dev_stdout, O_RDONLY, 0777); CHECK_EQUAL(ORBIS_KERNEL_ERROR_ENOENT, fd); CHECK_EQUAL(ENOENT, errno);
+ errno = 0; CHECK_EQUAL(ORBIS_KERNEL_ERROR_EBADF, sceKernelFstat(fd, &dev_stdout_ost)); CHECK_EQUAL(EBADF, errno);
+ errno = 0; CHECK_EQUAL(ORBIS_KERNEL_ERROR_EBADF, sceKernelClose(fd)); CHECK_EQUAL(EBADF, errno);
+ errno = 0; fd = sceKernelOpen(dev_stdout_fd, O_RDONLY, 0777); CHECK_EQUAL(ORBIS_KERNEL_ERROR_ENOENT, fd); CHECK_EQUAL(ENOENT, errno);
+ errno = 0; CHECK_EQUAL(ORBIS_KERNEL_ERROR_EBADF, sceKernelFstat(fd, &dev_stdout_fd_ost)); CHECK_EQUAL(EBADF, errno);
+ errno = 0; CHECK_EQUAL(ORBIS_KERNEL_ERROR_EBADF, sceKernelClose(fd)); CHECK_EQUAL(EBADF, errno);
+
+ errno = 0; fd = sceKernelOpen(dev_stderr, O_RDONLY, 0777); CHECK_EQUAL(ORBIS_KERNEL_ERROR_ENOENT, fd); CHECK_EQUAL(ENOENT, errno);
+ errno = 0; CHECK_EQUAL(ORBIS_KERNEL_ERROR_EBADF, sceKernelFstat(fd, &dev_stderr_ost)); CHECK_EQUAL(EBADF, errno);
+ errno = 0; CHECK_EQUAL(ORBIS_KERNEL_ERROR_EBADF, sceKernelClose(fd)); CHECK_EQUAL(EBADF, errno);
+ errno = 0; fd = sceKernelOpen(dev_stderr_fd, O_RDONLY, 0777); CHECK_EQUAL(ORBIS_KERNEL_ERROR_ENOENT, fd); CHECK_EQUAL(ENOENT, errno);
+ errno = 0; CHECK_EQUAL(ORBIS_KERNEL_ERROR_EBADF, sceKernelFstat(fd, &dev_stderr_fd_ost)); CHECK_EQUAL(EBADF, errno);
+ errno = 0; CHECK_EQUAL(ORBIS_KERNEL_ERROR_EBADF, sceKernelClose(fd)); CHECK_EQUAL(EBADF, errno);
+
+
+ errno = 0; CHECK_EQUAL(-1, stat(dev_stdin, &dev_stdin_st)); CHECK_EQUAL(ENOENT, errno);
+ errno = 0; CHECK_EQUAL(-1, stat(dev_stdin_fd, &dev_stdin_fd_st)); CHECK_EQUAL(ENOENT, errno);
+ errno = 0; CHECK_EQUAL(-1, stat(dev_stdout, &dev_stdout_st)); CHECK_EQUAL(ENOENT, errno);
+ errno = 0; CHECK_EQUAL(-1, stat(dev_stdout_fd, &dev_stdout_fd_st)); CHECK_EQUAL(ENOENT, errno);
+ errno = 0; CHECK_EQUAL(-1, stat(dev_stderr, &dev_stderr_st)); CHECK_EQUAL(ENOENT, errno);
+ errno = 0; CHECK_EQUAL(-1, stat(dev_stderr_fd, &dev_stderr_fd_st)); CHECK_EQUAL(ENOENT, errno);
+
+ errno = 0; CHECK_EQUAL(-1, lstat(dev_stdin, &dev_stdin_st)); CHECK_EQUAL(EPERM, errno);
+ errno = 0; CHECK_EQUAL(-1, lstat(dev_stdin_fd, &dev_stdin_fd_st)); CHECK_EQUAL(EPERM, errno);
+ errno = 0; CHECK_EQUAL(-1, lstat(dev_stdout, &dev_stdout_st)); CHECK_EQUAL(EPERM, errno);
+ errno = 0; CHECK_EQUAL(-1, lstat(dev_stdout_fd, &dev_stdout_fd_st)); CHECK_EQUAL(EPERM, errno);
+ errno = 0; CHECK_EQUAL(-1, lstat(dev_stderr, &dev_stderr_st)); CHECK_EQUAL(EPERM, errno);
+ errno = 0; CHECK_EQUAL(-1, lstat(dev_stderr_fd, &dev_stderr_fd_st)); CHECK_EQUAL(EPERM, errno);
+
+ errno = 0; fd = open(dev_stdin, O_RDONLY, 0777); CHECK_EQUAL(-1, fd); CHECK_EQUAL(ENOENT, errno);
+ errno = 0; CHECK_EQUAL(-1, fstat(fd, &dev_stdin_st)); CHECK_EQUAL(EBADF, errno);
+ errno = 0; CHECK_EQUAL(-1, close(fd)); CHECK_EQUAL(EBADF, errno);
+ errno = 0; fd = open(dev_stdin_fd, O_RDONLY, 0777); CHECK_EQUAL(-1, fd); CHECK_EQUAL(ENOENT, errno);
+ errno = 0; CHECK_EQUAL(-1, fstat(fd, &dev_stdin_fd_st)); CHECK_EQUAL(EBADF, errno);
+ errno = 0; CHECK_EQUAL(-1, close(fd)); CHECK_EQUAL(EBADF, errno);
+
+ errno = 0; fd = open(dev_stdout, O_RDONLY, 0777); CHECK_EQUAL(-1, fd); CHECK_EQUAL(ENOENT, errno);
+ errno = 0; CHECK_EQUAL(-1, fstat(fd, &dev_stdout_st)); CHECK_EQUAL(EBADF, errno);
+ errno = 0; CHECK_EQUAL(-1, close(fd)); CHECK_EQUAL(EBADF, errno);
+ errno = 0; fd = open(dev_stdout_fd, O_RDONLY, 0777); CHECK_EQUAL(-1, fd); CHECK_EQUAL(ENOENT, errno);
+ errno = 0; CHECK_EQUAL(-1, fstat(fd, &dev_stdout_fd_st)); CHECK_EQUAL(EBADF, errno);
+ errno = 0; CHECK_EQUAL(-1, close(fd)); CHECK_EQUAL(EBADF, errno);
+
+ errno = 0; fd = open(dev_stderr, O_RDONLY, 0777); CHECK_EQUAL(-1, fd); CHECK_EQUAL(ENOENT, errno);
+ errno = 0; CHECK_EQUAL(-1, fstat(fd, &dev_stderr_st)); CHECK_EQUAL(EBADF, errno);
+ errno = 0; CHECK_EQUAL(-1, close(fd)); CHECK_EQUAL(EBADF, errno);
+ errno = 0; fd = open(dev_stderr_fd, O_RDONLY, 0777); CHECK_EQUAL(-1, fd); CHECK_EQUAL(ENOENT, errno);
+ errno = 0; CHECK_EQUAL(-1, fstat(fd, &dev_stderr_fd_st)); CHECK_EQUAL(EBADF, errno);
+ errno = 0; CHECK_EQUAL(-1, close(fd)); CHECK_EQUAL(EBADF, errno);
+ // clang-format on
+}
+
+void RunTests() {
+
+ Log();
+ Log("<<<< TEST SUITE STARTING >>>>");
+ Log("\tSome test components may (and will) fail. This is expected.");
+ Log("\tValidity of the test is determined by last message emitted by test case.");
+ Log();
+
+ Log();
+ Log("\t<<<< DUMP DIRENTS >>>>");
+ Log();
+ dumpDirRecursive("/app0");
+
+ //
+
+ Log();
+ Log("\t<<<< RELATIVE FILENO >>>>");
+ Log();
+ //
+ // fileno=0 is *always* reserved for removed/nonexistent files
+ // fileno=1 is *always* reserved for the superblock partitions
+ // fileno=2 is *always* reserved for mount-root partitions
+ TEST_CASE(TestRelatives("/"), "Test complete. Expected values: ~700, 3, -2", "Can't test relatives of /");
+ TEST_CASE(TestRelatives("/app0", true), "Test complete", "Can't test relatives of /app0");
+ TEST_CASE(TestRelatives("/app0/sce_sys"), "Test complete", "Can't test relatives of /app0/sce_sys");
+ TEST_CASE(TestRelatives("/av_contents"), "Test complete", "Can't test relatives of /av_contents");
+ TEST_CASE(TestRelatives("/data", true), "Test complete", "Can't test relatives of /data/therapist");
+ TEST_CASE(!TestRelatives("/dev"), "Test complete. Expected values: -2, -2, ~800", "/dev should NOT be accessible");
+
+ TEST_CASE(TestRelatives("/host", true), "/host is a superblock partition. Expected values: 9, 1, ~700", "Can't test relatives of /host");
+ TEST_CASE(TestRelatives("/hostapp", true), "/hostapp is a superblock partition. Expected values: 10, 1, ~700", "Can't test relatives of /hostapp");
+
+ TEST_CASE(TestRelatives("/system_tmp", true), "Test complete", "Can't test relatives of /system_tmp");
+ TEST_CASE(!TestRelatives("/this_should_fail"), "Test complete", "Accessed nonexistent directory");
+
+ //
+
+ Log();
+ Log("\t<<<< NORMAL AND PFS DIRENT >>>>");
+ Log("\tNormal dirents are on LHS, PFS is on RHS.");
+ Log("\tThe last element of the path is the accessed dirent,");
+ Log("\tso it can refer to a file, directory or relative entry [ . ], [ .. ]");
+ Log();
+ //
+ // PFS works only with /app0
+ // Also, don't try to open /host with PFS
+ TEST_CASE(!CompareNormalVsPFS("/", "."), "Test complete [PFS should fail]", "Cannot access [ . ] at [ / ]");
+ TEST_CASE(!CompareNormalVsPFS("/", "app0"), "Test complete [PFS should fail]", "Cannot access [ app0 ] at [ / ]");
+ TEST_CASE(!CompareNormalVsPFS("/", "data"), "Test complete [PFS should fail]", "Cannot access [ data ] at [ / ]");
+ TEST_CASE(CompareNormalVsPFS("/app0", "."), "Test complete", "Cannot access [ . ] at [ /app0 ]");
+ TEST_CASE(CompareNormalVsPFS("/app0", ".."), "Test complete", "Cannot access [ .. ] at [ /app0 ]");
+ TEST_CASE(CompareNormalVsPFS("/app0", "sce_sys"), "Test complete", "Cannot access [ sce_sys ] at [ /app0 ]");
+ TEST_CASE(CompareNormalVsPFS("/app0", "eboot.bin"), "Test complete", "Cannot access [ eboot.bin ] at [ /app0 ]");
+ TEST_CASE(!CompareNormalVsPFS("/data/therapist", "."), "Test complete [PFS should fail]", "Cannot access [ . ] at [ /data/therapist ]");
+ TEST_CASE(!CompareNormalVsPFS("/this_should_fail", "."), "Test complete [All should fail]", "Accessed [ . ] at [ /this_should_fail ]");
+
+ //
+
+ Log();
+ Log("\t<<<< Example directory listings >>>>");
+ Log("\t This is made to mimic `ls -la`.");
+ Log("\t UID, GID are always 0");
+ Log();
+
+ ElEsDashElAy("/");
+ ElEsDashElAy("/app0");
+
+ //
+ // Dirents
+ //
+
+ Log();
+ Log("\t<<<< DIRENTS >>>>");
+ Log();
+
+ bool dirent_prepared = RegenerateDir("/data/therapist/tmp_dirent");
+ TEST_CASE(dirent_prepared, "Prepared for dirents", "Can't setup dirents");
+ if (dirent_prepared) {
+ TEST_CASE(TestDirEnts(), "Test complete", "You won't see this, this test doesn't have a negative return");
+ }
+
+ //
+ // Stat
+ //
+
+ //
+ // CURSED FILE CREATION
+ //
+
+ Log();
+ Log("\t<<<< CURSED FILE CREATION >>>>");
+ Log();
+
+ bool cursed_fileop_prepared = PrepareCursedFileop();
+ TEST_CASE(cursed_fileop_prepared, "Prepared for cursed fileop", "Can't setup cursed fileops");
+ if (cursed_fileop_prepared) {
+ TEST_CASE(TestFileTouch("/data/therapist/tmp_cursed/Aursed/AAursed/a_aa_file.txt"), "Test complete", "Test failed");
+ TEST_CASE(TestFileTouch("/data/therapist/tmp_cursed/Aursed/a_file.txt"), "Test complete", "Test failed");
+ TEST_CASE(TestFileTouch("/data/therapist/tmp_cursed/Aursed/././a_d_d_file.txt"), "Test complete", "Test failed");
+ TEST_CASE(TestFileTouch("/data/therapist/tmp_cursed/Bursed/../Aursed/AAursed/b_dd_a_aa_file.txt"), "Test complete", "Test failed");
+ TEST_CASE(TestFileTouch("/data/therapist/tmp_cursed/Aursed/AAursed/../../Cursed/../Bursed/aa_dd_dd_c_dd_b_file.txt"), "Test complete", "Test failed");
+ TEST_CASE(TestFileTouch("/data/therapist/tmp_cursed/Aursed/AAursed/../../Cursed/CCursed/../../Bursed/BBursed/a_aa_dd_dd_c_cc_dd_dd_b_bb_file.txt"),
+ "Test complete", "Test failed");
+ Log("errno for tests below should equal 9 (EBADF) and 2 (ENOENT)");
+ TEST_CASE(!TestFileTouch("/data/therapist/tmp_cursed/../tmp_cursed/../../././data/therapist/../data/therapist/././tmp_cursed/Cursed/../../../data/"
+ "therapist/tmp_cursed/Cursed/idfk.txt"),
+ "Test complete", "Test failed");
+ Log("errno for tests below should equal 9 (EBADF) and 22 (EINVAL)");
+ TEST_CASE(!TestFileTouch("../../../data/therapist/tmp_cursed/escape_from_app0_file.txt"), "Test complete: Can't", "Test failed: Can",
+ "escape from curdir with relatives");
+ TEST_CASE(!TestFileTouch("app0_file.txt"), "Test complete: File not", "Test failed: File", "written to (RO?) curdir");
+ }
+
+ //
+ // File ops tests
+ //
+
+ Log();
+ Log("\t<<<< File ops tests >>>>");
+ Log();
+
+ bool file_op_tests_prepared = RegenerateDir("/data/therapist/tmp_rw2"); // the same conditions
+ if (file_op_tests_prepared) {
+ // short test, just depends on target location. the output is looong, don't get overboard
+ TEST_CASE(!TestFileOps(""), "Pass", "Fail", "[open() should fail with errno = 22]");
+ TEST_CASE(!TestFileOps("/app0/assets/misc/test.txt"), "Pass", "Fail", "[open should fail with errno = 30]");
+ TEST_CASE(TestFileOps("/data/therapist/tmp_rw2/test.txt"), "Pass", "Fail");
+ // a true trial. should fail immediately :)
+ // TEST(TestFileOps("/app0/sce_sys/param.sfo", 0, "[No flags]"), "Pass", "Fail");
+ }
+
+ //
+ // File R/W tests
+ //
+
+ Log();
+ Log("\t<<<< File R/W tests >>>>");
+ Log();
+
+ bool file_rw_tests_prepared = RegenerateDir("/data/therapist/tmp_rw3"); // the same conditions
+ if (file_rw_tests_prepared) {
+ TEST_CASE(!TestFileRW("", 32), "Test complete", "Test failed", "[empty path, should fail with errno = 22 (EINVAL)]");
+ touch("/data/therapist/tmp_rw3/rwtest.txt");
+ TEST_CASE(TestFileRW("/data/therapist/tmp_rw3/rwtest.txt", 32), "Test complete", "Test failed", "[both buffers should hold the same values]");
+ TEST_CASE(!TestFileRW("/data/therapist/tmp_rw3", 32), "Test complete:", "Test failed:", "[R/W on a directory should fail with errno = 21 (EISDIR)]");
+ TEST_CASE(!TestFileRW("/app0/assets/misc/file_empty.txt", 32),
+ "Test complete:", "Test failed:", "[R/W on a file in RO directory should fail with errno = 30 (EROFS)]");
+
+ TEST_CASE(!TestFileRW("/dev/stdin", 32), "Test complete", "Test failed", "[Should fail with errno = 2 (ENOENT)]");
+ TEST_CASE(!TestFileRW("/dev/stdout", 32), "Test complete", "Test failed", "[Should fail with errno = 2 (ENOENT)]");
+ TEST_CASE(!TestFileRW("/dev/null", 32), "Test complete", "Test failed", "[Write should pass, read should return 0 bytes]");
+ TEST_CASE(TestFileRW("/dev/random", 32), "Test complete", "Test failed", "[All should pass, random reads]");
+ TEST_CASE(TestFileRW("/dev/urandom", 32), "Test complete", "Test failed", "[All should pass, random reads]");
+ TEST_CASE(TestFileRW("/dev/zero", 32), "Test complete", "Test failed", "[All should pass, read buffer zeroed out]");
+ }
+
+ RegenerateDir("/data/therapist/tmd");
+ for (u16 idx = 0; idx < 16; idx++) {
+ std::string p = std::string("/data/therapist/tmd/AFileWithAReallyLongName-") + std::to_string(idx);
+ touch(p.c_str());
+ }
+ for (u16 idx = 0; idx < 64; idx++) {
+ std::string p = std::string("/data/therapist/tmd/SN-") + std::to_string(idx);
+ touch(p.c_str());
+ }
+ dumpDirRecursive("/data/therapist/tmd");
+
+ ///
+ /// Case sensitivity
+ ///
+
+ Log();
+ Log("\t<<<< Case sensitivity tests >>>>");
+ Log();
+
+ struct stat st;
+ const char* case_insensitive_path = "/data/therapist/cAsEinSenSiTive.hwdp";
+ const char* case_insensitive_path_lower = "/data/therapist/caseinsensitive.hwdp";
+ const char* case_insensitive_path_upper = "/DATA/THERAPIST/CASEINSENSITIVE.HWDP";
+ const char* case_insensitive_path_upper_end = "/data/THERAPIST/CASEINSENSITIVE.HWDP";
+ TEST_CASE(sceKernelClose(sceKernelOpen(case_insensitive_path, O_RDWR | O_TRUNC | O_CREAT, 0777)) == 0, "Test file created", "Test file not created");
+
+ TEST_CASE(stat(case_insensitive_path, &st) == 0, "Data: 1:1 case sensitivity passed", "Data: Can't resolve 1:1 name", "( ", case_insensitive_path, " )");
+ TEST_CASE(stat(case_insensitive_path_lower, &st) != 0 && errno == ENOENT, "Data: Data: Lowercase sensitivity passed", "Data: Resolved name in lowercase",
+ "( ", case_insensitive_path_lower, " )");
+ TEST_CASE(stat(case_insensitive_path_upper, &st) != 0 && errno == ENOENT, "Data: Uppercase sensitivity passed", "Data: Resolved name in uppercase", "( ",
+ case_insensitive_path_upper, " )");
+ TEST_CASE(stat(case_insensitive_path_upper_end, &st) != 0 && errno == ENOENT, "Data: Uppercase sensitivity (2nd half) passed",
+ "Data: Resolved name (2nd half) in uppercase", "( ", case_insensitive_path_upper_end, " )");
+
+ const char* case_insensitive_app0_path = "/app0/assets/misc/cAsEinSEnsITiVE.HwDp";
+ const char* case_insensitive_path_app0_lower = "/app0/assets/misc/caseinsensitive.hwdp";
+ const char* case_insensitive_path_app0_upper = "/APP0/ASSETS/misc/CASEINSENSITIVE.HWDP";
+ const char* case_insensitive_path_app0_upper_end = "/app0/ASSETS/misc/CASEINSENSITIVE.HWDP";
+ TEST_CASE(stat(case_insensitive_app0_path, &st) == 0, "app0: 1:1 case sensitivity passed", "app0: Can't resolve 1:1 name", "( ", case_insensitive_app0_path,
+ " )");
+ TEST_CASE(stat(case_insensitive_path_app0_lower, &st) == 0, "app0: Data: Lowercase sensitivity passed", "app0: Can't resolve name in lowercase", "( ",
+ case_insensitive_path_app0_lower, " )");
+ TEST_CASE(stat(case_insensitive_path_app0_upper, &st) != 0 && errno == ENOENT, "app0: Uppercase (whole path) sensitivity passed",
+ "app0: Resolved (whole path) name in uppercase", "( ", case_insensitive_path_app0_upper, " )");
+ TEST_CASE(stat(case_insensitive_path_app0_upper_end, &st) == 0, "app0: Uppercase (app0 path) sensitivity passed",
+ "app0: Can't resolve (app0 path) name in uppercase", "( ", case_insensitive_path_app0_upper_end, " )");
+
+ ///
+ /// Long names (ENAMETOOLONG)
+ ///
+
+ Log();
+ Log("\tLong names (ENAMETOOLONG)");
+ Log();
+
+ sceKernelClose(sceKernelOpen("/data/therapist/dummy_target", O_CREAT | O_WRONLY, 0777));
+ OrbisKernelStat st_long_orbis {};
+ struct stat st_long_posix {};
+
+ const char* very_long_path = "/data/therapist/"
+ "thisisafilewithaverylongnameForrealthisfileissupposedtohaveareallylongnameforthistestcaseOtherwisewewontknowifitworkscorrec"
+ "tlyItsnotusedoftenbutcanbepro"
+ "blematicasthisbreaksdirentswhichcanstoreonly255charactersincludingnullterminatorThisisthelastsentence.goodluck";
+ // sceKernel*
+ TEST_CASE(int status = sceKernelOpen(very_long_path, O_RDONLY, 0777); errno == ENAMETOOLONG, "File name too long detected",
+ "Didn't detect file name >255 characters", "sceKernelOpen(RO) ( errno =", errno,
+ ", should be", ENAMETOOLONG, ")");
+ TEST_CASE(int status = sceKernelOpen(very_long_path, O_WRONLY | O_RDWR | O_RDONLY, 0777);
+ errno == EINVAL, "Cursed rw flags are more important than ENAMETOOLONG", "Didn't detect file name >255 characters",
+ "sceKernelOpen(RDO|WRO|RW) ( errno =", errno, ", should be", EINVAL, ")");
+ TEST_CASE(int status = sceKernelOpen(very_long_path, O_CREAT | O_RDONLY, 0777);
+ errno == ENAMETOOLONG, "File creation flags are less important than ENAMETOOLONG", "Didn't detect file name >255 characters",
+ "sceKernelOpen(CREAT|RDO) ( errno =", errno, ", should be", ENAMETOOLONG, ")");
+ TEST_CASE(int status = sceKernelRename(very_long_path, "/data/therapist/dummy_target_2");
+ errno == ENAMETOOLONG, "File name too long detected", "Didn't detect file name >255 characters", "sceKernelRename(long,normal) ( errno =", errno,
+ ", should be", ENAMETOOLONG, ")");
+ TEST_CASE(int status = sceKernelRename("/data/therapist/dummy_target", very_long_path);
+ errno == ENAMETOOLONG, "File name too long detected", "Didn't detect file name >255 characters", "sceKernelRename(normal,long) ( errno =", errno,
+ ", should be", ENAMETOOLONG, ")");
+ TEST_CASE(int status = sceKernelCheckReachability(very_long_path); errno == ENAMETOOLONG, "File name too long detected",
+ "Didn't detect file name >255 characters", "sceKernelCheckReachability() ( errno =", errno,
+ ", should be", ENAMETOOLONG, ")");
+ TEST_CASE(int status = sceKernelMkdir(very_long_path, 0777); errno == ENAMETOOLONG, "File name too long detected", "Didn't detect file name >255 characters ",
+ "sceKernelMkdir() ( errno =", errno, ", should be", ENAMETOOLONG, ")");
+
+ TEST_CASE(int status = sceKernelStat(very_long_path, &st_long_orbis); errno == ENAMETOOLONG, "File name too long detected",
+ "Didn't detect file name >255 characters", "sceKernelStat() ( errno =", errno,
+ ", should be", ENAMETOOLONG, ")");
+ TEST_CASE(int status = sceKernelUnlink(very_long_path); errno == ENAMETOOLONG, "File name too long detected", "Didn't detect file name >255 characters",
+ "sceKernelUnlink() ( errno =", errno, ", should be", ENAMETOOLONG, ")");
+
+ // posix_*
+ TEST_CASE(int status = open(very_long_path, O_RDONLY, 0777); errno == ENAMETOOLONG, "File name too long detected", "Didn't detect file name >255 characters ",
+ "open(RO) ( errno =", errno, ", should be", ENAMETOOLONG, ")");
+ TEST_CASE(int status = open(very_long_path, O_WRONLY | O_RDWR | O_RDONLY, 0777); errno == EINVAL, "Cursed rw flags are more important than ENAMETOOLONG",
+ "Didn't detect file name >255 characters",
+ "open(RDO|WRO|RW) ( errno =", errno, ", should be", EINVAL, ")");
+ TEST_CASE(int status = open(very_long_path, O_CREAT | O_RDONLY, 0777); errno == ENAMETOOLONG, "File creation flags are less important than ENAMETOOLONG",
+ "Didn't detect file name >255 characters", "open(CREAT|RDO) ( errno =", errno,
+ ", should be", ENAMETOOLONG, ")");
+ TEST_CASE(int status = rename(very_long_path, "/data/therapist/dummy_target_2"); errno == ENAMETOOLONG, "File name too long detected",
+ "Didn't detect file name >255 characters",
+ "rename(long,normal) ( errno =", errno, ", should be", ENAMETOOLONG, ")");
+ TEST_CASE(int status = rename("/data/therapist/dummy_target", very_long_path); errno == ENAMETOOLONG, "File name too long detected",
+ "Didn't detect file name >255 characters",
+ "rename(normal,long) ( errno =", errno, ", should be", ENAMETOOLONG, ")");
+ TEST_CASE(int status = mkdir(very_long_path, 0777); errno == ENAMETOOLONG, "File name too long detected", "Didn't detect file name >255 characters",
+ "mkdir() ( errno =", errno, ", should be", ENAMETOOLONG, ")");
+ TEST_CASE(int status = stat(very_long_path, &st_long_posix); errno == ENAMETOOLONG, "File name too long detected", "Didn't detect file name >255 characters ",
+ "stat() ( errno =", errno, ", should be", ENAMETOOLONG, ")");
+ TEST_CASE(int status = unlink(very_long_path); errno == ENAMETOOLONG, "File name too long detected", "Didn't detect file name >255 characters",
+ "unlink() ( errno =", errno, ", should be", ENAMETOOLONG, ")");
+}
+
+bool TestFileOps(const char* path) {
+ LogTest("Testing file operations on [", path, "]");
+ OrbisKernelStat st {};
+ int _errno = 0;
+ int fd = -1;
+ // shhh, don't spoil it yet
+ if (sceKernelStat(path, &st) > -1) sceKernelUnlink(path);
+
+ errno = 0;
+ TEST_CASE(sceKernelStat(path, &st) < 0, "Stat failed on nonexistent file", "Stat'd nonexistent file", "( errno =", errno, ")");
+ errno = 0;
+ TEST_CASE(sceKernelTruncate(path, 0) < 0, "Truncate to 0 failed on nonexistent file", "Truncated nonexistent file to 0", "( errno =", errno, ")");
+ errno = 0;
+ TEST_CASE(sceKernelTruncate(path, 10) < 0, "Truncate to 10 failed on nonexistent file", "Truncated nonexistent file to 10", "( errno =", errno, ")");
+
+ errno = 0;
+ TEST_CASE(fd = sceKernelOpen(path, 0x2 | 0x200, 0777); fd > -1, "File opened", "Can't open file", "[", path, "]", "( errno =", errno, ")");
+ if (fd < 0) return false;
+
+ // expand to 10 characters
+ errno = 0;
+ TEST_CASE(sceKernelFtruncate(fd, 10) == 0, "File expanded", "File not expanded", "( errno =", errno, ")");
+ errno = 0;
+ // new size
+ TEST_CASE(int news = GetSize(fd); news == 10, "File resized", "File not resized", "(current size:", news, "should be:", 10, ") ( errno =", errno, ")");
+ errno = 0;
+ // truncating up doesn't change file ptr
+ TEST_CASE(int newp = sceKernelLseek(fd, 0, 1); newp == 0, "ptr is valid", "ptr is invalid", "(lseek is", newp, "should be", 0, ") ( errno =", errno, ")");
+
+ char readbuffer[256];
+
+ const char teststr[] = "If you can read this, unused gibberish";
+ auto teststr_len = strlen(teststr);
+
+ // write test string
+ errno = 0;
+ TEST_CASE(int bw = sceKernelWrite(fd, teststr, teststr_len);
+ bw == teststr_len, "Write successful", "Write failed", "(Written:", bw, ") should write", teststr_len, "( errno =", errno, ")");
+ // check ptr after writing
+ errno = 0;
+ TEST_CASE(int curp = sceKernelLseek(fd, 0, 1);
+ curp == teststr_len, "ptr is valid", "ptr is invalid", "(lseek is", curp, "should be:", teststr_len, ") ( errno =", errno, ")");
+ // return to origin
+ errno = 0;
+ TEST_CASE(int curp = sceKernelLseek(fd, 0, 0); curp == 0, "ok:", "fail:", "origin+0 (lseek is", curp, "should be:", 0, ") ( errno =", errno, ")");
+ errno = 0;
+ memset(readbuffer, 0, 256);
+ TEST_CASE(int br = sceKernelRead(fd, readbuffer, 256);
+ br == teststr_len, "Read successful", "Read failed", "(Read:", br, "should read:", teststr_len, ") ( errno =", errno, ")");
+ Log("\t", readbuffer);
+ errno = 0;
+ // check lseek after reading
+ TEST_CASE(int curp = sceKernelLseek(fd, 0, 1);
+ curp == teststr_len, "ptr is valid", "ptr is invalid", "(lseek is", curp, "should be:", teststr_len, ") ( errno =", errno, ")");
+
+ // truncate to save only the beginning
+ errno = 0;
+ TEST_CASE(sceKernelFtruncate(fd, 20) == 0, "File truncated", "File not truncated", "( errno =", errno, ")");
+ errno = 0;
+ TEST_CASE(int news = GetSize(path); news == 20, "File resized", "File not resized", "(current size:", news, "should be:", 20, ") ( errno =", errno, ")");
+ errno = 0;
+ TEST_CASE(int newp = sceKernelLseek(fd, 0, 1); newp == 38, "file pointer not changed after resizing", "file ptr changed after resizing", "(lseek is", newp,
+ "should be", 38, ") ( errno =", errno, ")");
+
+ // overwrite 2nd half of the string
+ const char teststr2[] = "xxxxxxxxxxxxxxxxxxxx, remember to drink some water. This is saved for later.";
+ auto teststr2_len = strlen(teststr2);
+ errno = 0;
+ // lseek to the end of the file
+ TEST_CASE(int newp = sceKernelLseek(fd, 0, 2); newp == 20, "ok:", "fail:", "end+0 (lseek is", newp, "should be", 20, ") ( errno =", errno, ")");
+ errno = 0;
+ // write the other half
+ TEST_CASE(int bw = sceKernelWrite(fd, teststr2 + 20, teststr2_len - 20); bw == teststr2_len - 20, "2-nd write successful", "2-nd write failed",
+ "(Written:", bw, ") should write", teststr2_len - 20, "( errno =", errno, ")");
+ errno = 0;
+ // good advice
+ TEST_CASE(int curp = sceKernelLseek(fd, 0, 0); curp == 0, "ok:", "fail:", "origin+0 (lseek is", curp, "should be:", 0, ") ( errno =", errno, ")");
+ errno = 0;
+ memset(readbuffer, 0, 256);
+ TEST_CASE(int br = sceKernelRead(fd, readbuffer, 51);
+ br == 51, "Read successful", "Read failed", "(Read:", br, "should read:", 51, ") ( errno =", errno, ")");
+ Log("\t", readbuffer);
+ // last element
+ errno = 0;
+ TEST_CASE(int curp = sceKernelLseek(fd, -24, 2); curp == 52, "ok:", "fail:", "end-24 (lseek is", curp, "should be:", 52, ") ( errno =", errno, ")");
+ errno = 0;
+ memset(readbuffer, 0, 256);
+ TEST_CASE(int br = sceKernelRead(fd, readbuffer, 256);
+ br == 24, "Read successful", "Read failed", "(Read:", br, "should read:", 24, ") ( errno =", errno, ")");
+ Log("\t", readbuffer);
+
+ // random stuff
+ // drink
+ errno = 0;
+ sceKernelLseek(fd, 0, 0);
+ TEST_CASE(int curp = sceKernelLseek(fd, 34, 1); curp == 34, "ok:", "fail:", "current+34 (lseek is", curp, "should be:", 34, ") ( errno =", errno, ")");
+ memset(readbuffer, 0, 256);
+ TEST_CASE(int br = sceKernelRead(fd, readbuffer, 5); br == 5, "Read successful", "Read failed", "(Read:", br, "should read:", 5, ") ( errno =", errno, ")");
+ Log("\t", readbuffer);
+
+ // water
+ errno = 0;
+ TEST_CASE(int curp = sceKernelLseek(fd, 6, 1); curp == 45, "ok:", "fail:", "current+6 (lseek is", curp, "should be:", 45, ") ( errno =", errno, ")");
+ memset(readbuffer, 0, 256);
+ TEST_CASE(int br = sceKernelRead(fd, readbuffer, 5); br == 5, "Read successful", "Read failed", "(Read:", br, "should read:", 5, ") ( errno =", errno, ")");
+ Log("\t", readbuffer);
+ // remember
+ TEST_CASE(int curp = sceKernelLseek(fd, -28, 1); curp == 22, "ok:", "fail:", "current-28 (lseek is", curp, "should be:", 22, ") ( errno =", errno, ")");
+ memset(readbuffer, 0, 256);
+ TEST_CASE(int br = sceKernelRead(fd, readbuffer, 8); br == 8, "Read successful", "Read failed", "(Read:", br, "should read:", 8, ") ( errno =", errno, ")");
+ Log("\t", readbuffer);
+
+ // OOB tests
+ // TLDR - outcoming -OOB results in EINVAL, doesn't change ptr. +OOB is a fair game
+ errno = 0;
+ // absolute, 2137
+ TEST_CASE(int curp = sceKernelLseek(fd, 2137, 0);
+ curp == 2137, "ok:", "fail:", "origin+2137 (OOB) (lseek is", curp, "should be:", 2137, ") ( errno =", errno, ")");
+ errno = 0;
+ // error, no change in ptr
+ TEST_CASE(sceKernelLseek(fd, -2137, 0) < 0 && errno == 22, "ok:", "fail:", "origin-2137 (OOB) (errno should be 22 - EINVAL) ( errno =", errno, ")");
+ errno = 0;
+ // n to the front of current ptr, 2137+2137
+ TEST_CASE(int curp = sceKernelLseek(fd, 2137, 1);
+ curp == 2137 * 2, "ok:", "fail:", "current+2137 (OOB) (lseek is", curp, "should be:", 4274, ") ( errno =", errno, ")");
+ errno = 0;
+ // n to the back of current ptr, 2137+2137-1234
+ TEST_CASE(int curp = sceKernelLseek(fd, -1234, 1);
+ curp == 3040, "ok:", "fail:", "current-1234 (OOB) (lseek is", curp, "should be:", 3040, ") ( errno =", errno, ")");
+ errno = 0;
+ // n to the back of current ptr, into the negative 2137+2137-1234-5000
+ TEST_CASE(sceKernelLseek(fd, -5000, 1) < 0 && errno == 22, "ok:", "fail:", "current-5000 (into -OOB) (errno should be 22 - EINVAL) ( errno =", errno, ")");
+ errno = 0;
+ // n after the end, i.e. size+n
+ auto oob_end_pos = GetSize(fd) + 2137;
+ TEST_CASE(int curp = sceKernelLseek(fd, 2137, 2);
+ curp == oob_end_pos, "ok:", "fail:", "end+2137 (OOB) (lseek is", curp, "should be:", oob_end_pos, ") ( errno =", errno, ")");
+ errno = 0;
+ // error, no change in ptr
+ TEST_CASE(sceKernelLseek(fd, -2137, 2) < 0 && errno == 22, "ok:", "fail:", "end-2137 (OOB) (errno should be 22 - EINVAL) ( errno =", errno, ")");
+
+ if (0 != sceKernelClose(fd)) LogError("Can't close [", path, "]", "( errno =", errno, ")");
+
+ return true;
+}
+
+int TestOpenFlags(const char* path, int32_t flags, const char* flags_str, int* errno_return) {
+ LogTest("Testing open() on [", path, "] with flags:", to_hex(flags), "(", flags_str, ")");
+
+ errno = 0;
+ int fd = sceKernelOpen(path, flags, 0777);
+ if (nullptr != errno_return) *errno_return = errno;
+ if (fd < 0) return fd;
+
+ // dummy string, some files need text to be created
+ sceKernelWrite(fd, "TEST", 4);
+ sceKernelClose(fd);
+ return 0;
+}
+
+bool TestFileRW(const char* path, u16 to_test) {
+ LogTest("Testing r/w on [", path, "]");
+
+ if (to_test < 8) {
+ LogError("Must test at least 8 bytes!");
+ return false;
+ }
+
+ int fd = -1;
+ uint8_t* writebuf = new uint8_t[to_test + 2];
+ uint8_t* readbuf = new uint8_t[to_test + 2];
+ memset(writebuf, 0xFF, to_test);
+ memset(readbuf, 0xFF, to_test);
+
+ char tmpchr = 'a';
+ u16 cnt = 0;
+ while (cnt < to_test) {
+ writebuf[cnt++] = tmpchr;
+ if (++tmpchr == 'z') tmpchr = 'a';
+ }
+ writebuf[cnt++] = '\r';
+ writebuf[cnt] = '\n';
+
+ errno = 0;
+ fd = sceKernelOpen(path, 0x2, 0777);
+ TEST_CASE(fd > 0, "Opened", "Can't open", "[", path, "]", "( errno =", errno, ")");
+
+ if (fd < 0) return false;
+
+ errno = 0;
+ int bw = sceKernelWrite(fd, writebuf, to_test);
+ TEST_CASE(bw == to_test, "Write succeded", "Write failed", "(", bw, " bytes written)", "( errno =", errno, ")");
+
+ struct OrbisKernelStat st {};
+
+ sceKernelFstat(fd, &st);
+ // device is always 0 in size
+ bool not_a_dev = !S_ISCHR(st.st_mode);
+ auto target_size = st.st_size * not_a_dev;
+
+ errno = 0;
+ TEST_CASE(int status = sceKernelLseek(fd, 10, 0); status == 10, "", "", "Lseek ORIGIN+10", "val =", status, "should be", 10, "( errno =", errno, ")");
+ errno = 0;
+ TEST_CASE(int status = sceKernelLseek(fd, 1, 1); status == 11, "", "", "Lseek CURRENT+1", "val =", status, "should be", 11, "( errno =", errno, ")");
+ errno = 0;
+ TEST_CASE(int status = sceKernelLseek(fd, -1, 1); status == 10, "", "", "Lseek CURRENT-1", "val =", status, "should be", 10, "( errno =", errno, ")");
+ errno = 0;
+ TEST_CASE(int status = sceKernelLseek(fd, 0, 2);
+ status == target_size, "", "", "Lseek END", "val =", status, "should be", target_size, "( errno =", errno, ")");
+ errno = 0;
+ TEST_CASE(int status = sceKernelLseek(fd, -1, 2); status == (target_size - (1 * not_a_dev)), "", "", "Lseek END-1", "val =", status, "should be",
+ target_size - (1 * not_a_dev), "( errno =", errno, ")");
+ errno = 0;
+ TEST_CASE(int status = sceKernelLseek(fd, 1, 2);
+ status == (target_size + 1), "", "", "Lseek END+1", "val =", status, "should be", target_size + 1, "( errno =", errno, ")");
+ errno = 0;
+ TEST_CASE(int status = sceKernelLseek(fd, 0, 0); status == 0, "", "", "Lseek ORIGIN+0", "val =", status, "should be", 0, "( errno =", errno, ")");
+
+ errno = 0;
+ int br = sceKernelRead(fd, readbuf, to_test);
+ TEST_CASE(br == to_test, "Read succeded", "Read failed", "(", br, " bytes read)", "( errno =", errno, ")")
+ Log("Buffers are equal? :", (memcmp(writebuf, readbuf, to_test) == 0 ? "yes" : "no"));
+
+ if (bw > 0) Log("Write preview:", right(STR(writebuf[0]), 3), right(STR(writebuf[1]), 3), right(STR(writebuf[2]), 3), right(STR(writebuf[3]), 3));
+ if (br > 0) Log("Read preview:", right(STR(readbuf[0]), 3), right(STR(readbuf[1]), 3), right(STR(readbuf[2]), 3), right(STR(readbuf[3]), 3));
+
+ bool all_zeros = true;
+ for (u16 i = 0; i < to_test; i++) {
+ if (readbuf[i] == 0) continue;
+ all_zeros = false;
+ break;
+ }
+
+ Log("Is reading buffer full of zeros? :", (all_zeros ? "yes" : "no"));
+
+ delete[] writebuf;
+ delete[] readbuf;
+
+ return true;
+}
+
+bool TestFileTouch(const char* path) {
+ LogTest("Cursed file operations: [", path, "]");
+
+ OrbisKernelStat st {};
+
+ errno = 0;
+ TEST_CASE(0 == touch(path), "touched", "can'touch", "( errno =", errno, ")");
+
+ errno = 0;
+ TEST_CASE(0 == sceKernelStat(path, &st), "stat success", "stat fail", "( errno =", errno, ")")
+
+ return true;
+}
+
+bool PrepareCursedFileop(void) {
+ Obliterate("/data/therapist/tmp_cursed");
+
+ LogTest("Cursed file operations");
+ bool is_ok = true;
+
+ is_ok &= (0 == sceKernelMkdir("/data/therapist/tmp_cursed", 0777));
+ is_ok &= (0 == sceKernelMkdir("/data/therapist/tmp_cursed/Aursed", 0777));
+ is_ok &= (0 == sceKernelMkdir("/data/therapist/tmp_cursed/Aursed/AAursed", 0777));
+ is_ok &= (0 == sceKernelMkdir("/data/therapist/tmp_cursed/Bursed", 0777));
+ is_ok &= (0 == sceKernelMkdir("/data/therapist/tmp_cursed/Bursed/BBursed", 0777));
+ is_ok &= (0 == sceKernelMkdir("/data/therapist/tmp_cursed/Cursed", 0777));
+ is_ok &= (0 == sceKernelMkdir("/data/therapist/tmp_cursed/Cursed/CCursed", 0777));
+
+ return is_ok;
+}
+
+bool TestStat(fs::path path, const OrbisKernelStat* original) {
+ LogTest("Testing stat on [", path, "]");
+ OrbisKernelStat st {};
+
+ errno = 0;
+ TEST_CASE(0 == sceKernelStat(path.c_str(), &st), "Stat successful", "Stat failed", "[", path, "]", "( errno =", errno, ")");
+
+ if (nullptr == original) {
+ Log("No comparsiton target provided for [", path, "]. Dumping your own :)");
+ PrintStatInfo(&st);
+ return true;
+ }
+
+ return StatCmp(&st, original);
+}
+
+bool TestLStat(fs::path path) {
+ LogTest("Testing lstat on [", path, "]");
+ struct stat st {};
+
+ errno = 0;
+
+ return 0 == lstat(path.c_str(), &st);
+}
+
+bool RegenerateDir(const char* path) {
+ // TODO: this should return false sometimes *cough cough*
+ Obliterate(path);
+ sceKernelMkdir(path, 0777);
+ return true;
+}
+
+bool TestDirEnts() {
+ //
+ // Setup
+ //
+ LogTest("Testing dirents");
+
+ s32 result = 0;
+ char prebuffer[DIRENT_BUFFER_SIZE] {0};
+ char postbuffer[DIRENT_BUFFER_SIZE] {0};
+
+ //
+ // Creating target directory
+ //
+
+ errno = 0;
+ TEST_CASE(sceKernelMkdir("/data/therapist/tmp_dirent", 0777) == 0x80020011, "Creating [ /data/therapist/tmp_dirent ] failed (EEXIST)",
+ "Created [ /data/therapist/tmp_dirent ] even though it existed before", "( errno =", errno, ")");
+
+ //
+ // Test opening first
+ //
+
+ errno = 0;
+ int fd = sceKernelOpen("/data/therapist/tmp_dirent", 0, 0777);
+ TEST_CASE(fd > -1, "open() succeeded on", "can't open", "[ /data/therapist/tmp_dirent ] ( errno =", errno, ")");
+
+ errno = 0;
+ TEST_CASE(sceKernelClose(fd) > -1, "Closed", "Can't close", "[ /data/therapist/tmp_dirent ]", "( errno =", errno, ")");
+
+ //
+ // Create dummy files, read dir
+ //
+
+ errno = 0;
+ int tmp_creat_cnt = 0;
+ // basically creat(), but it's not available in sceKernel
+ tmp_creat_cnt += touch("/data/therapist/tmp_dirent/dummy_file_1");
+ tmp_creat_cnt += touch("/data/therapist/tmp_dirent/dummy_file_2");
+ tmp_creat_cnt += touch("/data/therapist/tmp_dirent/dummy_file_3");
+ tmp_creat_cnt += touch("/data/therapist/tmp_dirent/dummy_file_4");
+ TEST_CASE(tmp_creat_cnt == 0, "Dummy files (1-4) created", "Can't create dummy files in [ /data/therapist/tmp_dirent ]", "( errno =", errno, ")");
+
+ errno = 0;
+ fd = sceKernelOpen("/data/therapist/tmp_dirent", 0, 0777);
+ TEST_CASE(fd > -1, "open() succeeded on", "can't open", "[ /data/therapist/tmp_dirent ] ( errno =", errno, ")");
+
+ errno = 0;
+ TEST_CASE(sceKernelLseek(fd, 0, 0) == 0, "Seek to start", "Seek failed", "(dirents, pre)", "( errno =", errno, ")");
+ errno = 0;
+ TEST_CASE(int status = sceKernelGetdirentries(fd, prebuffer, DIRENT_BUFFER_SIZE, nullptr);
+ status == DIRENT_BUFFER_SIZE, "Direntries read correctly", "Can't get direntries", "( read bytes:", status, ")", "( errno =", errno, ")");
+ errno = 0;
+ TEST_CASE(sceKernelLseek(fd, 0, 0) == 0, "Seek to start", "Seek failed", "(dump, pre)", "( errno =", errno, ")");
+ errno = 0;
+ TEST_CASE(int last_reclen = dumpDir(fd); last_reclen == (DIRENT_BUFFER_SIZE - 96), "Read correct amount of data", "Last dirent has incorrect value",
+ "(dump, pre)", "( last_reclen =", last_reclen, "should be =", DIRENT_BUFFER_SIZE - 96, ")", "( errno =", errno, ")");
+ Log("You should see 4 dummy files here");
+
+ //
+ // Create more dummy files while dir is open
+ //
+
+ errno = 0;
+ tmp_creat_cnt = 0;
+ tmp_creat_cnt += touch("/data/therapist/tmp_dirent/dummy_file_5");
+ tmp_creat_cnt += touch("/data/therapist/tmp_dirent/dummy_file_6");
+ tmp_creat_cnt += touch("/data/therapist/tmp_dirent/dummy_file_7");
+ tmp_creat_cnt += touch("/data/therapist/tmp_dirent/dummy_file_8");
+ TEST_CASE(tmp_creat_cnt == 0, "Dummy files (5-8) created", "Can't create dummy files in [ /data/therapist/tmp_dirent ]", "( errno =", errno, ")");
+
+ errno = 0;
+ TEST_CASE(sceKernelLseek(fd, 0, 0) == 0, "Seek to start", "Seek failed", "(dirents, post)", "( errno =", errno, ")");
+ errno = 0;
+ TEST_CASE(int status = sceKernelGetdirentries(fd, postbuffer, DIRENT_BUFFER_SIZE, nullptr);
+ status == DIRENT_BUFFER_SIZE, "Direntries read correctly", "Can't get direntries", "( read bytes:", status, ")", "( errno =", errno, ")");
+ errno = 0;
+ TEST_CASE(sceKernelLseek(fd, 0, 0) == 0, "Seek to start", "Seek failed", "(dump, post)", "( errno =", errno, ")");
+ errno = 0;
+ TEST_CASE(int last_reclen = dumpDir(fd); last_reclen == (DIRENT_BUFFER_SIZE - 192), "Read correct amount of data", "Last dirent has incorrect value",
+ "(dump, post)", "( last_reclen =", last_reclen, "should be =", DIRENT_BUFFER_SIZE - 192, ")", "( errno =", errno,
+ ")");
+ Log("You should see 8 dummy files here");
+
+ //
+ // Cave Johnson. We're done here
+ //
+
+ errno = 0;
+ TEST_CASE(sceKernelClose(fd) != -1, "Closed", "Can't close", "[ /data/therapist/tmp_dirent ]", "( errno =", errno, ")");
+
+ return true;
+
+ // // compare before and after opening
+
+ // LogFilesystem("Creating a new file...\n");
+ // sceKernelClose(sceKernelOpen("/data/therapist/tmp/2created_after_opening", (int32_t)OpenFlags::Create, 0644));
+
+ // sceKernelLseek(tmpfd, 0, 0);
+ // result = sceKernelGetdirentries(tmpfd, buffer, BUFFER_SIZE, nullptr);
+ // LogFilesystemStatus("Printed entries (%lu bytes)\n", ASSERT(printContents(buffer, result)), result);
+
+ // auto q = memcmp(prebuffer, buffer, BUFFER_SIZE);
+ // LogFilesystemStatus("Comparing dirent buffers\n", q != 0);
+
+ // sceKernelClose(tmpfd);
+
+ // {
+ // LogFilesystemStatus("Opening directory again after creating a file\n", Test::TEST);
+ // tmpfd = sceKernelOpen("/data/therapist/tmp_dirent", 0, 0777);
+ // LogFilesystemStatus("Printed entries (%lu bytes)\n", ASSERT(printContents(prebuffer, result)), result);
+ // sceKernelClose(tmpfd);
+ // }
+
+ // // timing tests
+
+ // char tmpname[24]{0};
+ // const char *tftemplate = "/data/therapist/tmp/XD%d";
+
+ // tmpfd = sceKernelOpen("/data/therapist/tmp_dirent", 0, 0644);
+ // result = sceKernelGetdirentries(tmpfd, prebuffer, BUFFER_SIZE, nullptr);
+
+ // for (u16 idx = 0; idx < TESTFILES; idx++)
+ // {
+ // snprintf(tmpname, 24, tftemplate, idx);
+ // sceKernelClose(sceKernelOpen(tmpname, (int32_t)OpenFlags::Create, 0644));
+ // }
+
+ // for (u16 midx = 0; midx < 10; midx++)
+ // {
+ // auto bench_start = std::chrono::high_resolution_clock::now();
+ // for (u16 idx = 0; idx < TIMING_ITERATIONS; idx++)
+ // {
+ // sceKernelLseek(tmpfd, 0, 0);
+ // sceKernelGetdirentries(tmpfd, buffer, BUFFER_SIZE, &dirents_index);
+ // }
+ // auto bench_end = std::chrono::high_resolution_clock::now();
+ // auto duration = std::chrono::duration_cast(bench_end - bench_start).count();
+ // unsigned long long avgtime = duration / TIMING_ITERATIONS / 1000;
+ // LogFilesystem("Refreshing %d files %d times (no changes): avg %llu us/it\n", TESTFILES, TIMING_ITERATIONS, avgtime);
+ // }
+
+ // // test removing files sequentially
+
+ // {
+ // result = sceKernelGetdirentries(tmpfd, buffer, BUFFER_SIZE, nullptr);
+
+ // auto bench_start = std::chrono::high_resolution_clock::now();
+ // for (u16 idx = 0; idx < TESTFILES - 1; idx++)
+ // {
+ // snprintf(tmpname, 24, tftemplate, idx);
+ // sceKernelUnlink(tmpname);
+
+ // sceKernelLseek(tmpfd, 0, 0);
+ // sceKernelGetdirentries(tmpfd, buffer, BUFFER_SIZE, &dirents_index);
+ // }
+ // auto bench_end = std::chrono::high_resolution_clock::now();
+ // unsigned long long duration = std::chrono::duration_cast(bench_end - bench_start).count();
+ // LogFilesystem("Removed %d files in %llu us\n", TESTFILES - 1, duration / 1000);
+ // }
+
+ // sceKernelClose(tmpfd);
+}
+
+bool TestRelatives(fs::path path, bool expected_mountpoint) {
+ LogTest("Testing relative fileno perception of [", path.string(), "]");
+
+ const std::string path_str = path.string();
+ std::string leafstr = path.filename().string();
+ oi::FolderDirent leaf {};
+
+ s64 leaf_to_self {-2};
+ s64 parent_to_leaf {-2};
+ s64 leaf_to_parent {-2};
+
+ u8 ret {};
+
+ //
+ // test self (2 if mountpoint root)
+ ret = GetDir(path, ".", &leaf);
+ if (ret <= 0) {
+ LogError("Cannot get [ . ] from", path_str);
+ } else
+ leaf_to_self = leaf.d_fileno;
+
+ //
+ // test self-parent path (2 if mountpoint root)
+ ret = GetDir(path, "..", &leaf);
+ if (ret <= 0) {
+ LogError("Cannot get [ .. ] from", path_str);
+ } else
+ leaf_to_parent = leaf.d_fileno;
+
+ //
+ // test how parent sees the child
+ if (!leafstr.empty()) {
+ ret = GetDir(path.parent_path(), (path == "/" ? "/" : leafstr), &leaf);
+ if (ret <= 0) {
+ LogError("Cannot get [", leafstr, "] from", path_str);
+ } else
+ parent_to_leaf = leaf.d_fileno;
+ }
+
+ Log(path_str, "sees itself with fileno=", leaf_to_self);
+ Log(path_str, "sees its parent with fileno=", leaf_to_parent);
+ Log(path_str, "is seen with fileno=", parent_to_leaf);
+
+ bool is_mountpoint = leaf_to_self != parent_to_leaf && leaf_to_self != -2 && leaf_to_parent != -2 && parent_to_leaf != -2;
+ if (expected_mountpoint) {
+ TEST_CASE(is_mountpoint == expected_mountpoint, "It's a mountpoint", "It's not a mountpoint");
+ } else {
+ Log(is_mountpoint ? "It's a mountpoint" : "It's not a mountpoint");
+ }
+
+ return true;
+}
+
+bool CompareNormalVsPFS(fs::path path, fs::path leaf, s32 expected_normal_reclen, s32 expected_pfs_reclen) {
+ oi::PfsDirent pfs_dir {};
+ oi::FolderDirent normal_dir {};
+ const char* path_str = path.c_str();
+ const char* leaf_str = leaf.c_str();
+ fs::path q = path / leaf;
+ const char* path_full_str = q.c_str();
+
+ LogTest("Compare Normal and PFS dirent for", path_full_str);
+ if (GetDir(path, leaf, &normal_dir) == -1) {
+ LogError("Can't open", path_full_str, "as normal");
+ }
+ if (GetDir(path, leaf, &pfs_dir) == -1) {
+ LogError("Can't open", path_full_str, "as PFS");
+ }
+
+ bool expr;
+
+ expr = normal_dir.d_fileno == pfs_dir.d_fileno;
+
+ {
+ std::stringstream ss;
+ ss << path_full_str << " fileno " << normal_dir.d_fileno << (expr ? " == " : " != ") << pfs_dir.d_fileno;
+ TEST_CASE(expr, ss.str(), ss.str());
+ }
+
+ expr = normal_dir.d_namlen == pfs_dir.d_namlen;
+
+ {
+ std::stringstream ss;
+ ss << path_full_str << " namlen " << STR(normal_dir.d_namlen) << (expr ? " == " : " != ") << pfs_dir.d_namlen;
+ TEST_CASE(expr, ss.str(), ss.str());
+ }
+
+ if (expected_normal_reclen == -1 || expected_pfs_reclen == -1)
+ expr = normal_dir.d_reclen == pfs_dir.d_reclen;
+ else
+ expr = (normal_dir.d_reclen == expected_normal_reclen) && (pfs_dir.d_reclen == expected_pfs_reclen);
+
+ // may not be equal, hence expected values
+ {
+ std::stringstream ss;
+ ss << path_full_str << " reclen " << normal_dir.d_reclen << (expr ? " == " : " != ") << pfs_dir.d_reclen;
+ TEST_CASE(expr, ss.str(), ss.str());
+ }
+
+ expr = memcmp(normal_dir.d_name, pfs_dir.d_name, normal_dir.d_namlen) == 0;
+ TEST_CASE(expr, "Names are equal", "Names are not equal", "(memcmp)")
+
+ if (!expr) {
+ // just in case
+ normal_dir.d_name[255] = 0;
+ pfs_dir.d_name[255] = 0;
+ Log("Normal:\t", normal_dir.d_name);
+ Log("PFS:\t", pfs_dir.d_name);
+ }
+
+ return true;
+}
\ No newline at end of file
diff --git a/tests/code/filesystem_test/code/fs_test.h b/tests/code/filesystem_test/code/fs_test.h
new file mode 100644
index 00000000..c2c8723b
--- /dev/null
+++ b/tests/code/filesystem_test/code/fs_test.h
@@ -0,0 +1,83 @@
+#ifndef FS_TEST_H
+#define FS_TEST_H
+
+#define UNSIGNED_INT_EQUALS(expected, actual) UNSIGNED_LONGS_EQUAL_LOCATION((uint32_t)expected, (uint32_t)actual, NULLPTR, __FILE__, __LINE__)
+#define UNSIGNED_INT_EQUALS_TEXT(expected, actual, text) UNSIGNED_LONGS_EQUAL_LOCATION((uint32_t)expected, (uint32_t)actual, text, __FILE__, __LINE__)
+
+#include "log.h"
+
+#include
+#include
+#include
+#include
+#include
+
+namespace fs = std::filesystem;
+
+#define DIRENT_PFS_BUFFER_SIZE 65536
+#define DIRENT_BUFFER_SIZE 512
+
+using s8 = int8_t;
+using s16 = int16_t;
+using s32 = int32_t;
+using s64 = int64_t;
+
+using u8 = uint8_t;
+using u16 = uint16_t;
+using u32 = uint32_t;
+using u64 = uint64_t;
+
+namespace OrbisInternals {
+typedef struct PfsDirent {
+ s32 d_fileno;
+ s32 d_type;
+ s32 d_namlen;
+ s32 d_reclen;
+ char d_name[256];
+} PfsDirent;
+
+typedef struct FolderDirent {
+ u32 d_fileno;
+ u16 d_reclen;
+ u8 d_type;
+ u8 d_namlen;
+ char d_name[256];
+} FolderDirent;
+} // namespace OrbisInternals
+
+void RunTests(void);
+s32 TestMovements(const char* from, const char* to);
+bool TestRelatives(fs::path path, bool expected_mountpoint = false);
+bool CompareNormalVsPFS(fs::path path, fs::path leaf, s32 expected_normal_reclen = -1, s32 expected_pfs_reclen = -1);
+bool RegenerateDir(const char* path);
+bool TestDirEnts(void);
+bool TestStat(fs::path path, const OrbisKernelStat* original = nullptr);
+bool TestLStat(fs::path path);
+bool PrepareCursedFileop(void);
+bool TestFileTouch(const char* path);
+int TestOpenFlags(const char* path, int32_t flags, const char* flags_str, int* errno_return = nullptr);
+bool TestFileRW(const char* path, u16 to_test);
+bool TestFileOps(const char* path);
+
+bool StatCmp(const OrbisKernelStat* lhs, const OrbisKernelStat* rhs);
+
+u16 dumpDirRecursive(fs::path path, int depth = 0);
+u16 dumpDir(int fd);
+
+void PrintStatInfo(const struct stat* info);
+void PrintStatInfo(const OrbisKernelStat* info);
+s8 GetDir(fs::path path, fs::path leaf, OrbisInternals::FolderDirent* dirent);
+s8 GetDir(fs::path path, fs::path leaf, OrbisInternals::PfsDirent* dirent);
+
+std::string file_mode(OrbisKernelMode mode);
+ino_t get_fileno(const char* path);
+ino_t get_fileno(int fd);
+void Obliterate(const char* path);
+void ElEsDashElAy(const char* path);
+int32_t touch(const char* path);
+int32_t touch(const std::string& path);
+off_t GetSize(const char* path);
+off_t GetSize(int fd);
+int exists(const char* path);
+
+#endif // FS_TEST_H
diff --git a/tests/code/filesystem_test/code/fs_test_tools.cpp b/tests/code/filesystem_test/code/fs_test_tools.cpp
new file mode 100644
index 00000000..29757c83
--- /dev/null
+++ b/tests/code/filesystem_test/code/fs_test_tools.cpp
@@ -0,0 +1,523 @@
+#include "fs_test.h"
+
+#include
+#include
+#include
+#include
+#include
+#include
+
+namespace oi = OrbisInternals;
+
+off_t GetSize(int fd) {
+ OrbisKernelStat st;
+ if (int status = sceKernelFstat(fd, &st); status < 0) return status;
+ return st.st_size;
+}
+
+off_t GetSize(const char* path) {
+ int fd = sceKernelOpen(path, O_RDONLY, 0777);
+ int size = GetSize(fd);
+ sceKernelClose(fd);
+ return size;
+}
+
+int32_t touch(const char* path) {
+ return sceKernelClose(sceKernelOpen(path, O_WRONLY | O_CREAT | O_TRUNC, 0777));
+}
+
+int32_t touch(const std::string& path) {
+ return sceKernelClose(sceKernelOpen(path.c_str(), O_WRONLY | O_CREAT | O_TRUNC, 0777));
+}
+
+ino_t get_fileno(int fd) {
+ struct OrbisKernelStat st {};
+ int status = sceKernelFstat(fd, &st);
+ return (status == 0) * st.st_ino;
+}
+
+ino_t get_fileno(const char* path) {
+ struct OrbisKernelStat st {};
+ int fd = sceKernelOpen(path, O_RDONLY, 0777);
+ if (fd < 0) return 0;
+ int status = sceKernelFstat(fd, &st);
+ sceKernelClose(fd);
+ return (status == 0) * st.st_ino;
+}
+
+int exists(const char* path) {
+ struct OrbisKernelStat ost {};
+ return sceKernelStat(path, &ost);
+}
+
+void Obliterate(const char* path) {
+ Log("<< rm -rf [", path, "] >>");
+ std::error_code ec {};
+
+ std::vector entries;
+ for (auto& p: fs::recursive_directory_iterator(path, fs::directory_options::skip_permission_denied, ec))
+ entries.push_back(p.path().string());
+
+ for (auto it = entries.rbegin(); it != entries.rend(); ++it) {
+ if (ec) {
+ LogError("Exception: [", ec.value(), "] :", ec.message());
+ ec.clear();
+ continue;
+ }
+
+ const char* pp = it->c_str();
+
+ // see what sticks
+
+ struct OrbisKernelStat st {0};
+
+ errno = 0;
+ sceKernelStat(pp, &st);
+ if (2 == errno)
+ // not found, good
+ continue;
+
+ errno = 0;
+ if (S_ISDIR(st.st_mode)) sceKernelRmdir(pp);
+ if (S_ISREG(st.st_mode)) sceKernelUnlink(pp);
+
+ if (errno != 0) LogError("Cannot remove [", pp, "] ( errno =", errno, ")");
+ }
+
+ errno = 0;
+ sceKernelRmdir(path);
+
+ if (!(ENOENT == errno || 0 == errno)) LogError("Cannot remove [", path, "] ( errno =", errno, ")");
+
+ LogSuccess(">> rm -rf [", path, "] <<");
+ return;
+}
+
+void ElEsDashElAy(const char* path) {
+ Log("<< ls -la [", path, "] >>");
+ std::error_code ec {};
+
+ for (const auto& entry: fs::directory_iterator(path, ec)) {
+ struct OrbisKernelStat st {};
+ std::string pathstr = entry.path().string();
+ int fd = 0;
+
+ if (fd = sceKernelOpen(entry.path().c_str(), 0x0, 0777); fd < 0) {
+ LogError("Cannot open ", entry.path());
+ continue;
+ }
+ if (sceKernelFstat(fd, &st) == -1) {
+ LogError("Cannot stat ", entry.path());
+ continue;
+ }
+
+ char timebuf[64];
+ std::tm* t = std::localtime(&st.st_mtime);
+ std::strftime(timebuf, sizeof(timebuf), "%EY-%m-%d %H:%M", t);
+
+ Log(file_mode(st.st_mode), right('0' + to_octal(st.st_mode), 8), std::dec, right(STR(st.st_nlink), 3), st.st_uid, ":", st.st_gid, right(STR(st.st_size), 8),
+ timebuf, pathstr);
+
+ // uncomment for hex dump
+ // std::cout << "\t\t";
+ // for (auto q = 0; q < sizeof(st); ++q)
+ // {
+ // std::cout << " " << std::setw(2) << std::setfill('0') << std::hex << static_cast((reinterpret_cast(&st)[q]));
+ // if ((q + 1) % 32 == 0)
+ // std::cout << std::endl
+ // << "\t\t";
+ // }
+ // std::cout << std::endl;
+
+ if (sceKernelClose(fd) < 0) LogError("Can't close [", path, "]");
+ }
+
+ LogSuccess(">> ls -la [", path, "] <<");
+ return;
+}
+
+std::string file_mode(OrbisKernelMode mode) {
+ std::string s;
+
+ if (S_ISREG(mode))
+ s += '-';
+ else if (S_ISDIR(mode))
+ s += 'd';
+ else if (S_ISLNK(mode))
+ s += 'l';
+ else if (S_ISCHR(mode))
+ s += 'c';
+ else if (S_ISBLK(mode))
+ s += 'b';
+ else if (S_ISFIFO(mode))
+ s += 'p';
+ else if (S_ISSOCK(mode))
+ s += 's';
+ else
+ s += '?';
+
+ // owner
+ s += (mode & S_IRUSR) ? 'r' : '-';
+ s += (mode & S_IWUSR) ? 'w' : '-';
+ s += (mode & S_IXUSR) ? 'x' : '-';
+
+ // group
+ s += (mode & S_IRGRP) ? 'r' : '-';
+ s += (mode & S_IWGRP) ? 'w' : '-';
+ s += (mode & S_IXGRP) ? 'x' : '-';
+
+ // other
+ s += (mode & S_IROTH) ? 'r' : '-';
+ s += (mode & S_IWOTH) ? 'w' : '-';
+ s += (mode & S_IXOTH) ? 'x' : '-';
+
+ return s;
+}
+
+u16 dumpDirRecursive(fs::path path, int depth) {
+ if (0 == depth) {
+ Log("Listing dirents of [", path.string(), "]");
+ }
+
+ std::string depEnt = "|--";
+ for (u8 q = 0; q < depth; q++) {
+ depEnt = depEnt + "|--";
+ }
+ depEnt[depEnt.length() - 1] = '>';
+
+ // Log(depDir.c_str(), path_str.c_str());
+
+ s32 fd = sceKernelOpen(path.c_str(), 0, 0777);
+ if (fd < 0) {
+ Log("\t\t\t\t", depEnt.c_str(), "//NO ACCESS//");
+ return 0;
+ }
+
+ char* buf = new char[DIRENT_BUFFER_SIZE];
+ char* bufptr = buf;
+ s64 idx = 0;
+ s64 read_bytes;
+
+ read_bytes = sceKernelGetdirentries(fd, buf, DIRENT_BUFFER_SIZE, &idx);
+ if (read_bytes <= 0) Log("\t\t\t\t", depEnt.c_str(), "//FAILED//");
+
+ u16 last_reclen = 0;
+
+ while (read_bytes > 0) {
+ bufptr = buf;
+ char* endptr = buf + read_bytes;
+ while (bufptr < endptr) {
+ oi::FolderDirent* entry = (oi::FolderDirent*)bufptr;
+ bufptr += static_cast(entry->d_reclen);
+ if (entry->d_reclen == 0) {
+ Log("\t\t\t\t", depEnt.c_str(), "//BAD RECLEN//");
+ break;
+ }
+
+ std::string ftype {};
+ switch (entry->d_type) {
+ default: ftype = std::to_string(entry->d_type); break;
+ case 2: ftype = "DEV"; break;
+ case 4: ftype = "DIR"; break;
+ case 8: ftype = "FIL"; break;
+ case 10: ftype = "LNK"; break;
+ case 12: ftype = "SOC"; break;
+ }
+
+ std::string tree = depEnt + std::string(entry->d_name);
+
+ Log("[", center(ftype, 3), "][", right(STR(entry->d_fileno), 10), "][", right(STR(entry->d_namlen), 3), "][", right(STR(entry->d_reclen), 3), "]", tree);
+
+ last_reclen = entry->d_reclen;
+
+ if (ftype != "DIR") continue;
+ // preserved: parent and child may percieve each other differently
+ if (strncmp(".", entry->d_name, 1) == 0) continue;
+ if (strncmp("..", entry->d_name, 2) == 0) continue;
+
+ std::string child(entry->d_name);
+ dumpDirRecursive(path / child, depth + 1);
+ }
+ // move unread data to the beginning of the buffer
+ s64 diff = endptr - bufptr;
+ // shouldn't, but shit happens
+ if (diff < 0) {
+ Log("XDXDXDXDXDXDXDXDXDXD ", diff);
+ diff = 0;
+ }
+ // memmove(buf, bufptr, diff);
+ // read into after saved remainder
+ // read_bytes = sceKernelGetdirentries(fd, buf + diff, DIRENT_BUFFER_SIZE - diff, &idx) + diff;
+ read_bytes = sceKernelGetdirentries(fd, buf, DIRENT_BUFFER_SIZE, &idx);
+ }
+
+ sceKernelClose(fd);
+ delete[] buf;
+
+ if (0 == depth) {
+ LogSuccess("Listing dirents of [", path.string(), "]");
+ }
+ return last_reclen;
+}
+
+u16 dumpDir(int fd) {
+ std::string depEnt = "|->";
+
+ char* buf = new char[DIRENT_BUFFER_SIZE];
+ char* bufptr = buf;
+ s64 idx = 0;
+ s64 read_bytes;
+
+ read_bytes = sceKernelGetdirentries(fd, buf, DIRENT_BUFFER_SIZE, &idx);
+ if (read_bytes <= 0) Log("\t\t\t\t", depEnt.c_str(), "//FAILED//");
+
+ u16 last_reclen = 0;
+
+ while (read_bytes > 0) {
+ bufptr = buf;
+ char* endptr = buf + read_bytes;
+ while (bufptr < endptr) {
+ oi::FolderDirent* entry = (oi::FolderDirent*)bufptr;
+ bufptr += static_cast(entry->d_reclen);
+ if (entry->d_reclen == 0) {
+ Log("\t\t\t\t", depEnt.c_str(), "//BAD RECLEN//");
+ break;
+ }
+
+ std::string ftype {};
+ switch (entry->d_type) {
+ default: ftype = std::to_string(entry->d_type); break;
+ case 2: ftype = "DEV"; break;
+ case 4: ftype = "DIR"; break;
+ case 8: ftype = "FIL"; break;
+ case 10: ftype = "LNK"; break;
+ case 12: ftype = "SOC"; break;
+ }
+
+ std::string tree = depEnt + std::string(entry->d_name);
+
+ Log("[", center(ftype, 3), "][", right(STR(entry->d_fileno), 10), "][", right(STR(entry->d_namlen), 3), "][", right(STR(entry->d_reclen), 3), "]", tree);
+
+ last_reclen = entry->d_reclen;
+
+ if (ftype != "DIR") continue;
+ // preserved: parent and child may percieve each other differently
+ if (strncmp(".", entry->d_name, 1) == 0) continue;
+ if (strncmp("..", entry->d_name, 2) == 0) continue;
+ }
+ // move unread data to the beginning of the buffer
+ s64 diff = endptr - bufptr;
+ // shouldn't, but shit happens
+ if (diff < 0) {
+ Log("XDXDXDXDXDXDXDXDXDXD ", diff);
+ diff = 0;
+ }
+ memmove(buf, bufptr, diff);
+ // read into after saved remainder
+ read_bytes = sceKernelGetdirentries(fd, buf + diff, DIRENT_BUFFER_SIZE - diff, &idx) + diff;
+ }
+
+ delete[] buf;
+
+ return last_reclen;
+}
+
+void PrintStatInfo(const struct stat* info) {
+ Log("stat", "info.st_dev =", info->st_dev);
+ Log("stat", "info.st_ino =", info->st_ino);
+ Log("stat", "info.st_mode =", "0" + to_octal(info->st_mode));
+ Log("stat", "info.st_nlink =", info->st_nlink);
+ Log("stat", "info.st_uid =", info->st_uid);
+ Log("stat", "info.st_gid =", info->st_gid);
+ Log("stat", "info.st_rdev =", info->st_rdev);
+ Log("stat", "info.st_atim.tv_sec =", info->st_atim.tv_sec);
+ Log("stat", "info.st_atim.tv_nsec =", info->st_atim.tv_nsec);
+ Log("stat", "info.st_mtim.tv_sec =", info->st_mtim.tv_sec);
+ Log("stat", "info.st_mtim.tv_nsec =", info->st_mtim.tv_nsec);
+ Log("stat", "info.st_ctim.tv_sec =", info->st_ctim.tv_sec);
+ Log("stat", "info.st_ctim.tv_nsec =", info->st_ctim.tv_nsec);
+ Log("stat", "info.st_size = ", info->st_size);
+ Log("stat", "info.st_blocks =", info->st_blocks);
+ Log("stat", "info.st_blksize =", info->st_blksize);
+ Log("stat", "info.st_flags =", info->st_flags);
+ Log("stat", "info.st_gen =", info->st_gen);
+ Log("stat", "info.st_birthtim.tv_sec =", info->st_birthtim.tv_sec);
+ Log("stat", "info.st_birthtim.tv_nsec =", info->st_birthtim.tv_nsec);
+}
+
+void PrintStatInfo(const OrbisKernelStat* info) {
+ Log("stat", "info.st_dev =", info->st_dev);
+ Log("stat", "info.st_ino =", info->st_ino);
+ Log("stat", "info.st_mode =", "0" + to_octal(info->st_mode));
+ Log("stat", "info.st_nlink =", info->st_nlink);
+ Log("stat", "info.st_uid =", info->st_uid);
+ Log("stat", "info.st_gid =", info->st_gid);
+ Log("stat", "info.st_rdev =", info->st_rdev);
+ Log("stat", "info.st_atim.tv_sec =", info->st_atim.tv_sec);
+ Log("stat", "info.st_atim.tv_nsec =", info->st_atim.tv_nsec);
+ Log("stat", "info.st_mtim.tv_sec =", info->st_mtim.tv_sec);
+ Log("stat", "info.st_mtim.tv_nsec =", info->st_mtim.tv_nsec);
+ Log("stat", "info.st_ctim.tv_sec =", info->st_ctim.tv_sec);
+ Log("stat", "info.st_ctim.tv_nsec =", info->st_ctim.tv_nsec);
+ Log("stat", "info.st_size = ", info->st_size);
+ Log("stat", "info.st_blocks =", info->st_blocks);
+ Log("stat", "info.st_blksize =", info->st_blksize);
+ Log("stat", "info.st_flags =", info->st_flags);
+ Log("stat", "info.st_gen =", info->st_gen);
+ Log("stat", "info.st_lspare =", info->st_lspare);
+ Log("stat", "info.st_birthtim.tv_sec =", info->st_birthtim.tv_sec);
+ Log("stat", "info.st_birthtim.tv_nsec =", info->st_birthtim.tv_nsec);
+}
+
+bool StatCmp(const OrbisKernelStat* lhs, const OrbisKernelStat* rhs) {
+ if (nullptr == rhs) return true;
+
+ bool was_error = false;
+ was_error |= lhs->st_mode != rhs->st_mode;
+ was_error |= lhs->st_nlink != rhs->st_nlink;
+ was_error |= lhs->st_uid != rhs->st_uid;
+ was_error |= lhs->st_gid != rhs->st_gid;
+ was_error |= lhs->st_size != rhs->st_size;
+ was_error |= lhs->st_blocks != rhs->st_blocks;
+ was_error |= lhs->st_blksize != rhs->st_blksize;
+ was_error |= lhs->st_flags != rhs->st_flags;
+
+ Log("---- OrbisKernelStat comparsion ----");
+ Log("st_mode \tLHS = ", right("0" + to_octal(lhs->st_mode), 7), "\t|\tRHS = ", right("0" + to_octal(rhs->st_mode), 7));
+ // nlink can differ between localizations, constant in RO locations
+ Log("st_nlink \tLHS = ", right(STR(lhs->st_nlink), 7), "\t|\tRHS = ", right(STR(rhs->st_nlink), 7));
+ Log("st_uid \tLHS = ", right(STR(lhs->st_uid), 7), "\t|\tRHS = ", right(STR(rhs->st_uid), 7));
+ Log("st_gid \tLHS = ", right(STR(lhs->st_gid), 7), "\t|\tRHS = ", right(STR(rhs->st_gid), 7));
+ Log("st_size \tLHS = ", right(STR(lhs->st_size), 7), "\t|\tRHS = ", right(STR(rhs->st_size), 7));
+ Log("st_blocks \tLHS = ", right(STR(lhs->st_blocks), 7), "\t|\tRHS = ", right(STR(rhs->st_blocks), 7));
+ Log("st_blksize\tLHS = ", right(STR(lhs->st_blksize), 7), "\t|\tRHS = ", right(STR(rhs->st_blksize), 7));
+ Log("st_flags \tLHS = ", right(STR(lhs->st_flags), 7), "\t|\tRHS = ", right(STR(rhs->st_flags), 7));
+ return !was_error;
+}
+
+s8 GetDir(fs::path path, fs::path leaf, oi::PfsDirent* dirent) {
+ const char* target_file_name = leaf.c_str();
+ const u16 target_file_name_length = leaf.string().size();
+ char buffer[DIRENT_PFS_BUFFER_SIZE];
+ char* bufptr;
+ char* bufend;
+ u64 total_read {0};
+ s64 diff;
+ bool found {false};
+
+ int fd = sceKernelOpen(path.c_str(), 0, 0777);
+ if (fd < 0) {
+ LogError("[PFS] Cannot open [", target_file_name, "]");
+ return -1;
+ }
+
+ s64 read_bytes = sceKernelRead(fd, buffer, DIRENT_PFS_BUFFER_SIZE);
+
+ // redundant
+ while (read_bytes > 0 && !found) {
+ total_read += read_bytes;
+ bufptr = buffer;
+ bufend = buffer + read_bytes;
+
+ while (bufptr < bufend) {
+ oi::PfsDirent* entry = (oi::PfsDirent*)bufptr;
+
+ if (entry->d_reclen >= 0) bufptr += static_cast(entry->d_reclen);
+
+ if (entry->d_reclen <= 0) {
+ LogError("[PFS] //BAD RECLEN// at offset [", std::hex, total_read, "]");
+ break;
+ }
+
+ if (entry->d_namlen == 0) {
+ LogError("[PFS] //BAD FILENAME// at offset [", std::hex, total_read, "]");
+ break;
+ }
+
+ if (entry->d_namlen != target_file_name_length) continue;
+
+ if (strncmp(entry->d_name, target_file_name, target_file_name_length) == 0) {
+ memcpy(dirent, entry, entry->d_reclen);
+ found = true;
+ break;
+ }
+ }
+
+ if (read_bytes < DIRENT_PFS_BUFFER_SIZE) break;
+
+ if (found) break;
+
+ read_bytes = sceKernelRead(fd, buffer, DIRENT_PFS_BUFFER_SIZE);
+ }
+
+ fd = sceKernelClose(fd);
+ if (fd < 0) {
+ LogError("[PFS] Cannot close", target_file_name);
+ return -1;
+ }
+
+ return found;
+}
+
+s8 GetDir(fs::path path, fs::path leaf, oi::FolderDirent* dirent) {
+ const char* target_file_name = leaf.c_str();
+ const u16 target_file_name_length = leaf.string().size();
+ char buffer[DIRENT_BUFFER_SIZE];
+ char* bufptr;
+ char* bufend;
+ u64 total_read {0};
+ s64 diff;
+ bool found {false};
+
+ int fd = sceKernelOpen(path.c_str(), 0, 0777);
+ if (fd < 0) {
+ LogError("[Normal] Cannot open [", target_file_name, "]");
+ return -1;
+ }
+
+ s64 read_bytes = sceKernelGetdirentries(fd, buffer, DIRENT_BUFFER_SIZE, nullptr);
+
+ // redundant
+ while (read_bytes > 0 && !found) {
+ total_read += read_bytes;
+ bufptr = buffer;
+ bufend = buffer + read_bytes;
+
+ while (bufptr < bufend) {
+ oi::FolderDirent* entry = (oi::FolderDirent*)bufptr;
+ bufptr += static_cast(entry->d_reclen);
+
+ if (entry->d_reclen == 0) {
+ LogError("[Normal] //BAD RECLEN// at offset [", std::hex, total_read, "]");
+ break;
+ }
+
+ if (entry->d_namlen == 0) {
+ LogError("[Normal] //BAD FILENAME// at offset [", std::hex, total_read, "]");
+ break;
+ }
+
+ if (entry->d_namlen != target_file_name_length) continue;
+
+ if (strncmp(entry->d_name, target_file_name, target_file_name_length) == 0) {
+ memcpy(dirent, entry, sizeof(oi::FolderDirent));
+ found = true;
+ break;
+ }
+ }
+
+ if (found) break;
+
+ // read into after saved remainder
+ read_bytes = sceKernelGetdirentries(fd, buffer, DIRENT_BUFFER_SIZE, nullptr);
+ }
+
+ fd = sceKernelClose(fd);
+ if (fd < 0) {
+ LogError("[Normal] Cannot close", target_file_name);
+ return -1;
+ }
+
+ return found;
+
+} // namespace FS_Test
\ No newline at end of file
diff --git a/tests/code/filesystem_test/code/log.cpp b/tests/code/filesystem_test/code/log.cpp
new file mode 100644
index 00000000..150261bb
--- /dev/null
+++ b/tests/code/filesystem_test/code/log.cpp
@@ -0,0 +1,52 @@
+#include "log.h"
+
+#include
+#include
+
+std::ostream& center(std::ostream& os, const std::string& s, int width) {
+ int len = (int)s.size();
+ if (width <= len) return os << s.substr(0, width);
+ int left = (width - len) / 2;
+ int right = width - len - left;
+ return os << std::string(left, ' ') << s << std::string(right, ' ');
+}
+
+std::ostream& right(std::ostream& os, const std::string& s, int width) {
+ int len = (int)s.size();
+ if (width <= len) return os << s.substr(0, width);
+ int left = (width - len);
+ return os << std::string(left, ' ') << s;
+}
+
+std::string center(const std::string& s, int width) {
+ int len = (int)s.size();
+ if (width <= len) return s.substr(0, width);
+ int left = (width - len) / 2;
+ int right = width - len - left;
+ return std::string(left, ' ') + s + std::string(right, ' ');
+}
+
+std::string right(const std::string& s, int width) {
+ int len = (int)s.size();
+ if (width <= len) return s.substr(0, width);
+ int left = (width - len);
+ return std::string(left, ' ') + s;
+}
+
+std::string to_decimal(int value) {
+ std::ostringstream oss;
+ oss << std::dec << value;
+ return oss.str();
+}
+
+std::string to_octal(int value) {
+ std::ostringstream oss;
+ oss << std::oct << value;
+ return oss.str();
+}
+
+std::string to_hex(int value) {
+ std::ostringstream oss;
+ oss << std::hex << value;
+ return oss.str();
+}
\ No newline at end of file
diff --git a/tests/code/filesystem_test/code/log.h b/tests/code/filesystem_test/code/log.h
new file mode 100644
index 00000000..f4d0785d
--- /dev/null
+++ b/tests/code/filesystem_test/code/log.h
@@ -0,0 +1,55 @@
+#pragma once
+
+#ifndef LOG_H
+#define LOG_H
+
+#include
+#include
+
+#define STR(x) std::to_string(x)
+
+std::ostream& center(std::ostream& os, const std::string& s, int width);
+std::string center(const std::string& s, int width);
+std::ostream& right(std::ostream& os, const std::string& s, int width);
+std::string right(const std::string& s, int width);
+std::string to_decimal(int value);
+std::string to_octal(int value);
+std::string to_hex(int value);
+
+template
+void LogCustom(const char* fn, const char* msg, Args&&... args) {
+ std::cout << "[" << center(fn, 20) << "] " << msg;
+ ((std::cout << " " << args), ...);
+ std::cout << std::endl;
+}
+
+#define Log(...) \
+ { \
+ LogCustom(__FUNCTION__, "[INFO]", ##__VA_ARGS__); \
+ }
+
+#define LogTest(...) \
+ { \
+ LogCustom(__FUNCTION__, "\033[34;1m[TEST_CASE]\033[0m", ##__VA_ARGS__); \
+ }
+
+#define LogError(...) \
+ { \
+ LogCustom(__FUNCTION__, "\033[31;1m[FAIL]\033[0m", ##__VA_ARGS__, "( " __FILE__ ":", __LINE__, ")"); \
+ }
+
+#define LogSuccess(...) \
+ { \
+ LogCustom(__FUNCTION__, "\033[32;1m[SUCC]\033[0m", ##__VA_ARGS__); \
+ }
+
+#define TEST_CASE(cond, success_str, fail_str, ...) \
+ { \
+ if (cond) { \
+ LogSuccess(success_str, ##__VA_ARGS__); \
+ } else { \
+ LogError(fail_str, ##__VA_ARGS__); \
+ } \
+ }
+
+#endif
\ No newline at end of file
diff --git a/tests/code/filesystem_test/code/main.cpp b/tests/code/filesystem_test/code/main.cpp
new file mode 100644
index 00000000..21be268d
--- /dev/null
+++ b/tests/code/filesystem_test/code/main.cpp
@@ -0,0 +1,30 @@
+#include "fs_test.h"
+#include "log.h"
+
+#include
+#include
+
+IMPORT_TEST_GROUP(FilesystemTests);
+
+int main(int ac, char** av) {
+ // No buffering
+ setvbuf(stdout, NULL, _IONBF, 0);
+
+ // Log tests start
+ Log();
+ Log("<<<< TESTS START >>>>");
+ Log();
+
+ // Run file system tests
+ RegenerateDir("/data/therapist");
+ RunTests();
+ int result = RUN_ALL_TESTS(ac, av);
+
+ // Log tests end
+ Log();
+ Log("<<<< TESTS END >>>>");
+ Log();
+
+ sceSystemServiceLoadExec("EXIT", nullptr);
+ return result;
+}
diff --git a/tests/code/filesystem_test/sce_sys/icon0.png b/tests/code/filesystem_test/sce_sys/icon0.png
new file mode 100644
index 00000000..20a851ef
Binary files /dev/null and b/tests/code/filesystem_test/sce_sys/icon0.png differ