Browse Source

Drstd with dlibc (#5)

* 完成drstd

* 1

* 1

* ft
GnoCiYeH 1 year ago
parent
commit
9670759b78
100 changed files with 6698 additions and 870 deletions
  1. 0 9
      .vscode/settings.json
  2. 5 4
      Cargo.toml
  3. 21 674
      LICENSE
  4. 39 50
      build.rs
  5. 4 0
      dlibc/.gitignore
  6. 59 0
      dlibc/Cargo.toml
  7. 301 0
      dlibc/build.rs
  8. 0 0
      dlibc/core_io/.gitignore
  9. 0 0
      dlibc/core_io/Cargo.toml
  10. 0 0
      dlibc/core_io/LICENSE-APACHE
  11. 0 0
      dlibc/core_io/LICENSE-MIT
  12. 0 0
      dlibc/core_io/README.md
  13. 0 0
      dlibc/core_io/build-src.sh
  14. 0 0
      dlibc/core_io/build.rs
  15. 0 0
      dlibc/core_io/doc.sh
  16. 0 0
      dlibc/core_io/edit-patches.sh
  17. 0 0
      dlibc/core_io/functions.sh
  18. 0 0
      dlibc/core_io/mapping.rs
  19. 0 0
      dlibc/core_io/publish.sh
  20. 0 0
      dlibc/core_io/src/b9adc3327ec7d2820ab2db8bb3cc2a0196a8375d/buffered.rs
  21. 0 0
      dlibc/core_io/src/b9adc3327ec7d2820ab2db8bb3cc2a0196a8375d/cursor.rs
  22. 0 0
      dlibc/core_io/src/b9adc3327ec7d2820ab2db8bb3cc2a0196a8375d/error.rs
  23. 0 0
      dlibc/core_io/src/b9adc3327ec7d2820ab2db8bb3cc2a0196a8375d/impls.rs
  24. 0 0
      dlibc/core_io/src/b9adc3327ec7d2820ab2db8bb3cc2a0196a8375d/mod.rs
  25. 0 0
      dlibc/core_io/src/b9adc3327ec7d2820ab2db8bb3cc2a0196a8375d/prelude.rs
  26. 0 0
      dlibc/core_io/src/b9adc3327ec7d2820ab2db8bb3cc2a0196a8375d/util.rs
  27. 0 0
      dlibc/core_io/src/lib.rs
  28. 3 0
      dlibc/posix-regex/.gitignore
  29. 29 0
      dlibc/posix-regex/.gitlab-ci.yml
  30. 16 0
      dlibc/posix-regex/Cargo.toml
  31. 21 0
      dlibc/posix-regex/LICENSE
  32. 6 0
      dlibc/posix-regex/README.md
  33. 1 0
      dlibc/posix-regex/rust-toolchain
  34. 0 0
      dlibc/posix-regex/src/bench.rs
  35. 477 0
      dlibc/posix-regex/src/compile.rs
  36. 40 0
      dlibc/posix-regex/src/ctype.rs
  37. 29 0
      dlibc/posix-regex/src/lib.rs
  38. 752 0
      dlibc/posix-regex/src/matcher.rs
  39. 146 0
      dlibc/src/lib.rs
  40. 343 0
      dlibc/src/macros.rs
  41. 6 0
      dlibc/src/unix/align.rs
  42. 21 21
      dlibc/src/unix/c_str.rs
  43. 3 3
      dlibc/src/unix/c_vec.rs
  44. 0 0
      dlibc/src/unix/crt0/mod.rs
  45. 20 20
      dlibc/src/unix/fs.rs
  46. 9 0
      dlibc/src/unix/header/_aio/cbindgen.toml
  47. 59 0
      dlibc/src/unix/header/_aio/mod.rs
  48. 9 0
      dlibc/src/unix/header/_fenv/cbindgen.toml
  49. 68 0
      dlibc/src/unix/header/_fenv/mod.rs
  50. 7 0
      dlibc/src/unix/header/arch_aarch64_user/cbindgen.toml
  51. 29 0
      dlibc/src/unix/header/arch_aarch64_user/mod.rs
  52. 7 0
      dlibc/src/unix/header/arch_x64_user/cbindgen.toml
  53. 81 0
      dlibc/src/unix/header/arch_x64_user/mod.rs
  54. 12 0
      dlibc/src/unix/header/arpa_inet/cbindgen.toml
  55. 156 0
      dlibc/src/unix/header/arpa_inet/mod.rs
  56. 12 0
      dlibc/src/unix/header/assert/cbindgen.toml
  57. 18 0
      dlibc/src/unix/header/assert/mod.rs
  58. 0 0
      dlibc/src/unix/header/ctype/cbindgen.toml
  59. 103 0
      dlibc/src/unix/header/ctype/mod.rs
  60. 0 0
      dlibc/src/unix/header/dirent/cbindgen.toml
  61. 32 42
      dlibc/src/unix/header/dirent/mod.rs
  62. 0 0
      dlibc/src/unix/header/dl-tls/cbindgen.toml
  63. 5 4
      dlibc/src/unix/header/dl-tls/mod.rs
  64. 9 0
      dlibc/src/unix/header/dlfcn/cbindgen.toml
  65. 122 0
      dlibc/src/unix/header/dlfcn/mod.rs
  66. 9 0
      dlibc/src/unix/header/elf/cbindgen.toml
  67. 1005 0
      dlibc/src/unix/header/elf/mod.rs
  68. 0 0
      dlibc/src/unix/header/errno/cbindgen.toml
  69. 298 0
      dlibc/src/unix/header/errno/mod.rs
  70. 0 0
      dlibc/src/unix/header/fcntl/cbindgen.toml
  71. 32 0
      dlibc/src/unix/header/fcntl/mod.rs
  72. 9 0
      dlibc/src/unix/header/float/cbindgen.toml
  73. 14 0
      dlibc/src/unix/header/float/mod.rs
  74. 8 0
      dlibc/src/unix/header/fnmatch/cbindgen.toml
  75. 141 0
      dlibc/src/unix/header/fnmatch/mod.rs
  76. 0 0
      dlibc/src/unix/header/getopt/cbindgen.toml
  77. 40 43
      dlibc/src/unix/header/getopt/mod.rs
  78. 12 0
      dlibc/src/unix/header/grp/cbindgen.toml
  79. 65 0
      dlibc/src/unix/header/grp/mod.rs
  80. 10 0
      dlibc/src/unix/header/inttypes/cbindgen.toml
  81. 75 0
      dlibc/src/unix/header/inttypes/mod.rs
  82. 0 0
      dlibc/src/unix/header/libgen/cbindgen.toml
  83. 45 0
      dlibc/src/unix/header/libgen/mod.rs
  84. 0 0
      dlibc/src/unix/header/limits/cbindgen.toml
  85. 0 0
      dlibc/src/unix/header/limits/mod.rs
  86. 9 0
      dlibc/src/unix/header/locale/cbindgen.toml
  87. 70 0
      dlibc/src/unix/header/locale/mod.rs
  88. 67 0
      dlibc/src/unix/header/mod.rs
  89. 13 0
      dlibc/src/unix/header/netdb/cbindgen.toml
  90. 21 0
      dlibc/src/unix/header/netdb/dns/answer.rs
  91. 212 0
      dlibc/src/unix/header/netdb/dns/mod.rs
  92. 18 0
      dlibc/src/unix/header/netdb/dns/query.rs
  93. 29 0
      dlibc/src/unix/header/netdb/dragonos.rs
  94. 124 0
      dlibc/src/unix/header/netdb/host.rs
  95. 29 0
      dlibc/src/unix/header/netdb/linux.rs
  96. 256 0
      dlibc/src/unix/header/netdb/lookup.rs
  97. 911 0
      dlibc/src/unix/header/netdb/mod.rs
  98. 9 0
      dlibc/src/unix/header/netdb/redox.rs
  99. 13 0
      dlibc/src/unix/header/netinet_in/cbindgen.toml
  100. 74 0
      dlibc/src/unix/header/netinet_in/mod.rs

+ 0 - 9
.vscode/settings.json

@@ -1,14 +1,5 @@
 {
     "rust-analyzer.linkedProjects": [
         "./Cargo.toml",
-        "./Cargo.toml",
-        "./Cargo.toml",
-        "./Cargo.toml",
-        "./Cargo.toml",
-        "./Cargo.toml",
-        "./Cargo.toml",
-        "./Cargo.toml",
-        "./Cargo.toml",
-        "./Cargo.toml"
     ]
 }

+ 5 - 4
Cargo.toml

@@ -9,9 +9,8 @@ edition = "2021"
 #name = "drstd"
 #crate-type = ["staticlib"]
 
-[workspace]
-members = ["src/ld_so"]
-exclude = ["core_io"]
+#[workspace]
+members = [ "dlibc" ]
 
 [build-dependencies]
 cbindgen = "0.24.3"
@@ -19,13 +18,15 @@ cc = "1.0.25"
 
 [dependencies]
 cbitset = "0.1.0"
-core_io = { path = "core_io", features = ["collections"] }
 lazy_static = { version = "1.4.0", default-features = false, features = ["spin_no_std"] }
 memoffset = "0.5.1"
 rand = { version = "0.5.5", default-features = false }
 memchr = { version = "2.2.0", default-features = false }
 plain = "0.2"
 unicode-width = "0.1"
+hashbrown = { version = "0.14", default-features = false}
+cfg-if = { version = "1.0"}
+dlibc = {path = "dlibc"}
 
 [dependencies.goblin]
 version = "0.0.21"

+ 21 - 674
LICENSE

@@ -1,674 +1,21 @@
-                    GNU GENERAL PUBLIC LICENSE
-                       Version 3, 29 June 2007
-
- Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
- 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.
-
-    <one line to give the program's name and a brief idea of what it does.>
-    Copyright (C) <year>  <name of author>
-
-    This program is free software: you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation, either version 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 <https://www.gnu.org/licenses/>.
-
-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:
-
-    <program>  Copyright (C) <year>  <name of author>
-    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
-<https://www.gnu.org/licenses/>.
-
-  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
-<https://www.gnu.org/licenses/why-not-lgpl.html>.
+MIT License
+
+Copyright (c) 2022 DragonOS
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.

+ 39 - 50
build.rs

@@ -12,26 +12,26 @@ fn include_dir(d: &DirEntry) -> bool {
             .map_or(false, |c| c.to_str().map_or(false, |x| !x.starts_with("_")))
 }
 
-fn generate_bindings(cbindgen_config_path: &Path) {
-    let relative_path = cbindgen_config_path
-        .strip_prefix("src/header")
-        .ok()
-        .and_then(|p| p.parent())
-        .and_then(|p| p.to_str())
-        .unwrap()
-        .replace("_", "/");
-    let header_path = Path::new("target/include")
-        .join(&relative_path)
-        .with_extension("h");
-    let mod_path = cbindgen_config_path.with_file_name("mod.rs");
-    let config = cbindgen::Config::from_file(cbindgen_config_path).unwrap();
-    cbindgen::Builder::new()
-        .with_config(config)
-        .with_src(mod_path)
-        .generate()
-        .expect("Unable to generate bindings")
-        .write_to_file(header_path);
-}
+// fn generate_bindings(cbindgen_config_path: &Path) {
+//     let relative_path = cbindgen_config_path
+//         .strip_prefix("src/header")
+//         .ok()
+//         .and_then(|p| p.parent())
+//         .and_then(|p| p.to_str())
+//         .unwrap()
+//         .replace("_", "/");
+//     let header_path = Path::new("target/include")
+//         .join(&relative_path)
+//         .with_extension("h");
+//     let mod_path = cbindgen_config_path.with_file_name("mod.rs");
+//     let config = cbindgen::Config::from_file(cbindgen_config_path).unwrap();
+//     cbindgen::Builder::new()
+//         .with_config(config)
+//         .with_src(mod_path)
+//         .generate()
+//         .expect("Unable to generate bindings")
+//         .write_to_file(header_path);
+// }
 
 fn main() {
     let crate_dir = env::var("CARGO_MANIFEST_DIR").expect("CARGO_MANIFEST_DIR not set");
@@ -39,34 +39,23 @@ fn main() {
     // Generate C includes
     // - based on contents of src/header/**
     // - headers written to target/include
-    fs::read_dir(&Path::new("src/header"))
-        .unwrap()
-        .into_iter()
-        .filter_map(Result::ok)
-        .filter(|d| include_dir(d))
-        .map(|d| d.path().as_path().join("cbindgen.toml"))
-        .filter(|p| p.exists())
-        .for_each(|p| {
-            println!("cargo:rerun-if-changed={:?}", p.parent().unwrap());
-            println!("cargo:rerun-if-changed={:?}", p);
-            println!("cargo:rerun-if-changed={:?}", p.with_file_name("mod.rs"));
-            generate_bindings(&p);
-        });
-
-    let mut c = cc::Build::new();
-    c.flag("-nostdinc")
-        .flag("-nostdlib")
-        .flag("-fno-stack-protector")
-        .flag("-Wno-expansion-to-defined")
-        .file("src/platform/c/dragonos_malloc.c");
-
-    #[cfg(target_os = "dragonos")]
-    {
-        // for dragonos only
-        c.define("HAVE_MMAP", "0");
-    }
-
-    c.compile("drstd_c");
-
-    println!("cargo:rustc-link-lib=static=drstd_c");
+    // fs::read_dir(&Path::new("src/header"))
+    //     .unwrap()
+    //     .into_iter()
+    //     .filter_map(Result::ok)
+    //     .filter(|d| include_dir(d))
+    //     .map(|d| d.path().as_path().join("cbindgen.toml"))
+    //     .filter(|p| p.exists())
+    //     .for_each(|p| {
+    //         println!("cargo:rerun-if-changed={:?}", p.parent().unwrap());
+    //         println!("cargo:rerun-if-changed={:?}", p);
+    //         println!("cargo:rerun-if-changed={:?}", p.with_file_name("mod.rs"));
+    //         generate_bindings(&p);
+    //     });
+
+    // // 指定链接搜索路径
+    // println!("cargo:rustc-link-search=native=./dlibc");
+
+    // // 链接 dlibc 库
+    // println!("cargo:rustc-link-lib=dlibc");
 }

+ 4 - 0
dlibc/.gitignore

@@ -0,0 +1,4 @@
+target
+Cargo.lock
+*~
+style

+ 59 - 0
dlibc/Cargo.toml

@@ -0,0 +1,59 @@
+[package]
+name = "dlibc"
+version = "0.1.0"
+authors = ["The Rust Project Developers"]
+license = "MIT OR Apache-2.0"
+readme = "README.md"
+repository = "https://github.com/rust-lang/libc"
+homepage = "https://github.com/rust-lang/libc"
+documentation = "https://docs.rs/libc/"
+keywords = ["libc", "ffi", "bindings", "operating", "system"]
+categories = ["external-ffi-bindings", "no-std", "os"]
+build = "build.rs"
+exclude = ["/ci/*", "/.github/*", "/.cirrus.yml", "/triagebot.toml"]
+description = """
+Raw FFI bindings to platform libraries like libc.
+"""
+
+#[lib]
+#name = "dlibc"
+#crate-type = ["staticlib"]
+
+[build-dependencies]
+cbindgen = "0.24.3"
+cc = "1.0.25"
+
+[package.metadata.docs.rs]
+features = ["const-extern-fn", "extra_traits"]
+default-target = "x86_64-unknown-dragonos"
+cargo-args = ["-Zbuild-std=core,alloc,compiler_builtins"]
+
+[dependencies]
+cbitset = "0.1.0"
+rustc-std-workspace-core = { version = "1.0.0", optional = true }
+rand = { version = "0.5.5", default-features = false }
+core_io = { path = "core_io", features = ["collections"] }
+lazy_static = { version = "1.4.0", default-features = false, features = ["spin_no_std"] }
+unicode-width = "0.1"
+memchr = { version = "2.2.0", default-features = false }
+posix-regex = { path = "posix-regex", features = ["no_std"] }
+num-traits =  { version = "0.2.16", default-features = false }
+
+[dependencies.goblin]
+version = "0.0.21"
+default-features = false
+features = ["elf32", "elf64", "endian_fd"]
+
+[target.'cfg(target_os = "dragonos")'.dependencies]
+# Development
+dragonos-dsc = { git = "https://github.com/DragonOS-Community/dsc.git", rev = "d6e4fd8" }
+
+[features]
+default = ["std"]
+std = []
+align = []
+rustc-dep-of-std = ['align', 'rustc-std-workspace-core']
+extra_traits = []
+const-extern-fn = []
+# use_std is deprecated, use `std` instead
+use_std = ['std']

+ 301 - 0
dlibc/build.rs

@@ -0,0 +1,301 @@
+use std::env;
+use std::process::Command;
+use std::str;
+use std::string::String;
+
+// List of cfgs this build script is allowed to set. The list is needed to support check-cfg, as we
+// need to know all the possible cfgs that this script will set. If you need to set another cfg
+// make sure to add it to this list as well.
+const ALLOWED_CFGS: &'static [&'static str] = &[
+    "emscripten_new_stat_abi",
+    "freebsd10",
+    "freebsd11",
+    "freebsd12",
+    "freebsd13",
+    "freebsd14",
+    "libc_align",
+    "libc_cfg_target_vendor",
+    "libc_const_extern_fn",
+    "libc_const_extern_fn_unstable",
+    "libc_const_size_of",
+    "libc_core_cvoid",
+    "libc_deny_warnings",
+    "libc_int128",
+    "libc_long_array",
+    "libc_non_exhaustive",
+    "libc_packedN",
+    "libc_priv_mod_use",
+    "libc_ptr_addr_of",
+    "libc_thread_local",
+    "libc_underscore_const_names",
+    "libc_union",
+];
+
+// Extra values to allow for check-cfg.
+const CHECK_CFG_EXTRA: &'static [(&'static str, &'static [&'static str])] = &[
+    ("target_os", &["switch", "aix", "ohos"]),
+    ("target_env", &["illumos", "wasi", "aix", "ohos"]),
+    (
+        "target_arch",
+        &["loongarch64", "mips32r6", "mips64r6", "csky"],
+    ),
+];
+
+fn main() {
+    // Avoid unnecessary re-building.
+    println!("cargo:rerun-if-changed=build.rs");
+
+    let (rustc_minor_ver, is_nightly) = rustc_minor_nightly();
+    let rustc_dep_of_std = env::var("CARGO_FEATURE_RUSTC_DEP_OF_STD").is_ok();
+    let align_cargo_feature = env::var("CARGO_FEATURE_ALIGN").is_ok();
+    let const_extern_fn_cargo_feature = env::var("CARGO_FEATURE_CONST_EXTERN_FN").is_ok();
+    let libc_ci = env::var("LIBC_CI").is_ok();
+    let libc_check_cfg = env::var("LIBC_CHECK_CFG").is_ok();
+
+    if env::var("CARGO_FEATURE_USE_STD").is_ok() {
+        println!(
+            "cargo:warning=\"libc's use_std cargo feature is deprecated since libc 0.2.55; \
+             please consider using the `std` cargo feature instead\""
+        );
+    }
+
+    // The ABI of libc used by libstd is backward compatible with FreeBSD 10.
+    // The ABI of libc from crates.io is backward compatible with FreeBSD 11.
+    //
+    // On CI, we detect the actual FreeBSD version and match its ABI exactly,
+    // running tests to ensure that the ABI is correct.
+    match which_freebsd() {
+        Some(10) if libc_ci || rustc_dep_of_std => set_cfg("freebsd10"),
+        Some(11) if libc_ci => set_cfg("freebsd11"),
+        Some(12) if libc_ci => set_cfg("freebsd12"),
+        Some(13) if libc_ci => set_cfg("freebsd13"),
+        Some(14) if libc_ci => set_cfg("freebsd14"),
+        Some(_) | None => set_cfg("freebsd11"),
+    }
+
+    match emcc_version_code() {
+        Some(v) if (v >= 30142) => set_cfg("emscripten_new_stat_abi"),
+        // Non-Emscripten or version < 3.1.42.
+        Some(_) | None => (),
+    }
+
+    // On CI: deny all warnings
+    if libc_ci {
+        set_cfg("libc_deny_warnings");
+    }
+
+    // Rust >= 1.15 supports private module use:
+    if rustc_minor_ver >= 15 || rustc_dep_of_std {
+        set_cfg("libc_priv_mod_use");
+    }
+
+    // Rust >= 1.19 supports unions:
+    if rustc_minor_ver >= 19 || rustc_dep_of_std {
+        set_cfg("libc_union");
+    }
+
+    // Rust >= 1.24 supports const mem::size_of:
+    if rustc_minor_ver >= 24 || rustc_dep_of_std {
+        set_cfg("libc_const_size_of");
+    }
+
+    // Rust >= 1.25 supports repr(align):
+    if rustc_minor_ver >= 25 || rustc_dep_of_std || align_cargo_feature {
+        set_cfg("libc_align");
+    }
+
+    // Rust >= 1.26 supports i128 and u128:
+    if rustc_minor_ver >= 26 || rustc_dep_of_std {
+        set_cfg("libc_int128");
+    }
+
+    // Rust >= 1.30 supports `core::ffi::c_void`, so libc can just re-export it.
+    // Otherwise, it defines an incompatible type to retaining
+    // backwards-compatibility.
+    if rustc_minor_ver >= 30 || rustc_dep_of_std {
+        set_cfg("libc_core_cvoid");
+    }
+
+    // Rust >= 1.33 supports repr(packed(N)) and cfg(target_vendor).
+    if rustc_minor_ver >= 33 || rustc_dep_of_std {
+        set_cfg("libc_packedN");
+        set_cfg("libc_cfg_target_vendor");
+    }
+
+    // Rust >= 1.40 supports #[non_exhaustive].
+    if rustc_minor_ver >= 40 || rustc_dep_of_std {
+        set_cfg("libc_non_exhaustive");
+    }
+
+    // Rust >= 1.47 supports long array:
+    if rustc_minor_ver >= 47 || rustc_dep_of_std {
+        set_cfg("libc_long_array");
+    }
+
+    if rustc_minor_ver >= 51 || rustc_dep_of_std {
+        set_cfg("libc_ptr_addr_of");
+    }
+
+    // Rust >= 1.37.0 allows underscores as anonymous constant names.
+    if rustc_minor_ver >= 37 || rustc_dep_of_std {
+        set_cfg("libc_underscore_const_names");
+    }
+
+    // #[thread_local] is currently unstable
+    if rustc_dep_of_std {
+        set_cfg("libc_thread_local");
+    }
+
+    // Rust >= 1.62.0 allows to use `const_extern_fn` for "Rust" and "C".
+    if rustc_minor_ver >= 62 {
+        set_cfg("libc_const_extern_fn");
+    } else {
+        // Rust < 1.62.0 requires a crate feature and feature gate.
+        if const_extern_fn_cargo_feature {
+            if !is_nightly || rustc_minor_ver < 40 {
+                panic!("const-extern-fn requires a nightly compiler >= 1.40");
+            }
+            set_cfg("libc_const_extern_fn_unstable");
+            set_cfg("libc_const_extern_fn");
+        }
+    }
+
+    // check-cfg is a nightly cargo/rustc feature to warn when unknown cfgs are used across the
+    // codebase. libc can configure it if the appropriate environment variable is passed. Since
+    // rust-lang/rust enforces it, this is useful when using a custom libc fork there.
+    //
+    // https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#check-cfg
+    if libc_check_cfg {
+        for cfg in ALLOWED_CFGS {
+            println!("cargo:rustc-check-cfg=values({})", cfg);
+        }
+        for &(name, values) in CHECK_CFG_EXTRA {
+            let values = values.join("\",\"");
+            println!("cargo:rustc-check-cfg=values({},\"{}\")", name, values);
+        }
+    }
+
+    //TODO:增加平台内存分配器
+    //#[cfg(target_os = "dragonos")]
+    let mut c = cc::Build::new();
+    //#[cfg(target_os = "dragonos")]
+    c.flag("-nostdinc")
+    .flag("-nostdlib")
+    .flag("-fno-stack-protector")
+    .flag("-Wno-expansion-to-defined")
+    .file("src/unix/platform/dragonos/c/dragonos_malloc.c");
+    //#[cfg(target_os = "dragonos")]
+    c.define("HAVE_MMAP", "0");
+    //#[cfg(target_os = "dragonos")]
+    c.compile("dlibc_c");
+    //#[cfg(target_os = "dragonos")]
+    println!("cargo:rustc-link-lib=static=dlibc_c");
+        
+    
+}
+
+fn rustc_minor_nightly() -> (u32, bool) {
+    macro_rules! otry {
+        ($e:expr) => {
+            match $e {
+                Some(e) => e,
+                None => panic!("Failed to get rustc version"),
+            }
+        };
+    }
+
+    let rustc = otry!(env::var_os("RUSTC"));
+    let output = Command::new(rustc)
+        .arg("--version")
+        .output()
+        .ok()
+        .expect("Failed to get rustc version");
+    if !output.status.success() {
+        panic!(
+            "failed to run rustc: {}",
+            String::from_utf8_lossy(output.stderr.as_slice())
+        );
+    }
+
+    let version = otry!(str::from_utf8(&output.stdout).ok());
+    let mut pieces = version.split('.');
+
+    if pieces.next() != Some("rustc 1") {
+        panic!("Failed to get rustc version");
+    }
+
+    let minor = pieces.next();
+
+    // If `rustc` was built from a tarball, its version string
+    // will have neither a git hash nor a commit date
+    // (e.g. "rustc 1.39.0"). Treat this case as non-nightly,
+    // since a nightly build should either come from CI
+    // or a git checkout
+    let nightly_raw = otry!(pieces.next()).split('-').nth(1);
+    let nightly = nightly_raw
+        .map(|raw| raw.starts_with("dev") || raw.starts_with("nightly"))
+        .unwrap_or(false);
+    let minor = otry!(otry!(minor).parse().ok());
+
+    (minor, nightly)
+}
+
+fn which_freebsd() -> Option<i32> {
+    let output = std::process::Command::new("freebsd-version").output().ok();
+    if output.is_none() {
+        return None;
+    }
+    let output = output.unwrap();
+    if !output.status.success() {
+        return None;
+    }
+
+    let stdout = String::from_utf8(output.stdout).ok();
+    if stdout.is_none() {
+        return None;
+    }
+    let stdout = stdout.unwrap();
+
+    match &stdout {
+        s if s.starts_with("10") => Some(10),
+        s if s.starts_with("11") => Some(11),
+        s if s.starts_with("12") => Some(12),
+        s if s.starts_with("13") => Some(13),
+        s if s.starts_with("14") => Some(14),
+        _ => None,
+    }
+}
+
+fn emcc_version_code() -> Option<u64> {
+    let output = std::process::Command::new("emcc")
+        .arg("-dumpversion")
+        .output()
+        .ok();
+    if output.is_none() {
+        return None;
+    }
+    let output = output.unwrap();
+    if !output.status.success() {
+        return None;
+    }
+
+    let stdout = String::from_utf8(output.stdout).ok();
+    if stdout.is_none() {
+        return None;
+    }
+    let version = stdout.unwrap();
+    let mut pieces = version.trim().split('.');
+
+    let major = pieces.next().and_then(|x| x.parse().ok()).unwrap_or(0);
+    let minor = pieces.next().and_then(|x| x.parse().ok()).unwrap_or(0);
+    let patch = pieces.next().and_then(|x| x.parse().ok()).unwrap_or(0);
+
+    Some(major * 10000 + minor * 100 + patch)
+}
+
+fn set_cfg(cfg: &str) {
+    if !ALLOWED_CFGS.contains(&cfg) {
+        panic!("trying to set cfg {}, but it is not in ALLOWED_CFGS", cfg);
+    }
+    println!("cargo:rustc-cfg={}", cfg);
+}

+ 0 - 0
core_io/.gitignore → dlibc/core_io/.gitignore


+ 0 - 0
core_io/Cargo.toml → dlibc/core_io/Cargo.toml


+ 0 - 0
core_io/LICENSE-APACHE → dlibc/core_io/LICENSE-APACHE


+ 0 - 0
core_io/LICENSE-MIT → dlibc/core_io/LICENSE-MIT


+ 0 - 0
core_io/README.md → dlibc/core_io/README.md


+ 0 - 0
core_io/build-src.sh → dlibc/core_io/build-src.sh


+ 0 - 0
core_io/build.rs → dlibc/core_io/build.rs


+ 0 - 0
core_io/doc.sh → dlibc/core_io/doc.sh


+ 0 - 0
core_io/edit-patches.sh → dlibc/core_io/edit-patches.sh


+ 0 - 0
core_io/functions.sh → dlibc/core_io/functions.sh


+ 0 - 0
core_io/mapping.rs → dlibc/core_io/mapping.rs


+ 0 - 0
core_io/publish.sh → dlibc/core_io/publish.sh


+ 0 - 0
core_io/src/b9adc3327ec7d2820ab2db8bb3cc2a0196a8375d/buffered.rs → dlibc/core_io/src/b9adc3327ec7d2820ab2db8bb3cc2a0196a8375d/buffered.rs


+ 0 - 0
core_io/src/b9adc3327ec7d2820ab2db8bb3cc2a0196a8375d/cursor.rs → dlibc/core_io/src/b9adc3327ec7d2820ab2db8bb3cc2a0196a8375d/cursor.rs


+ 0 - 0
core_io/src/b9adc3327ec7d2820ab2db8bb3cc2a0196a8375d/error.rs → dlibc/core_io/src/b9adc3327ec7d2820ab2db8bb3cc2a0196a8375d/error.rs


+ 0 - 0
core_io/src/b9adc3327ec7d2820ab2db8bb3cc2a0196a8375d/impls.rs → dlibc/core_io/src/b9adc3327ec7d2820ab2db8bb3cc2a0196a8375d/impls.rs


+ 0 - 0
core_io/src/b9adc3327ec7d2820ab2db8bb3cc2a0196a8375d/mod.rs → dlibc/core_io/src/b9adc3327ec7d2820ab2db8bb3cc2a0196a8375d/mod.rs


+ 0 - 0
core_io/src/b9adc3327ec7d2820ab2db8bb3cc2a0196a8375d/prelude.rs → dlibc/core_io/src/b9adc3327ec7d2820ab2db8bb3cc2a0196a8375d/prelude.rs


+ 0 - 0
core_io/src/b9adc3327ec7d2820ab2db8bb3cc2a0196a8375d/util.rs → dlibc/core_io/src/b9adc3327ec7d2820ab2db8bb3cc2a0196a8375d/util.rs


+ 0 - 0
core_io/src/lib.rs → dlibc/core_io/src/lib.rs


+ 3 - 0
dlibc/posix-regex/.gitignore

@@ -0,0 +1,3 @@
+/target
+**/*.rs.bk
+Cargo.lock

+ 29 - 0
dlibc/posix-regex/.gitlab-ci.yml

@@ -0,0 +1,29 @@
+# This file is a template, and might need editing before it works on your project.
+# Official language image. Look for the different tagged releases at:
+# https://hub.docker.com/r/library/rust/tags/
+image: "rust:latest"
+
+# Optional: Pick zero or more services to be used on all builds.
+# Only needed when using a docker container to run your tests in.
+# Check out: http://docs.gitlab.com/ce/ci/docker/using_docker_images.html#what-is-a-service
+#services:
+#  - mysql:latest
+#  - redis:latest
+#  - postgres:latest
+
+# Optional: Install a C compiler, cmake and git into the container.
+# You will often need this when you (or any of your dependencies) depends on C code.
+#before_script:
+#- apt-get update -yqq
+#- apt-get install -yqq --no-install-recommends build-essential
+
+# Use cargo to test the project
+test:default:
+  script:
+  - rustc --version && cargo --version      # Print version info for debugging
+  - cargo test
+
+test:no_std:
+  script:
+  - rustc --version && cargo --version      # Print version info for debugging
+  - cargo test --features no_std

+ 16 - 0
dlibc/posix-regex/Cargo.toml

@@ -0,0 +1,16 @@
+[package]
+authors = ["jD91mZM2 <[email protected]>"]
+categories = ["no-std", "parsing"]
+description = "A library for parsing POSIX regular expressions"
+keywords = ["no_std", "regex"]
+license = "MIT"
+name = "posix-regex"
+readme = "README.md"
+repository = "https://gitlab.redox-os.org/redox-os/posix-regex"
+version = "0.1.0"
+
+[dependencies]
+
+[features]
+bench = []
+no_std = []

+ 21 - 0
dlibc/posix-regex/LICENSE

@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2018 jD91mZM2
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.

+ 6 - 0
dlibc/posix-regex/README.md

@@ -0,0 +1,6 @@
+# posix-regex [![Crates.io](https://img.shields.io/crates/v/posix-regex.svg)](https://crates.io/crates/posix-regex)
+
+A library for parsing POSIX regular expressions. Only supports ASCII.  Created
+for use in relibc and does not require the std.
+
+Currently only supports basic enhanced regex.

+ 1 - 0
dlibc/posix-regex/rust-toolchain

@@ -0,0 +1 @@
+nightly-2018-11-07

+ 0 - 0
dlibc/posix-regex/src/bench.rs


+ 477 - 0
dlibc/posix-regex/src/compile.rs

@@ -0,0 +1,477 @@
+//! The regex "compiler", which parses the regex itself.
+//! Produces a matcher ready to match input.
+
+#[cfg(feature = "no_std")]
+use std::prelude::*;
+
+use std::borrow::Cow;
+use std::collections::HashMap;
+use std::fmt;
+use {ctype, PosixRegex};
+
+/// Repetition bounds, for example + is (1, None), and ? is (0, Some(1))
+#[derive(Clone, Copy, PartialEq, Eq)]
+pub struct Range(pub u32, pub Option<u32>);
+impl fmt::Debug for Range {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        match self {
+            Range(start, None) => write!(f, "{}..", start),
+            Range(start, Some(end)) => write!(f, "{}..{}", start, end),
+        }
+    }
+}
+
+/// An item inside square brackets, like `[abc]` or `[[:digit:]]`
+#[derive(Clone, Debug, PartialEq, Eq)]
+pub enum Collation {
+    Char(u8),
+    Class(fn(u8) -> bool)
+}
+impl Collation {
+    /// Compare this collation to a character
+    pub fn matches(&self, other: u8, insensitive: bool) -> bool {
+        match *self {
+            Collation::Char(me) if insensitive => me & !32 == other & !32,
+            Collation::Char(me) => me == other,
+            Collation::Class(f) => f(other)
+        }
+    }
+}
+
+/// A single "compiled" token, such as a `.` or a character literal
+#[derive(Clone, PartialEq, Eq)]
+pub enum Token {
+    InternalStart,
+
+    Any,
+    Char(u8),
+    End,
+    Group {
+        id: usize,
+        branches: Vec<Vec<(Token, Range)>>
+    },
+    OneOf {
+        invert: bool,
+        list: Vec<Collation>
+    },
+    Start,
+    WordEnd,
+    WordStart
+}
+impl fmt::Debug for Token {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        match *self {
+            Token::InternalStart => write!(f, "<START>"),
+
+            Token::Any => write!(f, "."),
+            Token::Char(c) => write!(f, "{:?}", c as char),
+            Token::End => write!(f, "$"),
+            Token::Group { ref branches, .. } => write!(f, "Group({:?})", branches),
+            Token::OneOf { invert, ref list } => write!(f, "[invert: {}; {:?}]", invert, list),
+            Token::Start => write!(f, "^"),
+            Token::WordEnd => write!(f, ">"),
+            Token::WordStart => write!(f, "<")
+        }
+    }
+}
+/// An error that occurred while compiling the regex
+#[derive(Clone, Debug, PartialEq, Eq)]
+pub enum Error {
+    EOF,
+    EmptyRepetition,
+    Expected(u8, Option<u8>),
+    IllegalRange,
+    IntegerOverflow,
+    LeadingRepetition,
+    UnclosedRepetition,
+    UnexpectedToken(u8),
+    UnknownClass(Vec<u8>),
+    UnknownCollation
+}
+
+/// A regex builder struct
+pub struct PosixRegexBuilder<'a> {
+    input: &'a [u8],
+    classes: HashMap<&'a [u8], fn(u8) -> bool>,
+    group_id: usize
+}
+impl<'a> PosixRegexBuilder<'a> {
+    /// Create a new instance that is ready to parse the regex `input`
+    pub fn new(input: &'a [u8]) -> Self {
+        Self {
+            input,
+            classes: HashMap::new(),
+            group_id: 1
+        }
+    }
+    /// Add a custom collation class, for use within square brackets (such as `[[:digit:]]`)
+    pub fn with_class(mut self, name: &'a [u8], callback: fn(u8) -> bool) -> Self {
+        self.classes.insert(name, callback);
+        self
+    }
+    /// Add all the default collation classes, like `[[:digit:]]` and `[[:alnum:]]`
+    pub fn with_default_classes(mut self) -> Self {
+        #[cfg(not(feature = "no_std"))]
+        self.classes.reserve(12);
+
+        self.classes.insert(b"alnum", ctype::is_alnum);
+        self.classes.insert(b"alpha", ctype::is_alpha);
+        self.classes.insert(b"blank", ctype::is_blank);
+        self.classes.insert(b"cntrl", ctype::is_cntrl);
+        self.classes.insert(b"digit", ctype::is_digit);
+        self.classes.insert(b"graph", ctype::is_graph);
+        self.classes.insert(b"lower", ctype::is_lower);
+        self.classes.insert(b"print", ctype::is_print);
+        self.classes.insert(b"punct", ctype::is_punct);
+        self.classes.insert(b"space", ctype::is_space);
+        self.classes.insert(b"upper", ctype::is_upper);
+        self.classes.insert(b"xdigit", ctype::is_xdigit);
+
+        self
+    }
+    /// "Compile" this regex to a struct ready to match input
+    pub fn compile(mut self) -> Result<PosixRegex<'static>, Error> {
+        let search = self.compile_tokens()?;
+        Ok(PosixRegex::new(Cow::Owned(search)))
+    }
+
+    fn consume(&mut self, amount: usize) {
+        self.input = &self.input[amount..];
+    }
+    fn take_int(&mut self) -> Result<Option<u32>, Error> {
+        let mut out: Option<u32> = None;
+        while let Some(&c @ b'0'..=b'9') = self.input.first() {
+            self.consume(1);
+            out = Some(out.unwrap_or(0)
+                .checked_mul(10)
+                .and_then(|out| out.checked_add((c - b'0') as u32))
+                .ok_or(Error::IntegerOverflow)?);
+        }
+        Ok(out)
+    }
+    fn next(&mut self) -> Result<u8, Error> {
+        self.input.first()
+            .map(|&c| { self.consume(1); c })
+            .ok_or(Error::EOF)
+    }
+    fn expect(&mut self, c: u8) -> Result<(), Error> {
+        if self.input.first() != Some(&c) {
+            return Err(Error::Expected(c, self.input.first().cloned()));
+        }
+        self.consume(1);
+        Ok(())
+    }
+    pub fn compile_tokens(&mut self) -> Result<Vec<Vec<(Token, Range)>>, Error> {
+        let mut alternatives = Vec::new();
+        let mut chain: Vec<(Token, Range)> = Vec::new();
+
+        while let Some(&c) = self.input.first() {
+            self.consume(1);
+            let token = match c {
+                b'^' => Token::Start,
+                b'$' => Token::End,
+                b'.' => Token::Any,
+                b'*' => if let Some(last) = chain.last_mut() {
+                    last.1 = Range(0, None);
+                    continue;
+                } else {
+                    return Err(Error::LeadingRepetition);
+                },
+                b'[' => {
+                    let mut list = Vec::new();
+                    let invert = self.input.first() == Some(&b'^');
+
+                    if invert {
+                        self.consume(1);
+                    }
+
+                    loop {
+                        let mut c = self.next()?;
+
+                        let mut push = true;
+
+                        if c == b'[' {
+                            // TODO: Handle collation characters properly,
+                            // because currently idk what they are and only
+                            // have the behavior of `grep` to go on.
+                            match self.next()? {
+                                b'.' => {
+                                    c = self.next()?;
+                                    self.expect(b'.')?;
+                                    self.expect(b']')?;
+                                },
+                                b'=' => {
+                                    c = self.next()?;
+                                    self.expect(b'=')?;
+                                    self.expect(b']')?;
+                                },
+                                b':' => {
+                                    let end = self.input.iter().position(|&c| c == b':').ok_or(Error::EOF)?;
+                                    let key = &self.input[..end];
+                                    let class = *self.classes.get(key).ok_or_else(|| Error::UnknownClass(key.to_vec()))?;
+                                    self.consume(end + 1);
+                                    self.expect(b']')?;
+
+                                    list.push(Collation::Class(class));
+                                    push = false;
+                                },
+                                _ => return Err(Error::UnknownCollation)
+                            }
+                        }
+
+                        if push {
+                            list.push(Collation::Char(c));
+
+                            if self.input.first() == Some(&b'-') && self.input.get(1) != Some(&b']') {
+                                self.consume(1);
+                                let dest = self.next()?;
+                                for c in (c+1)..=dest {
+                                    list.push(Collation::Char(c));
+                                }
+                            }
+                        }
+
+                        if self.input.first() == Some(&b']') {
+                            self.consume(1);
+                            break;
+                        }
+                    }
+
+                    Token::OneOf {
+                        invert,
+                        list
+                    }
+                },
+                b'\\' => match self.next()? {
+                    b'(' => {
+                        let id = self.group_id;
+                        self.group_id += 1;
+                        Token::Group {
+                            id,
+                            branches: self.compile_tokens()?
+                        }
+                    },
+                    b')' => {
+                        alternatives.push(chain);
+                        return Ok(alternatives);
+                    }
+                    b'|' => {
+                        alternatives.push(chain);
+                        chain = Vec::new();
+                        continue;
+                    },
+                    b'<' => Token::WordStart,
+                    b'>' => Token::WordEnd,
+                    c@b'?' | c@b'+' => if let Some(last) = chain.last_mut() {
+                        last.1 = match c {
+                            b'?' => Range(0, Some(1)),
+                            b'+' => Range(1, None),
+                            _ => unreachable!("{}", c)
+                        };
+                        continue;
+                    } else {
+                        return Err(Error::LeadingRepetition);
+                    },
+                    b'{' => if let Some(last) = chain.last_mut() {
+                        let first = self.take_int()?.ok_or(Error::EmptyRepetition)?;
+                        let mut second = Some(first);
+                        if let Some(b',') = self.input.first() {
+                            self.consume(1);
+                            second = self.take_int()?;
+                        }
+                        if self.input.first() == Some(&b'}') {
+                            self.consume(1);
+                        } else if self.input.starts_with(br"\}") {
+                            self.consume(2);
+                        } else {
+                            return Err(Error::UnclosedRepetition);
+                        }
+                        if second.map(|second| first > second).unwrap_or(false) {
+                            return Err(Error::IllegalRange);
+                        }
+                        last.1 = Range(first, second);
+                        continue;
+                    } else {
+                        return Err(Error::LeadingRepetition);
+                    },
+                    b'a' => Token::OneOf { invert: false, list: vec![Collation::Class(ctype::is_alnum)] },
+                    b'd' => Token::OneOf { invert: false, list: vec![Collation::Class(ctype::is_digit)] },
+                    b's' => Token::OneOf { invert: false, list: vec![Collation::Class(ctype::is_space)] },
+                    b'S' => Token::OneOf { invert: true,  list: vec![Collation::Class(ctype::is_space)] },
+                    b'n' => Token::Char(b'\n'),
+                    b'r' => Token::Char(b'\r'),
+                    b't' => Token::Char(b'\t'),
+                    c => Token::Char(c)
+                },
+                c => Token::Char(c)
+            };
+            chain.push((token, Range(1, Some(1))));
+        }
+
+        alternatives.push(chain);
+        Ok(alternatives)
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+
+    fn compile(input: &[u8]) -> Vec<(Token, Range)> {
+        PosixRegexBuilder::new(input)
+            .with_default_classes()
+            .compile_tokens()
+            .expect("error compiling regex")
+            .into_iter()
+            .next()
+            .unwrap()
+    }
+    fn t(t: Token) -> (Token, Range) {
+        (t, Range(1, Some(1)))
+    }
+    fn c(c: u8) -> (Token, Range) {
+        t(Token::Char(c))
+    }
+
+    #[test]
+    fn basic() {
+        assert_eq!(compile(b"abc"), &[c(b'a'), c(b'b'), c(b'c')]);
+    }
+    #[test]
+    fn groups() {
+        assert_eq!(compile(br"\(abc\|bcd\|cde\)"), &[t(Token::Group { id: 1, branches: vec![
+            vec![c(b'a'), c(b'b'), c(b'c')],
+            vec![c(b'b'), c(b'c'), c(b'd')],
+            vec![c(b'c'), c(b'd'), c(b'e')]
+        ]})]);
+        assert_eq!(compile(br"\(abc\|\(bcd\|cde\)\)"), &[
+            t(Token::Group { id: 1, branches: vec![
+                vec![c(b'a'), c(b'b'), c(b'c')],
+                vec![t(Token::Group { id: 2, branches: vec![
+                    vec![c(b'b'), c(b'c'), c(b'd')],
+                    vec![c(b'c'), c(b'd'), c(b'e')]
+                ]})]
+            ]})
+        ]);
+    }
+    #[test]
+    fn words() {
+        assert_eq!(
+            compile(br"\<word\>"),
+            &[t(Token::WordStart), c(b'w'), c(b'o'), c(b'r'), c(b'd'), t(Token::WordEnd)]
+        );
+    }
+    #[test]
+    fn repetitions() {
+        assert_eq!(
+            compile(br"yeee*"),
+            &[c(b'y'), c(b'e'), c(b'e'), (Token::Char(b'e'), Range(0, None))]
+        );
+        assert_eq!(
+            compile(br"yee\?"),
+            &[c(b'y'), c(b'e'), (Token::Char(b'e'), Range(0, Some(1)))]
+        );
+        assert_eq!(
+            compile(br"yee\+"),
+            &[c(b'y'), c(b'e'), (Token::Char(b'e'), Range(1, None))]
+        );
+        assert_eq!(
+            compile(br"ye\{2}"),
+            &[c(b'y'), (Token::Char(b'e'), Range(2, Some(2)))]
+        );
+        assert_eq!(
+            compile(br"ye\{2,}"),
+            &[c(b'y'), (Token::Char(b'e'), Range(2, None))]
+        );
+        assert_eq!(
+            compile(br"ye\{2,3}"),
+            &[c(b'y'), (Token::Char(b'e'), Range(2, Some(3)))]
+        );
+    }
+    #[test]
+    fn bracket() {
+        assert_eq!(
+            compile(b"[abc]"),
+            &[t(Token::OneOf {
+                invert: false,
+                list: vec![
+                    Collation::Char(b'a'),
+                    Collation::Char(b'b'),
+                    Collation::Char(b'c')
+                ]
+            })]
+        );
+        assert_eq!(
+            compile(b"[^abc]"),
+            &[t(Token::OneOf {
+                invert: true,
+                list: vec![
+                    Collation::Char(b'a'),
+                    Collation::Char(b'b'),
+                    Collation::Char(b'c')
+                ]
+            })]
+        );
+        assert_eq!(
+            compile(b"[]] [^]]"),
+            &[
+                t(Token::OneOf { invert: false, list: vec![ Collation::Char(b']') ] }),
+                c(b' '),
+                t(Token::OneOf { invert: true,  list: vec![ Collation::Char(b']') ] }),
+            ]
+        );
+        assert_eq!(
+            compile(b"[0-3] [a-c] [-1] [1-]"),
+            &[
+                t(Token::OneOf { invert: false, list: vec![
+                    Collation::Char(b'0'),
+                    Collation::Char(b'1'),
+                    Collation::Char(b'2'),
+                    Collation::Char(b'3')
+                ] }),
+                c(b' '),
+                t(Token::OneOf { invert: false, list: vec![
+                    Collation::Char(b'a'),
+                    Collation::Char(b'b'),
+                    Collation::Char(b'c')
+                ] }),
+                c(b' '),
+                t(Token::OneOf { invert: false, list: vec![
+                    Collation::Char(b'-'),
+                    Collation::Char(b'1')
+                ] }),
+                c(b' '),
+                t(Token::OneOf { invert: false, list: vec![
+                    Collation::Char(b'1'),
+                    Collation::Char(b'-')
+                ] })
+            ]
+        );
+        assert_eq!(
+            compile(b"[[.-.]-/]"),
+            &[
+                t(Token::OneOf { invert: false, list: vec![
+                    Collation::Char(b'-'),
+                    Collation::Char(b'.'),
+                    Collation::Char(b'/')
+                ] })
+            ]
+        );
+        assert_eq!(
+            compile(b"[[:digit:][:upper:]]"),
+            &[
+                t(Token::OneOf { invert: false, list: vec![
+                    Collation::Class(ctype::is_digit),
+                    Collation::Class(ctype::is_upper)
+                ] })
+            ]
+        );
+    }
+    #[test]
+    fn newline() {
+        assert_eq!(
+            compile(br"\r\n"),
+            &[c(b'\r'), c(b'\n')]
+        );
+    }
+}

+ 40 - 0
dlibc/posix-regex/src/ctype.rs

@@ -0,0 +1,40 @@
+pub fn is_alnum(c: u8) -> bool {
+    is_alpha(c) || is_digit(c)
+}
+pub fn is_alpha(c: u8) -> bool {
+    is_lower(c) || is_upper(c)
+}
+pub fn is_blank(c: u8) -> bool {
+    c == b' ' || c == b'\t'
+}
+pub fn is_cntrl(c: u8) -> bool {
+    c <= 0x1f || c == 0x7f
+}
+pub fn is_digit(c: u8) -> bool {
+    c >= b'0' && c <= b'9'
+}
+pub fn is_graph(c: u8) -> bool {
+    c >= 0x21 && c <= 0x7e
+}
+pub fn is_lower(c: u8) -> bool {
+    c >= b'a' && c <= b'z'
+}
+pub fn is_print(c: u8) -> bool {
+    c >= 0x20 && c <= 0x7e
+}
+pub fn is_punct(c: u8) -> bool {
+    is_graph(c) && !is_alnum(c)
+}
+pub fn is_space(c: u8) -> bool {
+    c == b' ' || (c >= 0x9 && c <= 0xD)
+}
+pub fn is_upper(c: u8) -> bool {
+    c >= b'A' && c <= b'Z'
+}
+pub fn is_xdigit(c: u8) -> bool {
+    is_digit(c) || (c >= b'a' && c <= b'f') || (c >= b'A' && c <= b'F')
+}
+
+pub fn is_word_boundary(c: u8) -> bool {
+    !is_alnum(c) && c != b'_'
+}

+ 29 - 0
dlibc/posix-regex/src/lib.rs

@@ -0,0 +1,29 @@
+#![cfg_attr(feature = "bench", feature(test))]
+#![cfg_attr(feature = "no_std", no_std)]
+
+#[cfg(feature = "no_std")]
+#[macro_use]
+extern crate alloc;
+
+#[cfg(feature = "no_std")]
+mod std {
+    pub use alloc::{borrow, rc};
+    pub use core::*;
+
+    pub mod collections {
+        pub use alloc::collections::BTreeMap as HashMap;
+    }
+    pub mod prelude {
+        pub use alloc::borrow::ToOwned;
+        pub use alloc::boxed::Box;
+        pub use alloc::string::String;
+        pub use alloc::vec::Vec;
+    }
+}
+
+pub mod compile;
+pub mod ctype;
+pub mod matcher;
+
+pub use compile::PosixRegexBuilder;
+pub use matcher::PosixRegex;

+ 752 - 0
dlibc/posix-regex/src/matcher.rs

@@ -0,0 +1,752 @@
+//! The matcher: Can find substrings in a string that match any compiled regex
+
+#[cfg(feature = "no_std")]
+use std::prelude::*;
+
+use compile::{Token, Range};
+use ctype;
+use std::borrow::Cow;
+use std::fmt;
+use std::rc::Rc;
+
+/// A regex matcher, ready to match stuff
+#[derive(Clone)]
+pub struct PosixRegex<'a> {
+    branches: Cow<'a, [Vec<(Token, Range)>]>,
+    case_insensitive: bool,
+    newline: bool,
+    no_start: bool,
+    no_end: bool
+}
+impl<'a> PosixRegex<'a> {
+    /// Create a new matcher instance from the specified alternations. This
+    /// should probably not be used and instead an instance should be obtained
+    /// from `PosixRegexBuilder`, which also compiles a string into regex.
+    pub fn new(branches: Cow<'a, [Vec<(Token, Range)>]>) -> Self {
+        Self {
+            branches,
+            case_insensitive: false,
+            newline: false,
+            no_start: false,
+            no_end: false
+        }
+    }
+    /// Chainable function to enable/disable case insensitivity. Default: false.
+    /// When enabled, single characters match both their upper and lowercase
+    /// representations.
+    pub fn case_insensitive(mut self, value: bool) -> Self {
+        self.case_insensitive = value;
+        self
+    }
+    /// Chainable function to enable/disable newline mode. Default: false.
+    /// When enabled, ^ and $ match newlines as well as start/end.
+    /// This behavior overrides both no_start and no_end.
+    pub fn newline(mut self, value: bool) -> Self {
+        self.newline = value;
+        self
+    }
+    /// Chainable function to enable/disable no_start mode. Default: false.
+    /// When enabled, ^ doesn't actually match the start of a string.
+    pub fn no_start(mut self, value: bool) -> Self {
+        self.no_start = value;
+        self
+    }
+    /// Chainable function to enable/disable no_start mode. Default: false.
+    /// When enabled, $ doesn't actually match the end of a string.
+    pub fn no_end(mut self, value: bool) -> Self {
+        self.no_end = value;
+        self
+    }
+    /// Return the total number of matches that **will** be returned by
+    /// `matches_exact` or in each match in `matches`.
+    pub fn count_groups(&self) -> usize {
+        let mut count = 1;
+        for branch in &*self.branches {
+            count += count_groups(branch);
+        }
+        count
+    }
+    /// Match the string starting at the current position. This does not find
+    /// substrings.
+    pub fn matches_exact(&self, input: &[u8]) -> Option<Box<[Option<(usize, usize)>]>> {
+        let mut matcher = PosixRegexMatcher {
+            base: self,
+            input,
+            offset: 0
+        };
+        let branches = self.branches.iter()
+            .filter_map(|tokens| Branch::new(true, tokens))
+            .collect();
+
+        let start = matcher.offset;
+        match matcher.matches_exact(branches) {
+            None => None,
+            Some(mut groups) => {
+                assert_eq!(groups[0], None);
+                groups[0] = Some((start, matcher.offset));
+                Some(groups)
+            }
+        }
+    }
+    /// Match any substrings in the string, but optionally no more than `max`
+    pub fn matches(&self, input: &[u8], mut max: Option<usize>) -> Vec<Box<[Option<(usize, usize)>]>> {
+        let mut matcher = PosixRegexMatcher {
+            base: self,
+            input,
+            offset: 0
+        };
+
+        let tokens = vec![
+            (Token::InternalStart, Range(0, None)),
+            (Token::Group { id: 0, branches: self.branches.to_vec() }, Range(1, Some(1)))
+        ];
+        let branches = vec![
+            Branch::new(false, &tokens).unwrap()
+        ];
+
+        let mut matches = Vec::new();
+        while max.map(|max| max > 0).unwrap_or(true) {
+            match matcher.matches_exact(branches.clone()) {
+                Some(groups) => matches.push(groups),
+                None => break
+            }
+            max = max.map(|max| max - 1);
+        }
+        matches
+    }
+}
+
+fn count_groups(tokens: &[(Token, Range)]) -> usize {
+    let mut groups = 0;
+    for (token, _) in tokens {
+        if let Token::Group { ref branches, .. } = token {
+            groups += 1;
+            for branch in branches {
+                groups += count_groups(branch);
+            }
+        }
+    }
+    groups
+}
+
+#[derive(Debug, Clone, PartialEq, Eq)]
+struct Group {
+    index: usize,
+    variant: usize,
+    id: usize
+}
+
+#[derive(Clone)]
+struct Branch<'a> {
+    index: usize,
+    repeated: u32,
+    tokens: &'a [(Token, Range)],
+    path: Box<[Group]>,
+    prev: Box<[Option<(usize, usize)>]>,
+
+    parent: Option<Rc<Branch<'a>>>
+}
+impl<'a> fmt::Debug for Branch<'a> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        let (ref token, mut range) = *self.get_token();
+        range.0 = range.0.saturating_sub(self.repeated);
+        range.1 = range.1.map(|max| max.saturating_sub(self.repeated));
+        write!(f, "{:?}", (token, range))
+    }
+}
+impl<'a> Branch<'a> {
+    fn new(exact: bool, tokens: &'a [(Token, Range)]) -> Option<Self> {
+        if tokens.is_empty() {
+            return None;
+        }
+        Some(Self {
+            index: 0,
+            repeated: 0,
+            tokens: tokens,
+            path: Box::new([]),
+            prev: vec![None; if exact { 1 } else { 0 } + count_groups(tokens)].into_boxed_slice(),
+
+            parent: None
+        })
+    }
+    fn group(
+        path: Box<[Group]>,
+        prev: Box<[Option<(usize, usize)>]>,
+        tokens: &'a [(Token, Range)],
+        mut parent: Branch<'a>
+    ) -> Option<Self> {
+        if tokens.is_empty() {
+            return None;
+        }
+        parent.repeated += 1;
+        Some(Self {
+            index: 0,
+            repeated: 0,
+            tokens,
+            path,
+            prev,
+            parent: Some(Rc::new(parent))
+        })
+    }
+    fn parent_tokens(&self) -> &[(Token, Range)] {
+        let mut tokens = self.tokens;
+
+        let len = self.path.len();
+        if len > 0 {
+            for group in &self.path[..len-1] {
+                match tokens[group.index] {
+                    (Token::Group { ref branches, .. }, _) => tokens = &branches[group.variant],
+                    _ => panic!("non-group index in path")
+                }
+            }
+        }
+
+        tokens
+    }
+    fn tokens(&self) -> &[(Token, Range)] {
+        let mut tokens = self.parent_tokens();
+
+        if let Some(group) = self.path.last() {
+            match tokens[group.index] {
+                (Token::Group { ref branches, .. }, _) => tokens = &branches[group.variant],
+                _ => panic!("non-group index in path")
+            }
+        }
+
+        tokens
+    }
+    fn get_token(&self) -> &(Token, Range) {
+        &self.tokens()[self.index]
+    }
+    fn update_group_end(&mut self, offset: usize) {
+        for group in &mut *self.path {
+            self.prev[group.id].as_mut().unwrap().1 = offset;
+        }
+    }
+    fn extend(&self, prev: &mut Box<[Option<(usize, usize)>]>) {
+        for (i, &group) in self.prev.iter().enumerate() {
+            if group.is_some() {
+                prev[i] = group;
+            }
+        }
+    }
+    fn next_branch(&self) -> Option<Self> {
+        if self.index + 1 >= self.tokens().len() {
+            let parent = self.parent.as_ref()?;
+            let (_, Range(min, _)) = *parent.get_token();
+            // Don't add the next branch until we've repeated this one enough
+            if parent.repeated < min {
+                return None;
+            }
+
+            if let Some(mut next) = parent.next_branch() {
+                // Group is closing, migrate previous & current groups to next.
+                self.extend(&mut next.prev);
+
+                return Some(next);
+            }
+            return None;
+        }
+        Some(Self {
+            index: self.index + 1,
+            repeated: 0,
+            ..self.clone()
+        })
+    }
+    fn add_repeats(&self, branches: &mut Vec<Branch<'a>>, offset: usize) {
+        let mut branch = self;
+        loop {
+            if let (Token::Group { id, branches: ref alternatives }, Range(_, max)) = *branch.get_token() {
+                if max.map(|max| branch.repeated < max).unwrap_or(true) {
+                    for alternative in 0..alternatives.len() {
+                        let mut path = branch.path.to_vec();
+                        path.push(Group {
+                            variant: alternative,
+                            index: branch.index,
+                            id
+                        });
+
+                        let mut prev = self.prev.clone();
+                        prev[id].get_or_insert((0, 0)).0 = offset;
+
+                        if let Some(group) = Branch::group(
+                            path.into_boxed_slice(),
+                            prev,
+                            branch.tokens,
+                            branch.clone()
+                        ) {
+                            branches.push(group);
+                        }
+                    }
+                    break;
+                }
+            }
+
+            match branch.parent {
+                Some(ref new) => branch = new,
+                None => break
+            }
+        }
+    }
+    /// Returns if this node is "explored" enough times,
+    /// meaning it has repeated as many times as it want to and has nowhere to go next.
+    fn is_explored(&self) -> bool {
+        let mut branch = Cow::Borrowed(self);
+
+        loop {
+            {
+                let mut branch = &*branch;
+                while let Some(ref parent) = branch.parent {
+                    let (_, Range(min, _)) = *parent.get_token();
+                    if parent.repeated < min {
+                        // Group did not repeat enough times!
+                        return false;
+                    }
+                    branch = parent;
+                }
+            }
+
+            let (_, Range(min, _)) = *branch.get_token();
+            if branch.repeated < min {
+                return false;
+            }
+            match branch.next_branch() {
+                Some(next) => branch = Cow::Owned(next),
+                None => break
+            }
+        }
+        true
+    }
+}
+
+struct PosixRegexMatcher<'a> {
+    base: &'a PosixRegex<'a>,
+    input: &'a [u8],
+    offset: usize
+}
+impl<'a> PosixRegexMatcher<'a> {
+    fn expand<'b>(&mut self, branches: &mut [Branch<'b>]) -> Vec<Branch<'b>> {
+        let mut insert = Vec::new();
+
+        for branch in branches {
+            branch.update_group_end(self.offset);
+
+            let (ref token, range) = *branch.get_token();
+
+            if let Token::Group { id, branches: ref inner } = *token {
+                for alternation in 0..inner.len() {
+                    let mut path = Vec::with_capacity(branch.path.len() + 1);
+                    path.extend_from_slice(&branch.path);
+                    path.push(Group {
+                        index: branch.index,
+                        variant: alternation,
+                        id
+                    });
+
+                    let mut prev = branch.prev.clone();
+                    prev[id].get_or_insert((0, 0)).0 = self.offset;
+
+                    if let Some(branch) = Branch::group(
+                        path.into(),
+                        prev,
+                        branch.tokens,
+                        branch.clone()
+                    ) {
+                        insert.push(branch);
+                    }
+                }
+            }
+            if branch.repeated >= range.0 {
+                // Push the next element as a new branch
+                if let Some(next) = branch.next_branch() {
+                    insert.push(next);
+                }
+                branch.add_repeats(&mut insert, self.offset);
+            }
+        }
+
+        if !insert.is_empty() {
+            let mut new = self.expand(&mut insert);
+            insert.append(&mut new);
+        }
+        insert
+    }
+
+    fn matches_exact(&mut self, mut branches: Vec<Branch>) -> Option<Box<[Option<(usize, usize)>]>> {
+        // Whether or not any branch, at any point, got fully explored. This
+        // means at least one path of the regex successfully completed!
+        let mut succeeded = None;
+        let mut prev = self.offset.checked_sub(1).and_then(|index| self.input.get(index).cloned());
+
+        loop {
+            let next = self.input.get(self.offset).cloned();
+
+            let mut index = 0;
+            let mut remove = 0;
+
+            let mut insert = self.expand(&mut branches);
+            branches.append(&mut insert);
+
+            loop {
+                if index >= branches.len() {
+                    break;
+                }
+                if remove > 0 {
+                    // Just like Rust's `retain` function, shift all elements I
+                    // want to keep back and `truncate` when I'm done.
+                    branches.swap(index, index-remove);
+                }
+                let branch = &mut branches[index-remove];
+                index += 1;
+
+                let (ref token, Range(_, mut max)) = *branch.get_token();
+                let mut token = token;
+
+                let mut accepts = true;
+
+                // Step 1: Handle zero-width stuff like ^ and \<
+                loop {
+                    match token {
+                        Token::End |
+                        Token::Start |
+                        Token::WordEnd |
+                        Token::WordStart => {
+                            accepts = accepts && match token {
+                                Token::End =>
+                                    (!self.base.no_end && next.is_none())
+                                        || (self.base.newline && next == Some(b'\n')),
+                                Token::Start =>
+                                    (!self.base.no_start && self.offset == 0)
+                                        || (self.base.newline && prev == Some(b'\n')),
+                                Token::WordEnd => next.map(ctype::is_word_boundary).unwrap_or(true),
+                                Token::WordStart => prev.map(ctype::is_word_boundary).unwrap_or(true),
+                                _ => unreachable!()
+                            };
+
+                            // Skip ahead to the next token.
+                            match branch.next_branch() {
+                                Some(next) => *branch = next,
+                                None => break
+                            }
+                            let (ref new_token, Range(_, new_max)) = *branch.get_token();
+                            token = new_token;
+                            max = new_max;
+                        },
+                        _ => break
+                    }
+                }
+
+                // Step 2: Check if the token isn't repeated enough times already
+                accepts = accepts && max.map(|max| branch.repeated < max).unwrap_or(true);
+
+                // Step 3: Check if the token matches
+                accepts = accepts && match *token {
+                    Token::InternalStart => next.is_some(),
+                    Token::Group { .. } => false, // <- content is already expanded and handled
+
+                    Token::Any => next.map(|c| !self.base.newline || c != b'\n').unwrap_or(false),
+                    Token::Char(c) => if self.base.case_insensitive {
+                        next.map(|c2| c & !32 == c2 & !32).unwrap_or(false)
+                    } else {
+                        next == Some(c)
+                    },
+                    Token::OneOf { invert, ref list } => if let Some(next) = next {
+                        (!invert || !self.base.newline || next != b'\n')
+                        && list.iter().any(|c| c.matches(next, self.base.case_insensitive)) == !invert
+                    } else { false },
+
+                    // These will only get called if they are encountered at
+                    // EOF (because next_branch returns None), for example
+                    // "abc\>" or "^". Then we simply want to return true as to
+                    // preserve the current `accepts` status.
+                    Token::End |
+                    Token::Start |
+                    Token::WordEnd |
+                    Token::WordStart => true
+                };
+
+                if !accepts {
+                    if branch.is_explored() {
+                        succeeded = Some(branch.clone());
+                    }
+                    remove += 1;
+                    continue;
+                }
+
+                branch.repeated += 1;
+            }
+            let end = branches.len() - remove;
+            branches.truncate(end);
+
+            if branches.is_empty() ||
+                    // The internal start thing is lazy, not greedy:
+                    (succeeded.is_some() && branches.iter().all(|t| t.get_token().0 == Token::InternalStart)) {
+                return succeeded.map(|branch| branch.prev);
+            }
+
+            if next.is_some() {
+                self.offset += 1;
+                prev = next;
+            }
+        }
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    #[cfg(feature = "bench")]
+    extern crate test;
+
+    #[cfg(feature = "bench")]
+    use self::test::Bencher;
+
+    use super::*;
+    use ::PosixRegexBuilder;
+
+    // FIXME: Workaround to coerce a Box<[T; N]> into a Box<[T]>. Use type
+    // ascription when stabilized.
+    fn boxed_slice<T>(slice: Box<[T]>) -> Box<[T]> {
+        slice
+    }
+
+    macro_rules! abox {
+        ($($item:expr),*) => {
+            boxed_slice(Box::new([$($item),*]))
+        }
+    }
+
+    fn compile(regex: &str) -> PosixRegex {
+        PosixRegexBuilder::new(regex.as_bytes())
+            .with_default_classes()
+            .compile()
+            .expect("error compiling regex")
+    }
+    fn matches(regex: &str, input: &str) -> Vec<Box<[Option<(usize, usize)>]>> {
+        compile(regex)
+            .matches(input.as_bytes(), None)
+    }
+    fn matches_exact(regex: &str, input: &str) -> Option<Box<[Option<(usize, usize)>]>> {
+        compile(regex)
+            .matches_exact(input.as_bytes())
+    }
+
+    #[test]
+    fn basic() {
+        assert!(matches_exact("abc", "abc").is_some());
+        assert!(matches_exact("abc", "bbc").is_none());
+        assert!(matches_exact("abc", "acc").is_none());
+        assert!(matches_exact("abc", "abd").is_none());
+    }
+    #[test]
+    fn repetitions() {
+        assert!(matches_exact("abc*", "ab").is_some());
+        assert!(matches_exact("abc*", "abc").is_some());
+        assert!(matches_exact("abc*", "abccc").is_some());
+
+        assert!(matches_exact(r"a\{1,2\}b", "b").is_none());
+        assert!(matches_exact(r"a\{1,2\}b", "ab").is_some());
+        assert!(matches_exact(r"a\{1,2\}b", "aab").is_some());
+        assert!(matches_exact(r"a\{1,2\}b", "aaab").is_none());
+
+        assert!(matches_exact(r"[abc]\{3\}", "abcTRAILING").is_some());
+        assert!(matches_exact(r"[abc]\{3\}", "abTRAILING").is_none());
+    }
+    #[test]
+    fn any() {
+        assert!(matches_exact(".*", "").is_some());
+        assert!(matches_exact(".*b", "b").is_some());
+        assert!(matches_exact(".*b", "ab").is_some());
+        assert!(matches_exact(".*b", "aaaaab").is_some());
+        assert!(matches_exact(".*b", "HELLO WORLD").is_none());
+        assert!(matches_exact(".*b", "HELLO WORLDb").is_some());
+        assert!(matches_exact("H.*O WORLD", "HELLO WORLD").is_some());
+        assert!(matches_exact("H.*ORLD", "HELLO WORLD").is_some());
+    }
+    #[test]
+    fn brackets() {
+        assert!(matches_exact("[abc]*d", "abcd").is_some());
+        assert!(matches_exact("[0-9]*d", "1234d").is_some());
+        assert!(matches_exact("[[:digit:]]*d", "1234d").is_some());
+        assert!(matches_exact("[[:digit:]]*d", "abcd").is_none());
+    }
+    #[test]
+    fn alternations() {
+        assert!(matches_exact(r"abc\|bcd", "abc").is_some());
+        assert!(matches_exact(r"abc\|bcd", "bcd").is_some());
+        assert!(matches_exact(r"abc\|bcd", "cde").is_none());
+        assert!(matches_exact(r"[A-Z]\+\|yee", "").is_none());
+        assert!(matches_exact(r"[A-Z]\+\|yee", "HELLO").is_some());
+        assert!(matches_exact(r"[A-Z]\+\|yee", "yee").is_some());
+        assert!(matches_exact(r"[A-Z]\+\|yee", "hello").is_none());
+    }
+    #[test]
+    fn offsets() {
+        assert_eq!(
+            matches_exact("abc", "abcd"),
+            Some(abox![Some((0, 3))])
+        );
+        assert_eq!(
+            matches_exact(r"[[:alpha:]]\+", "abcde12345"),
+            Some(abox![Some((0, 5))])
+        );
+        assert_eq!(
+            matches_exact(r"a\(bc\)\+d", "abcbcd"),
+            Some(abox![Some((0, 6)), Some((3, 5))])
+        );
+        assert_eq!(
+            matches_exact(r"hello\( \(world\|universe\) :D\)\?!", "hello world :D!"),
+            Some(abox![Some((0, 15)), Some((5, 14)), Some((6, 11))])
+        );
+        assert_eq!(
+            matches_exact(r"hello\( \(world\|universe\) :D\)\?", "hello world :D"),
+            Some(abox![Some((0, 14)), Some((5, 14)), Some((6, 11))])
+        );
+        assert_eq!(
+            matches_exact(r"\(\<hello\>\) world", "hello world"),
+            Some(abox![Some((0, 11)), Some((0, 5))])
+        );
+        assert_eq!(
+            matches_exact(r".*d", "hid howd ared youd"),
+            Some(abox![Some((0, 18))])
+        );
+        assert_eq!(
+            matches_exact(r".*\(a\)", "bbbbba"),
+            Some(abox![Some((0, 6)), Some((5, 6))])
+        );
+        assert_eq!(
+            matches_exact(r"\(a \(b\) \(c\)\) \(d\)", "a b c d"),
+            Some(abox![Some((0, 7)), Some((0, 5)), Some((2, 3)), Some((4, 5)), Some((6, 7))])
+        );
+        assert_eq!(
+            matches_exact(r"\(.\)*", "hello"),
+            Some(abox![Some((0, 5)), Some((4, 5))])
+        );
+        assert_eq!(
+            matches(r"h\(i\)", "hello hi lol"),
+            vec!(abox![Some((6, 8)), Some((7, 8))])
+        );
+        assert_eq!(
+            matches_exact(r"\(\([[:alpha:]]\)*\)", "abcdefg"),
+            Some(abox![Some((0, 7)), Some((0, 7)), Some((6, 7))])
+        );
+        assert_eq!(
+            matches_exact(r"\(\.\([[:alpha:]]\)\)*", ".a.b.c.d.e.f.g"),
+            Some(abox![Some((0, 14)), Some((12, 14)), Some((13, 14))])
+        );
+        assert_eq!(
+            matches_exact(r"\(a\|\(b\)\)*\(c\)", "bababac"),
+            Some(abox![Some((0, 7)), Some((5, 6)), Some((4, 5)), Some((6, 7))])
+        );
+        assert_eq!(
+            matches_exact(r"\(a\|\(b\)\)*\(c\)", "aaac"),
+            Some(abox![Some((0, 4)), Some((2, 3)), None, Some((3, 4))])
+        );
+    }
+    #[test]
+    fn start_and_end() {
+        assert!(matches_exact("^abc$", "abc").is_some());
+        assert!(matches_exact("^bcd", "bcde").is_some());
+        assert!(matches_exact("^bcd", "abcd").is_none());
+        assert!(matches_exact("abc$", "abc").is_some());
+        assert!(matches_exact("abc$", "abcd").is_none());
+
+        assert!(matches_exact(r".*\(^\|a\)c", "c").is_some());
+        assert!(matches_exact(r".*\(^\|a\)c", "ac").is_some());
+        assert!(matches_exact(r".*\(^\|a\)c", "bc").is_none());
+
+        // Tests if ^ can be repeated without issues
+        assert!(matches_exact(".*^^a", "helloabc").is_none());
+        assert!(matches_exact(".*^^a", "abc").is_some());
+    }
+    #[test]
+    fn word_boundaries() {
+        assert!(matches_exact(r"hello\>.world", "hello world").is_some());
+        assert!(matches_exact(r"hello\>.world", "hello!world").is_some());
+        assert!(matches_exact(r"hello\>.world", "hellooworld").is_none());
+
+        assert!(matches_exact(r"hello.\<world", "hello world").is_some());
+        assert!(matches_exact(r"hello.\<world", "hello!world").is_some());
+        assert!(matches_exact(r"hello.\<world", "hellooworld").is_none());
+
+        assert!(matches_exact(r".*\<hello\>", "hihello").is_none());
+        assert!(matches_exact(r".*\<hello\>", "hi_hello").is_none());
+        assert!(matches_exact(r".*\<hello\>", "hi hello").is_some());
+    }
+    #[test]
+    fn groups() {
+        assert!(matches_exact(r"\(hello\) world", "hello world").is_some());
+        assert!(matches_exact(r"\(a*\|b\|c\)d", "d").is_some());
+        assert!(matches_exact(r"\(a*\|b\|c\)d", "aaaad").is_some());
+        assert!(matches_exact(r"\(a*\|b\|c\)d", "bd").is_some());
+        assert!(matches_exact(r"\(a*\|b\|c\)d", "bbbbbd").is_none());
+    }
+    #[test]
+    fn repeating_groups() {
+        assert!(matches_exact(r"\(a\|b\|c\)*d", "d").is_some());
+        assert!(matches_exact(r"\(a\|b\|c\)*d", "aaaad").is_some());
+        assert!(matches_exact(r"\(a\|b\|c\)*d", "bbbbd").is_some());
+        assert!(matches_exact(r"\(a\|b\|c\)*d", "aabbd").is_some());
+
+        assert!(matches_exact(r"\(a\|b\|c\)\{1,2\}d", "d").is_none());
+        assert!(matches_exact(r"\(a\|b\|c\)\{1,2\}d", "ad").is_some());
+        assert!(matches_exact(r"\(a\|b\|c\)\{1,2\}d", "abd").is_some());
+        assert!(matches_exact(r"\(a\|b\|c\)\{1,2\}d", "abcd").is_none());
+        assert!(matches_exact(r"\(\(a\|b\|c\)\)\{1,2\}d", "abd").is_some());
+        assert!(matches_exact(r"\(\(a\|b\|c\)\)\{1,2\}d", "abcd").is_none());
+
+        assert!(matches_exact(r"\(a\|b\|c\)\{4\}d", "ababad").is_none());
+        assert!(matches_exact(r"\(a\|b\|c\)\{4\}d", "ababd").is_some());
+        assert!(matches_exact(r"\(a\|b\|c\)\{4\}d", "abad").is_none());
+
+        assert!(matches_exact(r"\(\([abc]\)\)\{3\}", "abcTRAILING").is_some());
+        assert!(matches_exact(r"\(\([abc]\)\)\{3\}", "abTRAILING").is_none());
+    }
+    #[test]
+    fn case_insensitive() {
+        assert!(compile(r"abc[de]")
+            .case_insensitive(true)
+            .matches_exact(b"ABCD")
+            .is_some());
+        assert!(compile(r"abc[de]")
+            .case_insensitive(true)
+            .matches_exact(b"ABCF")
+            .is_none());
+    }
+    #[test]
+    fn newline() {
+        assert_eq!(compile(r"^hello$")
+            .newline(true)
+            .matches(b"hi\nhello\ngreetings", None)
+            .len(), 1);
+        assert!(compile(r"^hello$")
+            .newline(true)
+            .matches(b"hi\ngood day\ngreetings", None)
+            .is_empty());
+    }
+    #[test]
+    fn no_start_end() {
+        assert!(compile(r"^hello")
+            .no_start(true)
+            .matches_exact(b"hello")
+            .is_none());
+        assert!(compile(r"hello$")
+            .no_end(true)
+            .matches_exact(b"hello")
+            .is_none());
+    }
+
+    #[cfg(feature = "bench")]
+    #[bench]
+    fn speed_matches_exact(b: &mut Bencher) {
+        b.iter(|| {
+            assert!(matches_exact(r"\(\(a*\|b\|c\) test\|yee\)", "aaaaa test").is_some());
+        })
+    }
+    #[cfg(feature = "bench")]
+    #[bench]
+    fn speed_matches(b: &mut Bencher) {
+        b.iter(|| {
+            assert_eq!(matches(r"\(\(a*\|b\|c\) test\|yee\)", "oooo aaaaa test").len(), 1);
+        })
+    }
+}

+ 146 - 0
dlibc/src/lib.rs

@@ -0,0 +1,146 @@
+//! libc - Raw FFI bindings to platforms' system libraries
+//!
+//! [Documentation for other platforms][pd].
+//!
+//! [pd]: https://rust-lang.github.io/libc/#platform-specific-documentation
+//! 
+
+#![feature(core_intrinsics)]
+#![feature(linkage)]
+#![feature(thread_local)]
+#![feature(start)]
+#![feature(naked_functions)]
+#![feature(slice_internals)]
+#![feature(c_variadic)]
+#![feature(stmt_expr_attributes)]
+#![feature(lang_items)]
+
+
+#![crate_name = "dlibc"]
+#![crate_type = "staticlib"]
+#![allow(
+    renamed_and_removed_lints, // Keep this order.
+    unknown_lints, // Keep this order.
+    bad_style,
+    overflowing_literals,
+    improper_ctypes,
+    // This lint is renamed but we run CI for old stable rustc so should be here.
+    redundant_semicolon,
+    redundant_semicolons,
+    unused_macros,
+    unused_macro_rules,
+)]
+#![cfg_attr(libc_deny_warnings, deny(warnings))]
+// Attributes needed when building as part of the standard library
+#![cfg_attr(feature = "rustc-dep-of-std", feature(link_cfg, no_core))]
+#![cfg_attr(libc_thread_local, feature(thread_local))]
+// Enable extra lints:
+#![cfg_attr(feature = "extra_traits", deny(missing_debug_implementations))]
+//#![deny(missing_copy_implementations, safe_packed_borrows)]
+#![cfg_attr(not(feature = "rustc-dep-of-std"), no_std)]
+#![cfg_attr(feature = "rustc-dep-of-std", no_core)]
+#![cfg_attr(libc_const_extern_fn_unstable, feature(const_extern_fn))]
+
+#[macro_use]
+extern crate alloc;
+extern crate core_io;
+#[macro_use]
+extern crate lazy_static;
+extern crate memchr;
+extern crate goblin;
+extern crate rand;
+extern crate posix_regex;
+extern crate cbitset;
+extern crate num_traits;
+
+
+#[macro_use]
+mod macros;
+
+cfg_if! {
+    if #[cfg(feature = "rustc-dep-of-std")] {
+        extern crate rustc_std_workspace_core as core;
+        #[allow(unused_imports)]
+        use core::iter;
+        #[allow(unused_imports)]
+        use core::ops;
+        #[allow(unused_imports)]
+        use core::option;
+    }
+}
+cfg_if! {
+    if #[cfg(libc_priv_mod_use)] {
+        #[cfg(libc_core_cvoid)]
+        #[allow(unused_imports)]
+        use core::ffi;
+        #[allow(unused_imports)]
+        use core::fmt;
+        #[allow(unused_imports)]
+        use core::hash;
+        #[allow(unused_imports)]
+        use core::num;
+        #[allow(unused_imports)]
+        use core::mem;
+        #[doc(hidden)]
+        #[allow(unused_imports)]
+        use core::clone::Clone;
+        #[doc(hidden)]
+        #[allow(unused_imports)]
+        use core::marker::{Copy, Send, Sync};
+        #[doc(hidden)]
+        #[allow(unused_imports)]
+        use core::option::Option;
+    } else {
+        #[doc(hidden)]
+        #[allow(unused_imports)]
+        pub use core::fmt;
+        #[doc(hidden)]
+        #[allow(unused_imports)]
+        pub use core::hash;
+        #[doc(hidden)]
+        #[allow(unused_imports)]
+        pub use core::num;
+        #[doc(hidden)]
+        #[allow(unused_imports)]
+        pub use core::mem;
+        #[doc(hidden)]
+        #[allow(unused_imports)]
+        pub use core::clone::Clone;
+        #[doc(hidden)]
+        #[allow(unused_imports)]
+        pub use core::marker::{Copy, Send, Sync};
+        #[doc(hidden)]
+        #[allow(unused_imports)]
+        pub use core::option::Option;
+    }
+}
+
+#[cfg(target_os = "dragonos")]
+pub mod unix;
+#[cfg(target_os = "dragonos")]
+pub use unix::*;
+#[cfg(target_os = "dragonos")]
+#[macro_use]
+extern crate dsc;
+#[cfg(target_os = "dragonos")]
+#[global_allocator]
+static ALLOCATOR: crate::unix::platform::allocator::Allocator = crate::unix::platform::allocator::ALLOCATOR;
+#[cfg(target_os = "dragonos")]
+pub use crate::unix::macros::*;
+
+use core::panic::PanicInfo;
+
+#[lang = "eh_personality"]
+extern "C" fn eh_personality() {}
+
+#[cfg(target_os = "dragonos")]
+#[panic_handler]
+fn panic_handler(info: &core::panic::PanicInfo) -> ! {
+    // 在这里执行自定义的处理逻辑
+    println!("Panic occurred: {:?}", info);
+
+    // 可以选择进行一些清理或其他操作
+
+    // 结束程序,例如通过调用 `std::process::exit`
+    crate::unix::platform::pal::exit(0);
+}                        

+ 343 - 0
dlibc/src/macros.rs

@@ -0,0 +1,343 @@
+/// A macro for defining #[cfg] if-else statements.
+///
+/// This is similar to the `if/elif` C preprocessor macro by allowing definition
+/// of a cascade of `#[cfg]` cases, emitting the implementation which matches
+/// first.
+///
+/// This allows you to conveniently provide a long list #[cfg]'d blocks of code
+/// without having to rewrite each clause multiple times.
+macro_rules! cfg_if {
+    // match if/else chains with a final `else`
+    ($(
+        if #[cfg($($meta:meta),*)] { $($it:item)* }
+    ) else * else {
+        $($it2:item)*
+    }) => {
+        cfg_if! {
+            @__items
+            () ;
+            $( ( ($($meta),*) ($($it)*) ), )*
+            ( () ($($it2)*) ),
+        }
+    };
+
+    // match if/else chains lacking a final `else`
+    (
+        if #[cfg($($i_met:meta),*)] { $($i_it:item)* }
+        $(
+            else if #[cfg($($e_met:meta),*)] { $($e_it:item)* }
+        )*
+    ) => {
+        cfg_if! {
+            @__items
+            () ;
+            ( ($($i_met),*) ($($i_it)*) ),
+            $( ( ($($e_met),*) ($($e_it)*) ), )*
+            ( () () ),
+        }
+    };
+
+    // Internal and recursive macro to emit all the items
+    //
+    // Collects all the negated `cfg`s in a list at the beginning and after the
+    // semicolon is all the remaining items
+    (@__items ($($not:meta,)*) ; ) => {};
+    (@__items ($($not:meta,)*) ; ( ($($m:meta),*) ($($it:item)*) ),
+     $($rest:tt)*) => {
+        // Emit all items within one block, applying an appropriate #[cfg]. The
+        // #[cfg] will require all `$m` matchers specified and must also negate
+        // all previous matchers.
+        cfg_if! { @__apply cfg(all($($m,)* not(any($($not),*)))), $($it)* }
+
+        // Recurse to emit all other items in `$rest`, and when we do so add all
+        // our `$m` matchers to the list of `$not` matchers as future emissions
+        // will have to negate everything we just matched as well.
+        cfg_if! { @__items ($($not,)* $($m,)*) ; $($rest)* }
+    };
+
+    // Internal macro to Apply a cfg attribute to a list of items
+    (@__apply $m:meta, $($it:item)*) => {
+        $(#[$m] $it)*
+    };
+}
+
+macro_rules! s {
+    ($($(#[$attr:meta])* pub $t:ident $i:ident { $($field:tt)* })*) => ($(
+        s!(it: $(#[$attr])* pub $t $i { $($field)* });
+    )*);
+    (it: $(#[$attr:meta])* pub union $i:ident { $($field:tt)* }) => (
+        compile_error!("unions cannot derive extra traits, use s_no_extra_traits instead");
+    );
+    (it: $(#[$attr:meta])* pub struct $i:ident { $($field:tt)* }) => (
+        __item! {
+            #[repr(C)]
+            #[cfg_attr(feature = "extra_traits", derive(Debug, Eq, Hash, PartialEq))]
+            #[allow(deprecated)]
+            $(#[$attr])*
+            pub struct $i { $($field)* }
+        }
+        #[allow(deprecated)]
+        impl ::Copy for $i {}
+        #[allow(deprecated)]
+        impl ::Clone for $i {
+            fn clone(&self) -> $i { *self }
+        }
+    );
+}
+
+macro_rules! s_no_extra_traits {
+    ($($(#[$attr:meta])* pub $t:ident $i:ident { $($field:tt)* })*) => ($(
+        s_no_extra_traits!(it: $(#[$attr])* pub $t $i { $($field)* });
+    )*);
+    (it: $(#[$attr:meta])* pub union $i:ident { $($field:tt)* }) => (
+        cfg_if! {
+            if #[cfg(libc_union)] {
+                __item! {
+                    #[repr(C)]
+                    $(#[$attr])*
+                    pub union $i { $($field)* }
+                }
+
+                impl ::Copy for $i {}
+                impl ::Clone for $i {
+                    fn clone(&self) -> $i { *self }
+                }
+            }
+        }
+    );
+    (it: $(#[$attr:meta])* pub struct $i:ident { $($field:tt)* }) => (
+        __item! {
+            #[repr(C)]
+            $(#[$attr])*
+            pub struct $i { $($field)* }
+        }
+        #[allow(deprecated)]
+        impl ::Copy for $i {}
+        #[allow(deprecated)]
+        impl ::Clone for $i {
+            fn clone(&self) -> $i { *self }
+        }
+    );
+}
+
+macro_rules! e {
+    ($($(#[$attr:meta])* pub enum $i:ident { $($field:tt)* })*) => ($(
+        __item! {
+            #[cfg_attr(feature = "extra_traits", derive(Debug, Eq, Hash, PartialEq))]
+            $(#[$attr])*
+            pub enum $i { $($field)* }
+        }
+        impl ::Copy for $i {}
+        impl ::Clone for $i {
+            fn clone(&self) -> $i { *self }
+        }
+    )*);
+}
+
+macro_rules! s_paren {
+    ($($(#[$attr:meta])* pub struct $i:ident ( $($field:tt)* ); )* ) => ($(
+        __item! {
+            #[cfg_attr(feature = "extra_traits", derive(Debug, Eq, Hash, PartialEq))]
+            $(#[$attr])*
+            pub struct $i ( $($field)* );
+        }
+        impl ::Copy for $i {}
+        impl ::Clone for $i {
+            fn clone(&self) -> $i { *self }
+        }
+    )*);
+}
+
+// This is a pretty horrible hack to allow us to conditionally mark
+// some functions as 'const', without requiring users of this macro
+// to care about the "const-extern-fn" feature.
+//
+// When 'const-extern-fn' is enabled, we emit the captured 'const' keyword
+// in the expanded function.
+//
+// When 'const-extern-fn' is disabled, we always emit a plain 'pub unsafe extern fn'.
+// Note that the expression matched by the macro is exactly the same - this allows
+// users of this macro to work whether or not 'const-extern-fn' is enabled
+//
+// Unfortunately, we need to duplicate most of this macro between the 'cfg_if' blocks.
+// This is because 'const unsafe extern fn' won't even parse on older compilers,
+// so we need to avoid emitting it at all of 'const-extern-fn'.
+//
+// Specifically, moving the 'cfg_if' into the macro body will *not* work.
+// Doing so would cause the '#[cfg(feature = "const-extern-fn")]' to be emitted
+// into user code. The 'cfg' gate will not stop Rust from trying to parse the
+// 'pub const unsafe extern fn', so users would get a compiler error even when
+// the 'const-extern-fn' feature is disabled
+//
+// Note that users of this macro need to place 'const' in a weird position
+// (after the closing ')' for the arguments, but before the return type).
+// This was the only way I could satisfy the following two requirements:
+// 1. Avoid ambiguity errors from 'macro_rules!' (which happen when writing '$foo:ident fn'
+// 2. Allow users of this macro to mix 'pub fn foo' and 'pub const fn bar' within the same
+// 'f!' block
+cfg_if! {
+    if #[cfg(libc_const_extern_fn)] {
+        macro_rules! f {
+            ($($(#[$attr:meta])* pub $({$constness:ident})* fn $i:ident(
+                        $($arg:ident: $argty:ty),*
+            ) -> $ret:ty {
+                $($body:stmt);*
+            })*) => ($(
+                #[inline]
+                $(#[$attr])*
+                pub $($constness)* unsafe extern fn $i($($arg: $argty),*
+                ) -> $ret {
+                    $($body);*
+                }
+            )*)
+        }
+
+        macro_rules! safe_f {
+            ($($(#[$attr:meta])* pub $({$constness:ident})* fn $i:ident(
+                        $($arg:ident: $argty:ty),*
+            ) -> $ret:ty {
+                $($body:stmt);*
+            })*) => ($(
+                #[inline]
+                $(#[$attr])*
+                pub $($constness)* extern fn $i($($arg: $argty),*
+                ) -> $ret {
+                    $($body);*
+                }
+            )*)
+        }
+
+        macro_rules! const_fn {
+            ($($(#[$attr:meta])* $({$constness:ident})* fn $i:ident(
+                        $($arg:ident: $argty:ty),*
+            ) -> $ret:ty {
+                $($body:stmt);*
+            })*) => ($(
+                #[inline]
+                $(#[$attr])*
+                $($constness)* fn $i($($arg: $argty),*
+                ) -> $ret {
+                    $($body);*
+                }
+            )*)
+        }
+
+    } else {
+        macro_rules! f {
+            ($($(#[$attr:meta])* pub $({$constness:ident})* fn $i:ident(
+                        $($arg:ident: $argty:ty),*
+            ) -> $ret:ty {
+                $($body:stmt);*
+            })*) => ($(
+                #[inline]
+                $(#[$attr])*
+                pub unsafe extern fn $i($($arg: $argty),*
+                ) -> $ret {
+                    $($body);*
+                }
+            )*)
+        }
+
+        macro_rules! safe_f {
+            ($($(#[$attr:meta])* pub $({$constness:ident})* fn $i:ident(
+                        $($arg:ident: $argty:ty),*
+            ) -> $ret:ty {
+                $($body:stmt);*
+            })*) => ($(
+                #[inline]
+                $(#[$attr])*
+                pub extern fn $i($($arg: $argty),*
+                ) -> $ret {
+                    $($body);*
+                }
+            )*)
+        }
+
+        macro_rules! const_fn {
+            ($($(#[$attr:meta])* $({$constness:ident})* fn $i:ident(
+                        $($arg:ident: $argty:ty),*
+            ) -> $ret:ty {
+                $($body:stmt);*
+            })*) => ($(
+                #[inline]
+                $(#[$attr])*
+                fn $i($($arg: $argty),*
+                ) -> $ret {
+                    $($body);*
+                }
+            )*)
+        }
+    }
+}
+
+macro_rules! __item {
+    ($i:item) => {
+        $i
+    };
+}
+
+macro_rules! align_const {
+    ($($(#[$attr:meta])*
+       pub const $name:ident : $t1:ty
+       = $t2:ident { $($field:tt)* };)*) => ($(
+        #[cfg(libc_align)]
+        $(#[$attr])*
+        pub const $name : $t1 = $t2 {
+            $($field)*
+        };
+        #[cfg(not(libc_align))]
+        $(#[$attr])*
+        pub const $name : $t1 = $t2 {
+            $($field)*
+            __align: [],
+        };
+    )*)
+}
+
+// This macro is used to deprecate items that should be accessed via the mach2 crate
+macro_rules! deprecated_mach {
+    (pub const $id:ident: $ty:ty = $expr:expr;) => {
+        #[deprecated(
+            since = "0.2.55",
+            note = "Use the `mach2` crate instead",
+        )]
+        #[allow(deprecated)]
+        pub const $id: $ty = $expr;
+    };
+    ($(pub const $id:ident: $ty:ty = $expr:expr;)*) => {
+        $(
+            deprecated_mach!(
+                pub const $id: $ty = $expr;
+            );
+        )*
+    };
+    (pub type $id:ident = $ty:ty;) => {
+        #[deprecated(
+            since = "0.2.55",
+            note = "Use the `mach2` crate instead",
+        )]
+        #[allow(deprecated)]
+        pub type $id = $ty;
+    };
+    ($(pub type $id:ident = $ty:ty;)*) => {
+        $(
+            deprecated_mach!(
+                pub type $id = $ty;
+            );
+        )*
+    }
+}
+
+#[cfg(not(libc_ptr_addr_of))]
+macro_rules! ptr_addr_of {
+    ($place:expr) => {
+        &$place
+    };
+}
+
+#[cfg(libc_ptr_addr_of)]
+macro_rules! ptr_addr_of {
+    ($place:expr) => {
+        ::core::ptr::addr_of!($place)
+    };
+}

+ 6 - 0
dlibc/src/unix/align.rs

@@ -0,0 +1,6 @@
+s! {
+    #[repr(align(4))]
+    pub struct in6_addr {
+        pub s6_addr: [u8; 16],
+    }
+}

+ 21 - 21
src/c_str.rs → dlibc/src/unix/c_str.rs

@@ -24,15 +24,15 @@ use core::{
     str::{self, Utf8Error},
 };
 
-use crate::{header::string::strlen, platform::types::*};
+use crate::unix::header::string::strlen;
 
 pub fn memchr(needle: u8, haystack: &[u8]) -> Option<usize> {
     use crate::header::string;
 
     let p = unsafe {
         string::memchr(
-            haystack.as_ptr() as *const c_void,
-            needle as c_int,
+            haystack.as_ptr() as *const ::c_void,
+            needle as ::c_int,
             haystack.len(),
         )
     };
@@ -69,7 +69,7 @@ pub fn memchr(needle: u8, haystack: &[u8]) -> Option<usize> {
 /// # Extracting a raw pointer to the whole C string
 ///
 /// `CString` implements a [`as_ptr`] method through the [`Deref`]
-/// trait. This method will give you a `*const c_char` which you can
+/// trait. This method will give you a `*const ::c_char` which you can
 /// feed directly to extern functions that expect a nul-terminated
 /// string, like C's `strdup()`.
 ///
@@ -115,7 +115,7 @@ pub fn memchr(needle: u8, haystack: &[u8]) -> Option<usize> {
 /// use std::os::raw::c_char;
 ///
 /// extern {
-///     fn my_printer(s: *const c_char);
+///     fn my_printer(s: *const ::c_char);
 /// }
 ///
 /// // We are certain that our string doesn't have 0 bytes in the middle,
@@ -150,7 +150,7 @@ pub struct CString {
 ///
 /// This type represents a borrowed reference to a nul-terminated
 /// array of bytes. It can be constructed safely from a `&[`[`u8`]`]`
-/// slice, or unsafely from a raw `*const c_char`. It can then be
+/// slice, or unsafely from a raw `*const ::c_char`. It can then be
 /// converted to a Rust [`&str`] by performing UTF-8 validation, or
 /// into an owned [`CString`].
 ///
@@ -171,7 +171,7 @@ pub struct CString {
 /// use std::ffi::CStr;
 /// use std::os::raw::c_char;
 ///
-/// extern { fn my_string() -> *const c_char; }
+/// extern { fn my_string() -> *const ::c_char; }
 ///
 /// unsafe {
 ///     let slice = CStr::from_ptr(my_string());
@@ -186,7 +186,7 @@ pub struct CString {
 /// use std::os::raw::c_char;
 ///
 /// fn work(data: &CStr) {
-///     extern { fn work_with(data: *const c_char); }
+///     extern { fn work_with(data: *const ::c_char); }
 ///
 ///     unsafe { work_with(data.as_ptr()) }
 /// }
@@ -201,7 +201,7 @@ pub struct CString {
 /// use std::ffi::CStr;
 /// use std::os::raw::c_char;
 ///
-/// extern { fn my_string() -> *const c_char; }
+/// extern { fn my_string() -> *const ::c_char; }
 ///
 /// fn my_string_safe() -> String {
 ///     unsafe {
@@ -223,7 +223,7 @@ pub struct CStr {
     //        just a raw `c_char` along with some form of marker to make
     //        this an unsized type. Essentially `sizeof(&CStr)` should be the
     //        same as `sizeof(&c_char)` but `CStr` should be an unsized type.
-    inner: [c_char],
+    inner: [::c_char],
 }
 
 /// An error indicating that an interior nul byte was found.
@@ -333,7 +333,7 @@ impl CString {
     /// use std::ffi::CString;
     /// use std::os::raw::c_char;
     ///
-    /// extern { fn puts(s: *const c_char); }
+    /// extern { fn puts(s: *const ::c_char); }
     ///
     /// let to_print = CString::new("Hello!").unwrap();
     /// unsafe {
@@ -416,7 +416,7 @@ impl CString {
     /// use std::os::raw::c_char;
     ///
     /// extern {
-    ///     fn some_extern_function(s: *mut c_char);
+    ///     fn some_extern_function(s: *mut ::c_char);
     /// }
     ///
     /// let c_string = CString::new("Hello!").unwrap();
@@ -426,11 +426,11 @@ impl CString {
     ///     let c_string = CString::from_raw(raw);
     /// }
     /// ```
-    pub unsafe fn from_raw(ptr: *mut c_char) -> CString {
+    pub unsafe fn from_raw(ptr: *mut ::c_char) -> CString {
         let len = strlen(ptr) + 1; // Including the NUL byte
         let slice = slice::from_raw_parts_mut(ptr, len as usize);
         CString {
-            inner: Box::from_raw(slice as *mut [c_char] as *mut [u8]),
+            inner: Box::from_raw(slice as *mut [::c_char] as *mut [u8]),
         }
     }
 
@@ -465,8 +465,8 @@ impl CString {
     /// }
     /// ```
     #[inline]
-    pub fn into_raw(self) -> *mut c_char {
-        Box::into_raw(self.into_inner()) as *mut c_char
+    pub fn into_raw(self) -> *mut ::c_char {
+        Box::into_raw(self.into_inner()) as *mut ::c_char
     }
 
     /// Converts the `CString` into a [`String`] if it contains valid UTF-8 data.
@@ -682,7 +682,7 @@ impl fmt::Debug for CStr {
 
 impl<'a> Default for &'a CStr {
     fn default() -> &'a CStr {
-        const SLICE: &[c_char] = &[0];
+        const SLICE: &[::c_char] = &[0];
         unsafe { CStr::from_ptr(SLICE.as_ptr()) }
     }
 }
@@ -918,7 +918,7 @@ impl CStr {
     /// use std::os::raw::c_char;
     ///
     /// extern {
-    ///     fn my_string() -> *const c_char;
+    ///     fn my_string() -> *const ::c_char;
     /// }
     ///
     /// unsafe {
@@ -927,7 +927,7 @@ impl CStr {
     /// }
     /// # }
     /// ```
-    pub unsafe fn from_ptr<'a>(ptr: *const c_char) -> &'a CStr {
+    pub unsafe fn from_ptr<'a>(ptr: *const ::c_char) -> &'a CStr {
         let len = strlen(ptr);
         let ptr = ptr as *const u8;
         CStr::from_bytes_with_nul_unchecked(slice::from_raw_parts(ptr, len as usize + 1))
@@ -1044,7 +1044,7 @@ impl CStr {
     ///
     /// [`CString`]: struct.CString.html
     #[inline]
-    pub fn as_ptr(&self) -> *const c_char {
+    pub fn as_ptr(&self) -> *const ::c_char {
         self.inner.as_ptr()
     }
 
@@ -1092,7 +1092,7 @@ impl CStr {
     /// ```
     #[inline]
     pub fn to_bytes_with_nul(&self) -> &[u8] {
-        unsafe { &*(&self.inner as *const [c_char] as *const [u8]) }
+        unsafe { &*(&self.inner as *const [::c_char] as *const [u8]) }
     }
 
     /// Yields a [`&str`] slice if the `CStr` contains valid UTF-8.

+ 3 - 3
src/c_vec.rs → dlibc/src/unix/c_vec.rs

@@ -1,6 +1,6 @@
-use crate::{
+use crate::unix::{
     io::{self, Write},
-    platform::{self, types::*, WriteByte},
+    platform::{self, WriteByte},
 };
 use core::{
     cmp, fmt,
@@ -59,7 +59,7 @@ impl<T> CVec<T> {
         let ptr = if cap == 0 {
             NonNull::dangling()
         } else if self.cap > 0 {
-            NonNull::new(platform::realloc(self.ptr.as_ptr() as *mut c_void, size) as *mut T)
+            NonNull::new(platform::realloc(self.ptr.as_ptr() as *mut ::c_void, size) as *mut T)
                 .ok_or(AllocError)?
         } else {
             NonNull::new((platform::alloc(size)) as *mut T).ok_or(AllocError)?

+ 0 - 0
src/crt0/mod.rs → dlibc/src/unix/crt0/mod.rs


+ 20 - 20
src/fs.rs → dlibc/src/unix/fs.rs

@@ -1,58 +1,58 @@
-use crate::{
+use crate::unix::{
     header::{
         fcntl::O_CREAT,
         unistd::{SEEK_CUR, SEEK_END, SEEK_SET},
     },
     io,
-    platform::{types::*, Pal, Sys}, c_str::CStr
+    c_str::CStr
 };
 use core::ops::Deref;
-
+use crate::unix::platform;
 pub struct File {
-    pub fd: c_int,
+    pub fd: ::c_int,
     /// To avoid self referential FILE struct that needs both a reader and a writer,
     /// make "reference" files that share fd but don't close on drop.
     pub reference: bool,
 }
 
 impl File {
-    pub fn new(fd: c_int) -> Self {
+    pub fn new(fd: ::c_int) -> Self {
         Self {
             fd,
             reference: false,
         }
     }
 
-    pub fn open(path: &CStr, oflag: c_int) -> io::Result<Self> {
-        match Sys::open(path, oflag, 0) {
+    pub fn open(path: &CStr, oflag: ::c_int) -> io::Result<Self> {
+        match platform::pal::open(path.as_ptr(), oflag, 0) {
             -1 => Err(io::last_os_error()),
             ok => Ok(Self::new(ok)),
         }
     }
 
-    pub fn create(path: &CStr, oflag: c_int, mode: mode_t) -> io::Result<Self> {
-        match Sys::open(path, oflag | O_CREAT, mode) {
+    pub fn create(path: &CStr, oflag: ::c_int, mode: ::mode_t) -> io::Result<Self> {
+        match platform::pal::open(path.as_ptr(), oflag | O_CREAT, mode) {
             -1 => Err(io::last_os_error()),
             ok => Ok(Self::new(ok)),
         }
     }
 
     pub fn sync_all(&self) -> io::Result<()> {
-        match Sys::fsync(self.fd) {
+        match platform::pal::fsync(self.fd) {
             -1 => Err(io::last_os_error()),
             _ok => Ok(()),
         }
     }
 
     pub fn set_len(&self, size: u64) -> io::Result<()> {
-        match Sys::ftruncate(self.fd, size as off_t) {
+        match platform::pal::ftruncate(self.fd, size as ::off_t) {
             -1 => Err(io::last_os_error()),
             _ok => Ok(()),
         }
     }
 
     pub fn try_clone(&self) -> io::Result<Self> {
-        match Sys::dup(self.fd) {
+        match platform::pal::dup(self.fd) {
             -1 => Err(io::last_os_error()),
             ok => Ok(Self::new(ok)),
         }
@@ -71,7 +71,7 @@ impl File {
 
 impl io::Read for &File {
     fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
-        match Sys::read(self.fd, buf) {
+        match platform::pal::read(self.fd, buf.as_ptr() as *mut ::c_void,buf.len()) {
             -1 => Err(io::last_os_error()),
             ok => Ok(ok as usize),
         }
@@ -80,7 +80,7 @@ impl io::Read for &File {
 
 impl io::Write for &File {
     fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
-        match Sys::write(self.fd, buf) {
+        match platform::pal::write(self.fd, buf.as_ptr() as*const ::c_void,buf.len()) {
             -1 => Err(io::last_os_error()),
             ok => Ok(ok as usize),
         }
@@ -94,12 +94,12 @@ impl io::Write for &File {
 impl io::Seek for &File {
     fn seek(&mut self, pos: io::SeekFrom) -> io::Result<u64> {
         let (offset, whence) = match pos {
-            io::SeekFrom::Start(start) => (start as off_t, SEEK_SET),
-            io::SeekFrom::Current(current) => (current as off_t, SEEK_CUR),
-            io::SeekFrom::End(end) => (end as off_t, SEEK_END),
+            io::SeekFrom::Start(start) => (start as ::off_t, SEEK_SET),
+            io::SeekFrom::Current(current) => (current as ::off_t, SEEK_CUR),
+            io::SeekFrom::End(end) => (end as ::off_t, SEEK_END),
         };
 
-        match Sys::lseek(self.fd, offset, whence) {
+        match platform::pal::lseek(self.fd, offset, whence) {
             -1 => Err(io::last_os_error()),
             ok => Ok(ok as u64),
         }
@@ -129,7 +129,7 @@ impl io::Seek for File {
 }
 
 impl Deref for File {
-    type Target = c_int;
+    type Target = ::c_int;
 
     fn deref(&self) -> &Self::Target {
         &self.fd
@@ -139,7 +139,7 @@ impl Deref for File {
 impl Drop for File {
     fn drop(&mut self) {
         if !self.reference {
-            let _ = Sys::close(self.fd);
+            let _ = platform::pal::close(self.fd);
         }
     }
 }

+ 9 - 0
dlibc/src/unix/header/_aio/cbindgen.toml

@@ -0,0 +1,9 @@
+sys_includes = []
+include_guard = "_RELIBC_AIO_H"
+language = "C"
+style = "Tag"
+no_includes = true
+cpp_compat = true
+
+[enum]
+prefix_with_name = true

+ 59 - 0
dlibc/src/unix/header/_aio/mod.rs

@@ -0,0 +1,59 @@
+use crate::unix::header::time::{sigevent};
+
+pub struct aiocb {
+    pub aio_fildes: ::c_int,
+    pub aio_lio_opcode: ::c_int,
+    pub aio_reqprio: ::c_int,
+    pub aio_buf: *mut ::c_void,
+    pub aio_nbytes: usize,
+    pub aio_sigevent: sigevent,
+}
+
+// #[no_mangle]
+pub extern "C" fn aio_read(aiocbp: *mut aiocb) -> ::c_int {
+    unimplemented!();
+}
+
+// #[no_mangle]
+pub extern "C" fn aio_write(aiocbp: *mut aiocb) -> ::c_int {
+    unimplemented!();
+}
+
+// #[no_mangle]
+pub extern "C" fn lio_listio(
+    mode: ::c_int,
+    list: *const *const aiocb,
+    nent: ::c_int,
+    sig: *mut sigevent,
+) -> ::c_int {
+    unimplemented!();
+}
+
+// #[no_mangle]
+pub extern "C" fn aio_error(aiocbp: *const aiocb) -> ::c_int {
+    unimplemented!();
+}
+
+// #[no_mangle]
+pub extern "C" fn aio_return(aiocbp: *mut aiocb) -> usize {
+    unimplemented!();
+}
+
+// #[no_mangle]
+pub extern "C" fn aio_cancel(fildes: ::c_int, aiocbp: *mut aiocb) -> ::c_int {
+    unimplemented!();
+}
+
+// #[no_mangle]
+pub extern "C" fn aio_suspend(
+    list: *const *const aiocb,
+    nent: ::c_int,
+    timeout: *const ::timespec,
+) -> ::c_int {
+    unimplemented!();
+}
+
+// #[no_mangle]
+pub extern "C" fn aio_fsync(operation: ::c_int, aiocbp: *mut aiocb) -> ::c_int {
+    unimplemented!();
+}

+ 9 - 0
dlibc/src/unix/header/_fenv/cbindgen.toml

@@ -0,0 +1,9 @@
+sys_includes = ["stdint.h", "sys/types.h"]
+include_guard = "_RELIBC_FENV_H"
+language = "C"
+style = "Tag"
+no_includes = true
+cpp_compat = true
+
+[enum]
+prefix_with_name = true

+ 68 - 0
dlibc/src/unix/header/_fenv/mod.rs

@@ -0,0 +1,68 @@
+//! fenv.h implementation for Redox, following
+//! http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/fenv.h.html
+
+pub const FE_ALL_EXCEPT: ::c_int = 0;
+pub const FE_TONEAREST: ::c_int = 0;
+
+pub type fexcept_t = u64;
+
+#[repr(C)]
+#[derive(Copy,Clone)]
+pub struct fenv_t {
+    pub cw: u64,
+}
+
+// #[no_mangle]
+pub unsafe extern "C" fn feclearexcept(excepts: ::c_int) -> ::c_int {
+    unimplemented!();
+}
+
+// #[no_mangle]
+pub unsafe extern "C" fn fegenenv(envp: *mut fenv_t) -> ::c_int {
+    unimplemented!();
+}
+
+// #[no_mangle]
+pub unsafe extern "C" fn fegetexceptflag(flagp: *mut fexcept_t, excepts: ::c_int) -> ::c_int {
+    unimplemented!();
+}
+
+// #[no_mangle]
+pub unsafe extern "C" fn fegetround() -> ::c_int {
+    FE_TONEAREST
+}
+
+// #[no_mangle]
+pub unsafe extern "C" fn feholdexcept(envp: *mut fenv_t) -> ::c_int {
+    unimplemented!();
+}
+
+// #[no_mangle]
+pub unsafe extern "C" fn feraiseexcept(except: ::c_int) -> ::c_int {
+    unimplemented!();
+}
+
+// #[no_mangle]
+pub unsafe extern "C" fn fesetenv(envp: *const fenv_t) -> ::c_int {
+    unimplemented!();
+}
+
+// #[no_mangle]
+pub unsafe extern "C" fn fesetexceptflag(flagp: *const fexcept_t, excepts: ::c_int) -> ::c_int {
+    unimplemented!();
+}
+
+// #[no_mangle]
+pub unsafe extern "C" fn fesetround(round: ::c_int) -> ::c_int {
+    unimplemented!();
+}
+
+// #[no_mangle]
+pub unsafe extern "C" fn fetestexcept(excepts: ::c_int) -> ::c_int {
+    unimplemented!();
+}
+
+// #[no_mangle]
+pub unsafe extern "C" fn feupdateenv(envp: *const fenv_t) -> ::c_int {
+    unimplemented!();
+}

+ 7 - 0
dlibc/src/unix/header/arch_aarch64_user/cbindgen.toml

@@ -0,0 +1,7 @@
+sys_includes = []
+include_guard = "_AARCH64_USER_H"
+language = "C"
+style = "Tag"
+
+[enum]
+prefix_with_name = true

+ 29 - 0
dlibc/src/unix/header/arch_aarch64_user/mod.rs

@@ -0,0 +1,29 @@
+
+#[repr(C)]
+pub struct user_regs_struct {
+    pub regs: [::c_ulonglong; 31],
+    pub sp: ::c_ulonglong,
+    pub pc: ::c_ulonglong,
+    pub pstate: ::c_ulonglong,
+}
+
+#[repr(C)]
+pub struct user_fpsimd_struct {
+    pub vregs: [::c_double; 32], // BUG: rust doesn't have f128 which is equivalent for long double
+    pub fpsr: ::c_uint,
+    pub fpcr: ::c_uint,
+}
+
+pub type elf_greg_t = ::c_ulong;
+pub type elf_gregset_t = [::c_ulong; 34];
+pub type elf_fpregset_t = user_fpsimd_struct;
+
+#[no_mangle]
+pub extern "C" fn _cbindgen_only_generates_structs_if_they_are_mentioned_which_is_dumb_aarch64_user(
+    a: user_regs_struct,
+    b: user_fpsimd_struct,
+    c: elf_gregset_t,
+    d: elf_greg_t,
+    e: elf_fpregset_t,
+) {
+}

+ 7 - 0
dlibc/src/unix/header/arch_x64_user/cbindgen.toml

@@ -0,0 +1,7 @@
+sys_includes = []
+include_guard = "_X64_USER_H"
+language = "C"
+style = "Tag"
+
+[enum]
+prefix_with_name = true

+ 81 - 0
dlibc/src/unix/header/arch_x64_user/mod.rs

@@ -0,0 +1,81 @@
+//! A part of the ptrace compatibility for Redox OS
+
+#[repr(C)]
+pub struct user_fpregs_struct {
+    pub cwd: u16,
+    pub swd: u16,
+    pub ftw: u16,
+    pub fop: u16,
+    pub rip: u64,
+    pub rdp: u64,
+    pub mxcsr: u32,
+    pub mxcr_mask: u32,
+    pub st_space: [u32; 32],
+    pub xmm_space: [u32; 64],
+    pub padding: [u32; 24],
+}
+
+#[repr(C)]
+pub struct user_regs_struct {
+    pub r15: ::c_ulong,
+    pub r14: ::c_ulong,
+    pub r13: ::c_ulong,
+    pub r12: ::c_ulong,
+    pub rbp: ::c_ulong,
+    pub rbx: ::c_ulong,
+    pub r11: ::c_ulong,
+    pub r10: ::c_ulong,
+    pub r9: ::c_ulong,
+    pub r8: ::c_ulong,
+    pub rax: ::c_ulong,
+    pub rcx: ::c_ulong,
+    pub rdx: ::c_ulong,
+    pub rsi: ::c_ulong,
+    pub rdi: ::c_ulong,
+    pub orig_rax: ::c_ulong,
+    pub rip: ::c_ulong,
+    pub cs: ::c_ulong,
+    pub eflags: ::c_ulong,
+    pub rsp: ::c_ulong,
+    pub ss: ::c_ulong,
+    pub fs_base: ::c_ulong,
+    pub gs_base: ::c_ulong,
+    pub ds: ::c_ulong,
+    pub es: ::c_ulong,
+    pub fs: ::c_ulong,
+    pub gs: ::c_ulong,
+}
+
+pub type elf_greg_t = ::c_ulong;
+
+pub type elf_gregset_t = [::c_ulong; 27];
+pub type elf_fpregset_t = user_fpregs_struct;
+#[repr(C)]
+pub struct user {
+    pub regs: user_regs_struct,
+    pub u_fpvalid: ::c_int,
+    pub i387: user_fpregs_struct,
+    pub u_tsize: ::c_ulong,
+    pub u_dsize: ::c_ulong,
+    pub u_ssize: ::c_ulong,
+    pub start_code: ::c_ulong,
+    pub start_stack: ::c_ulong,
+    pub signal: ::c_long,
+    pub reserved: ::c_int,
+    pub u_ar0: *mut user_regs_struct,
+    pub u_fpstate: *mut user_fpregs_struct,
+    pub magic: ::c_ulong,
+    pub u_comm: [::c_char; 32],
+    pub u_debugreg: [::c_ulong; 8],
+}
+
+#[no_mangle]
+pub extern "C" fn _cbindgen_only_generates_structs_if_they_are_mentioned_which_is_dumb_x86_user(
+    a: user_fpregs_struct,
+    b: user_regs_struct,
+    c: user,
+    d: elf_gregset_t,
+    e: elf_greg_t,
+    f: elf_fpregset_t,
+) {
+}

+ 12 - 0
dlibc/src/unix/header/arpa_inet/cbindgen.toml

@@ -0,0 +1,12 @@
+sys_includes = ["stddef.h", "sys/socket.h", "netinet/in.h"]
+include_guard = "_ARPA_INET_H"
+language = "C"
+style = "Tag"
+no_includes = true
+cpp_compat = true
+
+[enum]
+prefix_with_name = true
+
+[export.rename]
+"in_addr" = "struct in_addr"

+ 156 - 0
dlibc/src/unix/header/arpa_inet/mod.rs

@@ -0,0 +1,156 @@
+//! arpa/inet implementation for Redox, following http://pubs.opengroup.org/onlinepubs/7908799/xns/arpainet.h.html
+
+use core::{
+    ptr, slice,
+    str::{self, FromStr},
+};
+use crate::unix::c_str::*;
+use crate::unix::platform;
+use unix;
+use crate::unix::header::{
+    errno::*,
+    netinet_in::{in_addr, in_addr_t, INADDR_NONE},
+    sys_socket::{constants::*, socklen_t},
+};
+
+#[no_mangle]
+pub extern "C" fn htonl(hostlong: ::uint32_t) -> ::uint32_t {
+    hostlong.to_be()
+}
+
+#[no_mangle]
+pub extern "C" fn htons(hostshort: ::uint16_t) -> ::uint16_t {
+    hostshort.to_be()
+}
+
+#[no_mangle]
+pub extern "C" fn ntohl(netlong: ::uint32_t) -> ::uint32_t {
+    u32::from_be(netlong)
+}
+
+#[no_mangle]
+pub extern "C" fn ntohs(netshort: ::uint16_t) -> ::uint16_t {
+    u16::from_be(netshort)
+}
+
+#[no_mangle]
+pub unsafe extern "C" fn inet_aton(cp: *const ::c_char, inp: *mut in_addr) -> ::c_int {
+    // TODO: octal/hex
+    inet_pton(AF_INET, cp, inp as *mut ::c_void)
+}
+
+#[no_mangle]
+pub unsafe extern "C" fn inet_ntoa(addr: in_addr) -> *const ::c_char {
+    static mut NTOA_ADDR: [::c_char; 16] = [0; 16];
+
+    inet_ntop(
+        AF_INET,
+        &addr as *const in_addr as *const ::c_void,
+        NTOA_ADDR.as_mut_ptr(),
+        16,
+    )
+}
+
+#[no_mangle]
+pub unsafe extern "C" fn inet_pton(domain: ::c_int, src: *const ::c_char, dest: *mut ::c_void) -> ::c_int {
+    if domain != AF_INET {
+        platform::errno = EAFNOSUPPORT;
+        -1
+    } else {
+        let s_addr = slice::from_raw_parts_mut(
+            &mut (*(dest as *mut in_addr)).s_addr as *mut _ as *mut u8,
+            4,
+        );
+        let src_cstr = CStr::from_ptr(src);
+        let mut octets = str::from_utf8_unchecked(src_cstr.to_bytes()).split('.');
+        for i in 0..4 {
+            if let Some(n) = octets.next().and_then(|x| u8::from_str(x).ok()) {
+                s_addr[i] = n;
+            } else {
+                return 0;
+            }
+        }
+        if octets.next() == None {
+            1 // Success
+        } else {
+            0
+        }
+    }
+}
+
+#[no_mangle]
+pub unsafe extern "C" fn inet_ntop(
+    domain: ::c_int,
+    src: *const ::c_void,
+    dest: *mut ::c_char,
+    size: socklen_t,
+) -> *const ::c_char {
+    if domain != AF_INET {
+        platform::errno = EAFNOSUPPORT;
+        ptr::null()
+    } else if size < 16 {
+        platform::errno = ENOSPC;
+        ptr::null()
+    } else {
+        let s_addr = slice::from_raw_parts(
+            &(*(src as *const in_addr)).s_addr as *const _ as *const u8,
+            4,
+        );
+        let addr = format!("{}.{}.{}.{}\0", s_addr[0], s_addr[1], s_addr[2], s_addr[3]);
+        ptr::copy(addr.as_ptr() as *const ::c_char, dest, addr.len());
+        dest
+    }
+}
+
+#[no_mangle]
+pub unsafe extern "C" fn inet_addr(cp: *const ::c_char) -> in_addr_t {
+    let mut val: in_addr = in_addr { s_addr: 0 };
+
+    if inet_aton(cp, &mut val) > 0 {
+        val.s_addr
+    } else {
+        INADDR_NONE
+    }
+}
+
+#[no_mangle]
+pub extern "C" fn inet_lnaof(input: in_addr) -> in_addr_t {
+    if input.s_addr >> 24 < 128 {
+        input.s_addr & 0xff_ffff
+    } else if input.s_addr >> 24 < 192 {
+        input.s_addr & 0xffff
+    } else {
+        input.s_addr & 0xff
+    }
+}
+
+#[no_mangle]
+pub extern "C" fn inet_makeaddr(net: in_addr_t, host: in_addr_t) -> in_addr {
+    let mut output: in_addr = in_addr { s_addr: 0 };
+
+    if net < 256 {
+        output.s_addr = host | net << 24;
+    } else if net < 65536 {
+        output.s_addr = host | net << 16;
+    } else {
+        output.s_addr = host | net << 8;
+    }
+
+    output
+}
+
+#[no_mangle]
+pub extern "C" fn inet_netof(input: in_addr) -> in_addr_t {
+    if input.s_addr >> 24 < 128 {
+        input.s_addr & 0xff_ffff
+    } else if input.s_addr >> 24 < 192 {
+        input.s_addr & 0xffff
+    } else {
+        input.s_addr & 0xff
+    }
+}
+
+#[no_mangle]
+pub unsafe extern "C" fn inet_network(cp: *mut ::c_char) -> in_addr_t {
+    ntohl(inet_addr(cp))
+}

+ 12 - 0
dlibc/src/unix/header/assert/cbindgen.toml

@@ -0,0 +1,12 @@
+sys_includes = ["bits/assert.h"]
+include_guard = "_RELIBC_ASSERT_H"
+language = "C"
+style = "Tag"
+no_includes = true
+cpp_compat = true
+
+[enum]
+prefix_with_name = true
+
+[fn]
+no_return = "__attribute__((noreturn))"

+ 18 - 0
dlibc/src/unix/header/assert/mod.rs

@@ -0,0 +1,18 @@
+//! assert implementation for Redox, following http://pubs.opengroup.org/onlinepubs/7908799/xsh/assert.h.html
+use crate::unix::header::{stdio, stdlib};
+use crate::unix::c_str::*;
+#[no_mangle]
+pub unsafe extern "C" fn __assert_fail(
+    func: *const ::c_char,
+    file: *const ::c_char,
+    line: ::c_int,
+    cond: *const ::c_char,
+) -> ! {
+    let func = CStr::from_ptr(func).to_str().unwrap();
+    let file = CStr::from_ptr(file).to_str().unwrap();
+    let cond = CStr::from_ptr(cond).to_str().unwrap();
+
+    eprintln!("{}: {}:{}: Assertion `{}` failed.", func, file, line, cond);
+
+    core::intrinsics::abort();
+}

+ 0 - 0
src/header/ctype/cbindgen.toml → dlibc/src/unix/header/ctype/cbindgen.toml


+ 103 - 0
dlibc/src/unix/header/ctype/mod.rs

@@ -0,0 +1,103 @@
+//! ctype implementation for Redox, following http://pubs.opengroup.org/onlinepubs/7908799/xsh/ctype.h.html
+
+#[no_mangle]
+pub extern "C" fn isalnum(c: ::c_int) -> ::c_int {
+    ::c_int::from(isdigit(c) != 0 || isalpha(c) != 0)
+}
+
+#[no_mangle]
+pub extern "C" fn isalpha(c: ::c_int) -> ::c_int {
+    ::c_int::from(islower(c) != 0 || isupper(c) != 0)
+}
+
+#[no_mangle]
+pub extern "C" fn isascii(c: ::c_int) -> ::c_int {
+    ::c_int::from((c & !0x7f) == 0)
+}
+
+#[no_mangle]
+pub extern "C" fn isblank(c: ::c_int) -> ::c_int {
+    ::c_int::from(c == ::c_int::from(b' ') || c == ::c_int::from(b'\t'))
+}
+
+#[no_mangle]
+pub extern "C" fn iscntrl(c: ::c_int) -> ::c_int {
+    ::c_int::from((c >= 0x00 && c <= 0x1f) || c == 0x7f)
+}
+
+#[no_mangle]
+pub extern "C" fn isdigit(c: ::c_int) -> ::c_int {
+    ::c_int::from(c >= ::c_int::from(b'0') && c <= ::c_int::from(b'9'))
+}
+
+#[no_mangle]
+pub extern "C" fn isgraph(c: ::c_int) -> ::c_int {
+    ::c_int::from(c >= 0x21 && c <= 0x7e)
+}
+
+#[no_mangle]
+pub extern "C" fn islower(c: ::c_int) -> ::c_int {
+    ::c_int::from(c >= ::c_int::from(b'a') && c <= ::c_int::from(b'z'))
+}
+
+#[no_mangle]
+pub extern "C" fn isprint(c: ::c_int) -> ::c_int {
+    ::c_int::from(c >= 0x20 && c < 0x7f)
+}
+
+#[no_mangle]
+pub extern "C" fn ispunct(c: ::c_int) -> ::c_int {
+    ::c_int::from(
+        (c >= ::c_int::from(b'!') && c <= ::c_int::from(b'/'))
+            || (c >= ::c_int::from(b':') && c <= ::c_int::from(b'@'))
+            || (c >= ::c_int::from(b'[') && c <= ::c_int::from(b'`'))
+            || (c >= ::c_int::from(b'{') && c <= ::c_int::from(b'~')),
+    )
+}
+
+#[no_mangle]
+pub extern "C" fn isspace(c: ::c_int) -> ::c_int {
+    ::c_int::from(
+        c == ::c_int::from(b' ')
+            || c == ::c_int::from(b'\t')
+            || c == ::c_int::from(b'\n')
+            || c == ::c_int::from(b'\r')
+            || c == 0x0b
+            || c == 0x0c,
+    )
+}
+
+#[no_mangle]
+pub extern "C" fn isupper(c: ::c_int) -> ::c_int {
+    ::c_int::from(c >= ::c_int::from(b'A') && c <= ::c_int::from(b'Z'))
+}
+
+#[no_mangle]
+pub extern "C" fn isxdigit(c: ::c_int) -> ::c_int {
+    ::c_int::from(isdigit(c) != 0 || (c | 32 >= ::c_int::from(b'a') && c | 32 <= ::c_int::from(b'f')))
+}
+
+#[no_mangle]
+/// The comment in musl:
+/// "nonsense function that should NEVER be used!"
+pub extern "C" fn toascii(c: ::c_int) -> ::c_int {
+    c & 0x7f
+}
+
+#[no_mangle]
+pub extern "C" fn tolower(c: ::c_int) -> ::c_int {
+    if isupper(c) != 0 {
+        c | 0x20
+    } else {
+        c
+    }
+}
+
+#[no_mangle]
+pub extern "C" fn toupper(c: ::c_int) -> ::c_int {
+    if islower(c) != 0 {
+        c & !0x20
+    } else {
+        c
+    }
+}

+ 0 - 0
src/header/dirent/cbindgen.toml → dlibc/src/unix/header/dirent/cbindgen.toml


+ 32 - 42
src/header/dirent/mod.rs → dlibc/src/unix/header/dirent/mod.rs

@@ -1,23 +1,23 @@
-//! dirent implementation following http://pubs.opengroup.org/onlinepubs/009695399/basedefs/dirent.h.html
+//! ::dirent implementation following http://pubs.opengroup.org/onlinepubs/009695399/basedefs/dirent.h.html
 
 use alloc::boxed::Box;
 use core::{mem, ptr};
 
-use crate::{
+use crate::unix::{
     c_str::CStr,
     c_vec::CVec,
     fs::File,
     header::{errno, fcntl, stdlib, string},
     io::{Seek, SeekFrom},
-    platform::{self, types::*, Pal, Sys},
+    platform,
 };
 
-const DIR_BUF_SIZE: usize = mem::size_of::<dirent>() * 3;
+const DIR_BUF_SIZE: usize = mem::size_of::<::dirent>() * 3;
 
 // No repr(C) needed, C won't see the content
 pub struct DIR {
     file: File,
-    buf: [c_char; DIR_BUF_SIZE],
+    buf: [::c_char; DIR_BUF_SIZE],
     // index and len are specified in bytes
     index: usize,
     len: usize,
@@ -26,18 +26,8 @@ pub struct DIR {
     offset: usize,
 }
 
-#[repr(C)]
-#[derive(Clone)]
-pub struct dirent {
-    pub d_ino: ino_t,
-    pub d_off: off_t,
-    pub d_reclen: c_ushort,
-    pub d_type: c_uchar,
-    pub d_name: [c_char; 256],
-}
-
 #[no_mangle]
-pub unsafe extern "C" fn opendir(path: *const c_char) -> *mut DIR {
+pub unsafe extern "C" fn opendir(path: *const ::c_char) -> *mut DIR {
     let path = CStr::from_ptr(path);
     let file = match File::open(
         path,
@@ -57,10 +47,10 @@ pub unsafe extern "C" fn opendir(path: *const c_char) -> *mut DIR {
 }
 
 #[no_mangle]
-pub unsafe extern "C" fn closedir(dir: *mut DIR) -> c_int {
+pub unsafe extern "C" fn closedir(dir: *mut DIR) -> ::c_int {
     let mut dir = Box::from_raw(dir);
 
-    let ret = Sys::close(*dir.file);
+    let ret = platform::pal::close(*dir.file);
 
     // Reference files aren't closed when dropped
     dir.file.reference = true;
@@ -69,16 +59,16 @@ pub unsafe extern "C" fn closedir(dir: *mut DIR) -> c_int {
 }
 
 #[no_mangle]
-pub unsafe extern "C" fn dirfd(dir: *mut DIR) -> c_int {
+pub unsafe extern "C" fn dirfd(dir: *mut DIR) -> ::c_int {
     *((*dir).file)
 }
 
 #[no_mangle]
-pub unsafe extern "C" fn readdir(dir: *mut DIR) -> *mut dirent {
+pub unsafe extern "C" fn readdir(dir: *mut DIR) -> *mut ::dirent {
     if (*dir).index >= (*dir).len {
-        let read = Sys::getdents(
+        let read = platform::pal::getdents(
             *(*dir).file,
-            (*dir).buf.as_mut_ptr() as *mut dirent,
+            (*dir).buf.as_mut_ptr() as *mut ::dirent,
             (*dir).buf.len(),
         );
         if read <= 0 {
@@ -92,7 +82,7 @@ pub unsafe extern "C" fn readdir(dir: *mut DIR) -> *mut dirent {
         (*dir).len = read as usize;
     }
 
-    let ptr = (*dir).buf.as_mut_ptr().add((*dir).index) as *mut dirent;
+    let ptr = (*dir).buf.as_mut_ptr().add((*dir).index) as *mut ::dirent;
 
     (*dir).offset = (*ptr).d_off as usize;
     (*dir).index += (*ptr).d_reclen as usize;
@@ -101,18 +91,18 @@ pub unsafe extern "C" fn readdir(dir: *mut DIR) -> *mut dirent {
 // #[no_mangle]
 pub extern "C" fn readdir_r(
     _dir: *mut DIR,
-    _entry: *mut dirent,
-    _result: *mut *mut dirent,
-) -> *mut dirent {
+    _entry: *mut ::dirent,
+    _result: *mut *mut ::dirent,
+) -> *mut ::dirent {
     unimplemented!(); // plus, deprecated
 }
 
 #[no_mangle]
-pub unsafe extern "C" fn telldir(dir: *mut DIR) -> c_long {
-    (*dir).offset as c_long
+pub unsafe extern "C" fn telldir(dir: *mut DIR) -> ::c_long {
+    (*dir).offset as ::c_long
 }
 #[no_mangle]
-pub unsafe extern "C" fn seekdir(dir: *mut DIR, off: c_long) {
+pub unsafe extern "C" fn seekdir(dir: *mut DIR, off: ::c_long) {
     let _ = (*dir).file.seek(SeekFrom::Start(off as u64));
     (*dir).offset = off as usize;
     (*dir).index = 0;
@@ -124,17 +114,17 @@ pub unsafe extern "C" fn rewinddir(dir: *mut DIR) {
 }
 
 #[no_mangle]
-pub unsafe extern "C" fn alphasort(first: *mut *const dirent, second: *mut *const dirent) -> c_int {
+pub unsafe extern "C" fn alphasort(first: *mut *const ::dirent, second: *mut *const ::dirent) -> ::c_int {
     string::strcoll((**first).d_name.as_ptr(), (**second).d_name.as_ptr())
 }
 
 #[no_mangle]
 pub unsafe extern "C" fn scandir(
-    dirp: *const c_char,
-    namelist: *mut *mut *mut dirent,
-    filter: Option<extern "C" fn(_: *const dirent) -> c_int>,
-    compare: Option<extern "C" fn(_: *mut *const dirent, _: *mut *const dirent) -> c_int>,
-) -> c_int {
+    dirp: *const ::c_char,
+    namelist: *mut *mut *mut ::dirent,
+    filter: Option<extern "C" fn(_: *const ::dirent) -> ::c_int>,
+    compare: Option<extern "C" fn(_: *mut *const ::dirent, _: *mut *const ::dirent) -> ::c_int>,
+) -> ::c_int {
     let dir = opendir(dirp);
     if dir.is_null() {
         return -1;
@@ -149,7 +139,7 @@ pub unsafe extern "C" fn scandir(
     platform::errno = 0;
 
     loop {
-        let entry: *mut dirent = readdir(dir);
+        let entry: *mut ::dirent = readdir(dir);
         if entry.is_null() {
             break;
         }
@@ -160,7 +150,7 @@ pub unsafe extern "C" fn scandir(
             }
         }
 
-        let copy = platform::alloc(mem::size_of::<dirent>()) as *mut dirent;
+        let copy = platform::alloc(mem::size_of::<::dirent>()) as *mut ::dirent;
         if copy.is_null() {
             break;
         }
@@ -179,7 +169,7 @@ pub unsafe extern "C" fn scandir(
 
     if platform::errno != 0 {
         for ptr in &mut vec {
-            platform::free(*ptr as *mut c_void);
+            platform::free(*ptr as *mut ::c_void);
         }
         -1
     } else {
@@ -187,12 +177,12 @@ pub unsafe extern "C" fn scandir(
 
         platform::errno = old_errno;
         stdlib::qsort(
-            *namelist as *mut c_void,
-            len as size_t,
-            mem::size_of::<*mut dirent>(),
+            *namelist as *mut ::c_void,
+            len as ::size_t,
+            mem::size_of::<*mut ::dirent>(),
             mem::transmute(compare),
         );
 
-        len as c_int
+        len as ::c_int
     }
 }

+ 0 - 0
src/header/dl_tls/cbindgen.toml → dlibc/src/unix/header/dl-tls/cbindgen.toml


+ 5 - 4
src/header/dl_tls/mod.rs → dlibc/src/unix/header/dl-tls/mod.rs

@@ -1,15 +1,16 @@
 //! dl-tls implementation for Redox
 
-use crate::{ld_so::tcb::Tcb, platform::types::*, trace};
+use crate::ld_so::tcb::Tcb;
 
 #[repr(C)]
+#[derive(Copy,Clone)]
 pub struct dl_tls_index {
     pub ti_module: u64,
     pub ti_offset: u64,
 }
 
 #[no_mangle]
-pub unsafe extern "C" fn __tls_get_addr(ti: *mut dl_tls_index) -> *mut c_void {
+pub unsafe extern "C" fn __tls_get_addr(ti: *mut dl_tls_index) -> *mut ::c_void {
     trace!(
         "__tls_get_addr({:p}: {:#x}, {:#x})",
         ti,
@@ -27,7 +28,7 @@ pub unsafe extern "C" fn __tls_get_addr(ti: *mut dl_tls_index) -> *mut c_void {
                     (*ti).ti_offset,
                     addr
                 );
-                return addr as *mut c_void;
+                return addr as *mut ::c_void;
             }
         }
     }
@@ -42,6 +43,6 @@ pub unsafe extern "C" fn __tls_get_addr(ti: *mut dl_tls_index) -> *mut c_void {
 // x86 can define a version that does not require stack alignment
 #[cfg(target_arch = "x86")]
 #[no_mangle]
-pub unsafe extern "C" fn ___tls_get_addr(ti: *mut dl_tls_index) -> *mut c_void {
+pub unsafe extern "C" fn ___tls_get_addr(ti: *mut dl_tls_index) -> *mut ::c_void {
     __tls_get_addr(ti)
 }

+ 9 - 0
dlibc/src/unix/header/dlfcn/cbindgen.toml

@@ -0,0 +1,9 @@
+sys_includes = []
+include_guard = "_RELIBC_DLFCN_H"
+language = "C"
+style = "Type"
+no_includes = true
+cpp_compat = true
+
+[enum]
+prefix_with_name = true

+ 122 - 0
dlibc/src/unix/header/dlfcn/mod.rs

@@ -0,0 +1,122 @@
+//! dlfcn implementation for Redox, following http://pubs.opengroup.org/onlinepubs/7908799/xsh/dlfcn.h.html
+
+use core::{
+    ptr, str,
+    sync::atomic::{AtomicUsize, Ordering},
+};
+use crate::unix::c_str::*;
+use crate::ld_so::tcb::Tcb;
+
+static ERROR_NOT_SUPPORTED: &'static CStr = c_str!("dlfcn not supported");
+
+#[thread_local]
+static ERROR: AtomicUsize = AtomicUsize::new(0);
+
+#[no_mangle]
+pub unsafe extern "C" fn dladdr(addr: *mut ::c_void, info: *mut ::Dl_info) -> ::c_int {
+    //TODO
+    (*info).dli_fname = ptr::null();
+    (*info).dli_fbase = ptr::null_mut();
+    (*info).dli_sname = ptr::null();
+    (*info).dli_saddr = ptr::null_mut();
+    0
+}
+
+#[no_mangle]
+pub unsafe extern "C" fn dlopen(cfilename: *const ::c_char, flags: ::c_int) -> *mut ::c_void {
+    //TODO support all sort of flags
+
+    let filename = if cfilename.is_null() {
+        None
+    } else {
+        Some(str::from_utf8_unchecked(
+            CStr::from_ptr(cfilename).to_bytes(),
+        ))
+    };
+
+    let tcb = match Tcb::current() {
+        Some(tcb) => tcb,
+        None => {
+            ERROR.store(ERROR_NOT_SUPPORTED.as_ptr() as usize, Ordering::SeqCst);
+            return ptr::null_mut();
+        }
+    };
+    if tcb.linker_ptr.is_null() {
+        ERROR.store(ERROR_NOT_SUPPORTED.as_ptr() as usize, Ordering::SeqCst);
+        return ptr::null_mut();
+    }
+    let mut linker = (&*tcb.linker_ptr).lock();
+
+    let cbs_c = linker.cbs.clone();
+    let cbs = cbs_c.borrow();
+
+    let id = match (cbs.load_library)(&mut linker, filename) {
+        Err(err) => {
+            ERROR.store(ERROR_NOT_SUPPORTED.as_ptr() as usize, Ordering::SeqCst);
+            return ptr::null_mut();
+        }
+        Ok(id) => id,
+    };
+
+    id as *mut ::c_void
+}
+
+#[no_mangle]
+pub unsafe extern "C" fn dlsym(handle: *mut ::c_void, symbol: *const ::c_char) -> *mut ::c_void {
+    if symbol.is_null() {
+        ERROR.store(ERROR_NOT_SUPPORTED.as_ptr() as usize, Ordering::SeqCst);
+        return ptr::null_mut();
+    }
+
+    let symbol_str = str::from_utf8_unchecked(CStr::from_ptr(symbol).to_bytes());
+
+    let tcb = match Tcb::current() {
+        Some(tcb) => tcb,
+        None => {
+            ERROR.store(ERROR_NOT_SUPPORTED.as_ptr() as usize, Ordering::SeqCst);
+            return ptr::null_mut();
+        }
+    };
+
+    if tcb.linker_ptr.is_null() {
+        ERROR.store(ERROR_NOT_SUPPORTED.as_ptr() as usize, Ordering::SeqCst);
+        return ptr::null_mut();
+    }
+
+    let linker = (&*tcb.linker_ptr).lock();
+    let cbs_c = linker.cbs.clone();
+    let cbs = cbs_c.borrow();
+    match (cbs.get_sym)(&linker, handle as usize, symbol_str) {
+        Some(sym) => sym,
+        _ => {
+            ERROR.store(ERROR_NOT_SUPPORTED.as_ptr() as usize, Ordering::SeqCst);
+            ptr::null_mut()
+        }
+    }
+}
+
+#[no_mangle]
+pub unsafe extern "C" fn dlclose(handle: *mut ::c_void) -> ::c_int {
+    let tcb = match Tcb::current() {
+        Some(tcb) => tcb,
+        None => {
+            ERROR.store(ERROR_NOT_SUPPORTED.as_ptr() as usize, Ordering::SeqCst);
+            return -1;
+        }
+    };
+
+    if tcb.linker_ptr.is_null() {
+        ERROR.store(ERROR_NOT_SUPPORTED.as_ptr() as usize, Ordering::SeqCst);
+        return -1;
+    };
+    let mut linker = (&*tcb.linker_ptr).lock();
+    let cbs_c = linker.cbs.clone();
+    let cbs = cbs_c.borrow();
+    (cbs.unload)(&mut linker, handle as usize);
+    0
+}
+
+#[no_mangle]
+pub extern "C" fn dlerror() -> *mut ::c_char {
+    ERROR.swap(0, Ordering::SeqCst) as *mut ::c_char
+}

+ 9 - 0
dlibc/src/unix/header/elf/cbindgen.toml

@@ -0,0 +1,9 @@
+sys_includes = ["bits/elf.h"]
+include_guard = "_ELF_H"
+language = "C"
+style = "Tag"
+no_includes = true
+cpp_compat = true
+
+[enum]
+prefix_with_name = true

+ 1005 - 0
dlibc/src/unix/header/elf/mod.rs

@@ -0,0 +1,1005 @@
+
+pub type Elf32_Half = ::uint16_t;
+pub type Elf64_Half = ::uint16_t;
+
+pub type Elf32_Word = ::uint32_t;
+pub type Elf32_Sword = ::int32_t;
+pub type Elf64_Word = ::uint64_t;
+pub type Elf64_Sword = ::int64_t;
+
+pub type Elf32_Xword = ::uint64_t;
+pub type Elf32_Sxword = ::int64_t;
+pub type Elf64_Xword = ::uint64_t;
+pub type Elf64_Sxword = ::int64_t;
+
+pub type Elf32_Addr = ::uint32_t;
+pub type Elf64_Addr = ::uint64_t;
+
+pub type Elf32_Off = ::uint32_t;
+pub type Elf64_Off = ::uint64_t;
+
+pub type Elf32_Section = ::uint16_t;
+pub type Elf64_Section = ::uint16_t;
+
+pub type Elf32_Versym = Elf32_Half;
+pub type Elf64_Versym = Elf64_Half;
+
+pub const EI_NIDENT: usize = 16;
+
+#[repr(C)]
+#[derive(Copy,Clone)]
+pub struct Elf32_Ehdr {
+    pub e_ident: [::c_uchar; EI_NIDENT],
+    pub e_type: Elf32_Half,
+    pub e_machine: Elf32_Half,
+    pub e_version: Elf32_Word,
+    pub e_entry: Elf32_Addr,
+    pub e_phoff: Elf32_Off,
+    pub e_shoff: Elf32_Off,
+    pub e_flags: Elf32_Word,
+    pub e_ehsize: Elf32_Half,
+    pub e_phentsize: Elf32_Half,
+    pub e_phnum: Elf32_Half,
+    pub e_shentsize: Elf32_Half,
+    pub e_shnum: Elf32_Half,
+    pub e_shstrndx: Elf32_Half,
+}
+
+#[repr(C)]
+#[derive(Copy,Clone)]
+pub struct Elf64_Ehdr {
+    pub e_ident: [::c_uchar; EI_NIDENT],
+    pub e_type: Elf64_Half,
+    pub e_machine: Elf64_Half,
+    pub e_version: Elf64_Word,
+    pub e_entry: Elf64_Addr,
+    pub e_phoff: Elf64_Off,
+    pub e_shoff: Elf64_Off,
+    pub e_flags: Elf64_Word,
+    pub e_ehsize: Elf64_Half,
+    pub e_phentsize: Elf64_Half,
+    pub e_phnum: Elf64_Half,
+    pub e_shentsize: Elf64_Half,
+    pub e_shnum: Elf64_Half,
+    pub e_shstrndx: Elf64_Half,
+}
+
+pub const EI_MAG0: usize = 0;
+pub const ELFMAG0: usize = 0x7f;
+pub const EI_MAG1: usize = 1;
+pub const ELFMAG1: ::c_char = 'E' as ::c_char;
+pub const EI_MAG2: usize = 2;
+pub const ELFMAG2: ::c_char = 'L' as ::c_char;
+pub const EI_MAG3: usize = 3;
+pub const ELFMAG3: ::c_char = 'F' as ::c_char;
+pub const ELFMAG: &'static str = "\x7fELF";
+pub const SELFMAG: usize = 4;
+pub const EI_CLASS: usize = 4;
+pub const ELFCLASSNONE: usize = 0;
+pub const ELFCLASS32: usize = 1;
+pub const ELFCLASS64: usize = 2;
+pub const ELFCLASSNUM: usize = 3;
+pub const EI_DATA: usize = 5;
+pub const ELFDATANONE: usize = 0;
+pub const ELFDATA2LSB: usize = 1;
+pub const ELFDATA2MSB: usize = 2;
+pub const ELFDATANUM: usize = 3;
+pub const EI_VERSION: usize = 6;
+pub const EI_OSABI: usize = 7;
+pub const ELFOSABI_NONE: usize = 0;
+pub const ELFOSABI_SYSV: usize = 0;
+pub const ELFOSABI_HPUX: usize = 1;
+pub const ELFOSABI_NETBSD: usize = 2;
+pub const ELFOSABI_LINUX: usize = 3;
+pub const ELFOSABI_GNU: usize = 3;
+pub const ELFOSABI_SOLARIS: usize = 6;
+pub const ELFOSABI_AIX: usize = 7;
+pub const ELFOSABI_IRIX: usize = 8;
+pub const ELFOSABI_FREEBSD: usize = 9;
+pub const ELFOSABI_TRU64: usize = 10;
+pub const ELFOSABI_MODESTO: usize = 11;
+pub const ELFOSABI_OPENBSD: usize = 12;
+pub const ELFOSABI_ARM: usize = 97;
+pub const ELFOSABI_STANDALONE: usize = 255;
+pub const EI_ABIVERSION: usize = 8;
+pub const EI_PAD: usize = 9;
+pub const ET_NONE: usize = 0;
+pub const ET_REL: usize = 1;
+pub const ET_EXEC: usize = 2;
+pub const ET_DYN: usize = 3;
+pub const ET_CORE: usize = 4;
+pub const ET_NUM: usize = 5;
+pub const ET_LOOS: usize = 0xfe00;
+pub const ET_HIOS: usize = 0xfeff;
+pub const ET_LOPROC: usize = 0xff00;
+pub const ET_HIPROC: usize = 0xffff;
+pub const EM_NONE: usize = 0;
+pub const EM_M32: usize = 1;
+pub const EM_SPARC: usize = 2;
+pub const EM_386: usize = 3;
+pub const EM_68K: usize = 4;
+pub const EM_88K: usize = 5;
+pub const EM_860: usize = 7;
+pub const EM_MIPS: usize = 8;
+pub const EM_S370: usize = 9;
+pub const EM_MIPS_RS3_LE: usize = 10;
+pub const EM_PARISC: usize = 15;
+pub const EM_VPP500: usize = 17;
+pub const EM_SPARC32PLUS: usize = 18;
+pub const EM_960: usize = 19;
+pub const EM_PPC: usize = 20;
+pub const EM_PPC64: usize = 21;
+pub const EM_S390: usize = 22;
+pub const EM_V800: usize = 36;
+pub const EM_FR20: usize = 37;
+pub const EM_RH32: usize = 38;
+pub const EM_RCE: usize = 39;
+pub const EM_ARM: usize = 40;
+pub const EM_FAKE_ALPHA: usize = 41;
+pub const EM_SH: usize = 42;
+pub const EM_SPARCV9: usize = 43;
+pub const EM_TRICORE: usize = 44;
+pub const EM_ARC: usize = 45;
+pub const EM_H8_300: usize = 46;
+pub const EM_H8_300H: usize = 47;
+pub const EM_H8S: usize = 48;
+pub const EM_H8_500: usize = 49;
+pub const EM_IA_64: usize = 50;
+pub const EM_MIPS_X: usize = 51;
+pub const EM_COLDFIRE: usize = 52;
+pub const EM_68HC12: usize = 53;
+pub const EM_MMA: usize = 54;
+pub const EM_PCP: usize = 55;
+pub const EM_NCPU: usize = 56;
+pub const EM_NDR1: usize = 57;
+pub const EM_STARCORE: usize = 58;
+pub const EM_ME16: usize = 59;
+pub const EM_ST100: usize = 60;
+pub const EM_TINYJ: usize = 61;
+pub const EM_X86_64: usize = 62;
+pub const EM_PDSP: usize = 63;
+pub const EM_FX66: usize = 66;
+pub const EM_ST9PLUS: usize = 67;
+pub const EM_ST7: usize = 68;
+pub const EM_68HC16: usize = 69;
+pub const EM_68HC11: usize = 70;
+pub const EM_68HC08: usize = 71;
+pub const EM_68HC05: usize = 72;
+pub const EM_SVX: usize = 73;
+pub const EM_ST19: usize = 74;
+pub const EM_VAX: usize = 75;
+pub const EM_CRIS: usize = 76;
+pub const EM_JAVELIN: usize = 77;
+pub const EM_FIREPATH: usize = 78;
+pub const EM_ZSP: usize = 79;
+pub const EM_MMIX: usize = 80;
+pub const EM_HUANY: usize = 81;
+pub const EM_PRISM: usize = 82;
+pub const EM_AVR: usize = 83;
+pub const EM_FR30: usize = 84;
+pub const EM_D10V: usize = 85;
+pub const EM_D30V: usize = 86;
+pub const EM_V850: usize = 87;
+pub const EM_M32R: usize = 88;
+pub const EM_MN10300: usize = 89;
+pub const EM_MN10200: usize = 90;
+pub const EM_PJ: usize = 91;
+pub const EM_OR1K: usize = 92;
+pub const EM_ARC_A5: usize = 93;
+pub const EM_XTENSA: usize = 94;
+pub const EM_AARCH64: usize = 183;
+pub const EM_TILEPRO: usize = 188;
+pub const EM_MICROBLAZE: usize = 189;
+pub const EM_TILEGX: usize = 191;
+pub const EM_NUM: usize = 192;
+pub const EM_ALPHA: usize = 0x9026;
+pub const EV_NONE: usize = 0;
+pub const EV_CURRENT: usize = 1;
+pub const EV_NUM: usize = 2;
+
+#[repr(C)]
+#[derive(Copy,Clone)]
+pub struct Elf32_Shdr {
+    pub sh_name: Elf32_Word,
+    pub sh_type: Elf32_Word,
+    pub sh_flags: Elf32_Word,
+    pub sh_addr: Elf32_Addr,
+    pub sh_offset: Elf32_Off,
+    pub sh_size: Elf32_Word,
+    pub sh_link: Elf32_Word,
+    pub sh_info: Elf32_Word,
+    pub sh_addralign: Elf32_Word,
+    pub sh_entsize: Elf32_Word,
+}
+
+#[repr(C)]
+#[derive(Copy,Clone)]
+pub struct Elf64_Shdr {
+    pub sh_name: Elf64_Word,
+    pub sh_type: Elf64_Word,
+    pub sh_flags: Elf64_Xword,
+    pub sh_addr: Elf64_Addr,
+    pub sh_offset: Elf64_Off,
+    pub sh_size: Elf64_Xword,
+    pub sh_link: Elf64_Word,
+    pub sh_info: Elf64_Word,
+    pub sh_addralign: Elf64_Xword,
+    pub sh_entsize: Elf64_Xword,
+}
+
+pub const SHN_UNDEF: usize = 0;
+pub const SHN_LORESERVE: usize = 0xff00;
+pub const SHN_LOPROC: usize = 0xff00;
+pub const SHN_BEFORE: usize = 0xff00;
+pub const SHN_AFTER: usize = 0xff01;
+pub const SHN_HIPROC: usize = 0xff1f;
+pub const SHN_LOOS: usize = 0xff20;
+pub const SHN_HIOS: usize = 0xff3f;
+pub const SHN_ABS: usize = 0xfff1;
+pub const SHN_COMMON: usize = 0xfff2;
+pub const SHN_XINDEX: usize = 0xffff;
+pub const SHN_HIRESERVE: usize = 0xffff;
+pub const SHT_NULL: usize = 0;
+pub const SHT_PROGBITS: usize = 1;
+pub const SHT_SYMTAB: usize = 2;
+pub const SHT_STRTAB: usize = 3;
+pub const SHT_RELA: usize = 4;
+pub const SHT_HASH: usize = 5;
+pub const SHT_DYNAMIC: usize = 6;
+pub const SHT_NOTE: usize = 7;
+pub const SHT_NOBITS: usize = 8;
+pub const SHT_REL: usize = 9;
+pub const SHT_SHLIB: usize = 10;
+pub const SHT_DYNSYM: usize = 11;
+pub const SHT_INIT_ARRAY: usize = 14;
+pub const SHT_FINI_ARRAY: usize = 15;
+pub const SHT_PREINIT_ARRAY: usize = 16;
+pub const SHT_GROUP: usize = 17;
+pub const SHT_SYMTAB_SHNDX: usize = 18;
+pub const SHT_NUM: usize = 19;
+pub const SHT_LOOS: usize = 0x60000000;
+pub const SHT_GNU_ATTRIBUTES: usize = 0x6ffffff5;
+pub const SHT_GNU_HASH: usize = 0x6ffffff6;
+pub const SHT_GNU_LIBLIST: usize = 0x6ffffff7;
+pub const SHT_CHECKSUM: usize = 0x6ffffff8;
+pub const SHT_LOSUNW: usize = 0x6ffffffa;
+pub const SHT_SUNW_move: usize = 0x6ffffffa;
+pub const SHT_SUNW_COMDAT: usize = 0x6ffffffb;
+pub const SHT_SUNW_syminfo: usize = 0x6ffffffc;
+pub const SHT_GNU_verdef: usize = 0x6ffffffd;
+pub const SHT_GNU_verneed: usize = 0x6ffffffe;
+pub const SHT_GNU_versym: usize = 0x6fffffff;
+pub const SHT_HISUNW: usize = 0x6fffffff;
+pub const SHT_HIOS: usize = 0x6fffffff;
+pub const SHT_LOPROC: usize = 0x70000000;
+pub const SHT_HIPROC: usize = 0x7fffffff;
+pub const SHT_LOUSER: usize = 0x80000000;
+pub const SHT_HIUSER: usize = 0x8fffffff;
+
+pub const SHF_WRITE: usize = 1 << 0;
+pub const SHF_ALLOC: usize = 1 << 1;
+pub const SHF_EXECINSTR: usize = 1 << 2;
+pub const SHF_MERGE: usize = 1 << 4;
+pub const SHF_STRINGS: usize = 1 << 5;
+pub const SHF_INFO_LINK: usize = 1 << 6;
+pub const SHF_LINK_ORDER: usize = 1 << 7;
+pub const SHF_OS_NONCONFORMING: usize = 1 << 8;
+pub const SHF_GROUP: usize = 1 << 9;
+pub const SHF_TLS: usize = 1 << 10;
+pub const SHF_MASKOS: usize = 0x0ff00000;
+pub const SHF_MASKPROC: usize = 0xf0000000;
+pub const SHF_ORDERED: usize = 1 << 30;
+pub const SHF_EXCLUDE: usize = 1 << 31;
+pub const GRP_COMDAT: usize = 0x1;
+
+#[repr(C)]
+#[derive(Copy,Clone)]
+pub struct Elf32_Sym {
+    pub st_name: Elf32_Word,
+    pub st_value: Elf32_Addr,
+    pub st_size: Elf32_Word,
+    pub st_info: ::c_uchar,
+    pub st_other: ::c_uchar,
+    pub st_shndx: Elf32_Section,
+}
+
+#[repr(C)]
+#[derive(Copy,Clone)]
+pub struct Elf64_Sym {
+    pub st_name: Elf64_Word,
+    pub st_info: ::c_uchar,
+    pub st_other: ::c_uchar,
+    pub st_shndx: Elf64_Section,
+    pub st_value: Elf64_Addr,
+    pub st_size: Elf64_Xword,
+}
+
+#[repr(C)]
+#[derive(Copy,Clone)]
+pub struct Elf32_Syminfo {
+    pub si_boundto: Elf32_Half,
+    pub si_flags: Elf32_Half,
+}
+
+#[repr(C)]
+#[derive(Copy,Clone)]
+pub struct Elf64_Syminfo {
+    pub si_boundto: Elf64_Half,
+    pub si_flags: Elf64_Half,
+}
+
+pub const SYMINFO_BT_SELF: usize = 0xffff;
+pub const SYMINFO_BT_PARENT: usize = 0xfffe;
+pub const SYMINFO_BT_LOWRESERVE: usize = 0xff00;
+pub const SYMINFO_FLG_DIRECT: usize = 0x0001;
+pub const SYMINFO_FLG_PASSTHRU: usize = 0x0002;
+pub const SYMINFO_FLG_COPY: usize = 0x0004;
+pub const SYMINFO_FLG_LAZYLOAD: usize = 0x0008;
+pub const SYMINFO_NONE: usize = 0;
+pub const SYMINFO_CURRENT: usize = 1;
+pub const SYMINFO_NUM: usize = 2;
+
+pub const STB_LOCAL: usize = 0;
+pub const STB_GLOBAL: usize = 1;
+pub const STB_WEAK: usize = 2;
+pub const STB_NUM: usize = 3;
+pub const STB_LOOS: usize = 10;
+pub const STB_GNU_UNIQUE: usize = 10;
+pub const STB_HIOS: usize = 12;
+pub const STB_LOPROC: usize = 13;
+pub const STB_HIPROC: usize = 15;
+pub const STT_NOTYPE: usize = 0;
+pub const STT_OBJECT: usize = 1;
+pub const STT_FUNC: usize = 2;
+pub const STT_SECTION: usize = 3;
+pub const STT_FILE: usize = 4;
+pub const STT_COMMON: usize = 5;
+pub const STT_TLS: usize = 6;
+pub const STT_NUM: usize = 7;
+pub const STT_LOOS: usize = 10;
+pub const STT_GNU_IFUNC: usize = 10;
+pub const STT_HIOS: usize = 12;
+pub const STT_LOPROC: usize = 13;
+pub const STT_HIPROC: usize = 15;
+pub const STN_UNDEF: usize = 0;
+
+pub const STV_DEFAULT: usize = 0;
+pub const STV_INTERNAL: usize = 1;
+pub const STV_HIDDEN: usize = 2;
+pub const STV_PROTECTED: usize = 3;
+
+#[repr(C)]
+#[derive(Copy,Clone)]
+pub struct Elf32_Rel {
+    pub r_offset: Elf32_Addr,
+    pub r_info: Elf32_Word,
+}
+
+#[repr(C)]
+#[derive(Copy,Clone)]
+pub struct Elf64_Rel {
+    pub r_offset: Elf64_Addr,
+    pub r_info: Elf64_Xword,
+}
+
+#[repr(C)]
+#[derive(Copy,Clone)]
+pub struct Elf32_Rela {
+    pub r_offset: Elf32_Addr,
+    pub r_info: Elf32_Word,
+    pub r_addend: Elf32_Sword,
+}
+
+#[repr(C)]
+#[derive(Copy,Clone)]
+pub struct Elf64_Rela {
+    pub r_offset: Elf64_Addr,
+    pub r_info: Elf64_Xword,
+    pub r_addend: Elf64_Sxword,
+}
+
+#[repr(C)]
+#[derive(Copy,Clone)]
+pub struct Elf32_Phdr {
+    pub p_type: Elf32_Word,
+    pub p_offset: Elf32_Off,
+    pub p_vaddr: Elf32_Addr,
+    pub p_paddr: Elf32_Addr,
+    pub p_filesz: Elf32_Word,
+    pub p_memsz: Elf32_Word,
+    pub p_flags: Elf32_Word,
+    pub p_align: Elf32_Word,
+}
+
+#[repr(C)]
+#[derive(Copy,Clone)]
+pub struct Elf64_Phdr {
+    pub p_type: Elf64_Word,
+    pub p_flags: Elf64_Word,
+    pub p_offset: Elf64_Off,
+    pub p_vaddr: Elf64_Addr,
+    pub p_paddr: Elf64_Addr,
+    pub p_filesz: Elf64_Xword,
+    pub p_memsz: Elf64_Xword,
+    pub p_align: Elf64_Xword,
+}
+
+pub const PT_NULL: usize = 0;
+pub const PT_LOAD: usize = 1;
+pub const PT_DYNAMIC: usize = 2;
+pub const PT_INTERP: usize = 3;
+pub const PT_NOTE: usize = 4;
+pub const PT_SHLIB: usize = 5;
+pub const PT_PHDR: usize = 6;
+pub const PT_TLS: usize = 7;
+pub const PT_NUM: usize = 8;
+pub const PT_LOOS: usize = 0x60000000;
+pub const PT_GNU_EH_FRAME: usize = 0x6474e550;
+pub const PT_GNU_STACK: usize = 0x6474e551;
+pub const PT_GNU_RELRO: usize = 0x6474e552;
+pub const PT_LOSUNW: usize = 0x6ffffffa;
+pub const PT_SUNWBSS: usize = 0x6ffffffa;
+pub const PT_SUNWSTACK: usize = 0x6ffffffb;
+pub const PT_HISUNW: usize = 0x6fffffff;
+pub const PT_HIOS: usize = 0x6fffffff;
+pub const PT_LOPROC: usize = 0x70000000;
+pub const PT_HIPROC: usize = 0x7fffffff;
+pub const PN_XNUM: usize = 0xffff;
+pub const PF_X: usize = 1 << 0;
+pub const PF_W: usize = 1 << 1;
+pub const PF_R: usize = 1 << 2;
+pub const PF_MASKOS: usize = 0x0ff00000;
+pub const PF_MASKPROC: usize = 0xf0000000;
+
+pub const NT_PRSTATUS: usize = 1;
+pub const NT_FPREGSET: usize = 2;
+pub const NT_PRPSINFO: usize = 3;
+pub const NT_PRXREG: usize = 4;
+pub const NT_TASKSTRUCT: usize = 4;
+pub const NT_PLATFORM: usize = 5;
+pub const NT_AUXV: usize = 6;
+pub const NT_GWINDOWS: usize = 7;
+pub const NT_ASRS: usize = 8;
+pub const NT_PSTATUS: usize = 10;
+pub const NT_PSINFO: usize = 13;
+pub const NT_PRCRED: usize = 14;
+pub const NT_UTSNAME: usize = 15;
+pub const NT_LWPSTATUS: usize = 16;
+pub const NT_LWPSINFO: usize = 17;
+pub const NT_PRFPXREG: usize = 20;
+pub const NT_SIGINFO: usize = 0x53494749;
+pub const NT_FILE: usize = 0x46494c45;
+pub const NT_PRXFPREG: usize = 0x46e62b7f;
+pub const NT_PPC_VMX: usize = 0x100;
+pub const NT_PPC_SPE: usize = 0x101;
+pub const NT_PPC_VSX: usize = 0x102;
+pub const NT_386_TLS: usize = 0x200;
+pub const NT_386_IOPERM: usize = 0x201;
+pub const NT_X86_XSTATE: usize = 0x202;
+pub const NT_S390_HIGH_GPRS: usize = 0x300;
+pub const NT_S390_TIMER: usize = 0x301;
+pub const NT_S390_TODCMP: usize = 0x302;
+pub const NT_S390_TODPREG: usize = 0x303;
+pub const NT_S390_CTRS: usize = 0x304;
+pub const NT_S390_PREFIX: usize = 0x305;
+pub const NT_S390_LAST_BREAK: usize = 0x306;
+pub const NT_S390_SYSTEM_CALL: usize = 0x307;
+pub const NT_S390_TDB: usize = 0x308;
+pub const NT_ARM_VFP: usize = 0x400;
+pub const NT_ARM_TLS: usize = 0x401;
+pub const NT_ARM_HW_BREAK: usize = 0x402;
+pub const NT_ARM_HW_WATCH: usize = 0x403;
+pub const NT_METAG_CBUF: usize = 0x500;
+pub const NT_METAG_RPIPE: usize = 0x501;
+pub const NT_METAG_TLS: usize = 0x502;
+pub const NT_VERSION: usize = 1;
+
+#[repr(C)]
+#[derive(Copy,Clone)]
+pub union Elf32_Dyn_Union {
+    d_val: Elf32_Word,
+    d_ptr: Elf32_Addr,
+}
+
+#[repr(C)]
+#[derive(Copy,Clone)]
+pub struct Elf32_Dyn {
+    pub d_tag: Elf32_Sword,
+    pub d_un: Elf32_Dyn_Union,
+}
+
+#[repr(C)]
+#[derive(Copy,Clone)]
+pub union Elf64_Dyn_Union {
+    d_val: Elf64_Xword,
+    d_ptr: Elf64_Addr,
+}
+
+#[repr(C)]
+#[derive(Copy,Clone)]
+pub struct Elf64_Dyn {
+    pub d_tag: Elf64_Sxword,
+    pub d_un: Elf64_Dyn_Union,
+}
+
+pub const DT_NULL: usize = 0;
+pub const DT_NEEDED: usize = 1;
+pub const DT_PLTRELSZ: usize = 2;
+pub const DT_PLTGOT: usize = 3;
+pub const DT_HASH: usize = 4;
+pub const DT_STRTAB: usize = 5;
+pub const DT_SYMTAB: usize = 6;
+pub const DT_RELA: usize = 7;
+pub const DT_RELASZ: usize = 8;
+pub const DT_RELAENT: usize = 9;
+pub const DT_STRSZ: usize = 10;
+pub const DT_SYMENT: usize = 11;
+pub const DT_INIT: usize = 12;
+pub const DT_FINI: usize = 13;
+pub const DT_SONAME: usize = 14;
+pub const DT_RPATH: usize = 15;
+pub const DT_SYMBOLIC: usize = 16;
+pub const DT_REL: usize = 17;
+pub const DT_RELSZ: usize = 18;
+pub const DT_RELENT: usize = 19;
+pub const DT_PLTREL: usize = 20;
+pub const DT_DEBUG: usize = 21;
+pub const DT_TEXTREL: usize = 22;
+pub const DT_JMPREL: usize = 23;
+pub const DT_BIND_NOW: usize = 24;
+pub const DT_INIT_ARRAY: usize = 25;
+pub const DT_FINI_ARRAY: usize = 26;
+pub const DT_INIT_ARRAYSZ: usize = 27;
+pub const DT_FINI_ARRAYSZ: usize = 28;
+pub const DT_RUNPATH: usize = 29;
+pub const DT_FLAGS: usize = 30;
+pub const DT_ENCODING: usize = 32;
+pub const DT_PREINIT_ARRAY: usize = 32;
+pub const DT_PREINIT_ARRAYSZ: usize = 33;
+pub const DT_NUM: usize = 34;
+pub const DT_LOOS: usize = 0x6000000d;
+pub const DT_HIOS: usize = 0x6ffff000;
+pub const DT_LOPROC: usize = 0x70000000;
+pub const DT_HIPROC: usize = 0x7fffffff;
+pub const DT_VALRNGLO: usize = 0x6ffffd00;
+pub const DT_GNU_PRELINKED: usize = 0x6ffffdf5;
+pub const DT_GNU_CONFLICTSZ: usize = 0x6ffffdf6;
+pub const DT_GNU_LIBLISTSZ: usize = 0x6ffffdf7;
+pub const DT_CHECKSUM: usize = 0x6ffffdf8;
+pub const DT_PLTPADSZ: usize = 0x6ffffdf9;
+pub const DT_MOVEENT: usize = 0x6ffffdfa;
+pub const DT_MOVESZ: usize = 0x6ffffdfb;
+pub const DT_FEATURE_1: usize = 0x6ffffdfc;
+pub const DT_POSFLAG_1: usize = 0x6ffffdfd;
+pub const DT_SYMINSZ: usize = 0x6ffffdfe;
+pub const DT_SYMINENT: usize = 0x6ffffdff;
+pub const DT_VALNUM: usize = 12;
+
+pub const DT_ADDRRNGLO: usize = 0x6ffffe00;
+pub const DT_GNU_HASH: usize = 0x6ffffef5;
+pub const DT_TLSDESC_PLT: usize = 0x6ffffef6;
+pub const DT_TLSDESC_GOT: usize = 0x6ffffef7;
+pub const DT_GNU_CONFLICT: usize = 0x6ffffef8;
+pub const DT_GNU_LIBLIST: usize = 0x6ffffef9;
+pub const DT_CONFIG: usize = 0x6ffffefa;
+pub const DT_DEPAUDIT: usize = 0x6ffffefb;
+pub const DT_AUDIT: usize = 0x6ffffefc;
+pub const DT_PLTPAD: usize = 0x6ffffefd;
+pub const DT_MOVETAB: usize = 0x6ffffefe;
+pub const DT_SYMINFO: usize = 0x6ffffeff;
+pub const DT_ADDRNUM: usize = 11;
+pub const DT_VERSYM: usize = 0x6ffffff0;
+pub const DT_RELACOUNT: usize = 0x6ffffff9;
+pub const DT_RELCOUNT: usize = 0x6ffffffa;
+pub const DT_FLAGS_1: usize = 0x6ffffffb;
+pub const DT_VERDEF: usize = 0x6ffffffc;
+pub const DT_VERDEFNUM: usize = 0x6ffffffd;
+pub const DT_VERNEED: usize = 0x6ffffffe;
+pub const DT_VERSIONTAGNUM: usize = 16;
+pub const DT_AUXILIARY: usize = 0x7ffffffd;
+pub const DT_FILTER: usize = 0x7fffffff;
+pub const DT_EXTRANUM: usize = 3;
+pub const DF_ORIGIN: usize = 0x00000001;
+pub const DF_SYMBOLIC: usize = 0x00000002;
+pub const DF_TEXTREL: usize = 0x00000004;
+pub const DF_BIND_NOW: usize = 0x00000008;
+pub const DF_STATIC_TLS: usize = 0x00000010;
+pub const DF_1_NOW: usize = 0x00000001;
+pub const DF_1_GLOBAL: usize = 0x00000002;
+pub const DF_1_GROUP: usize = 0x00000004;
+pub const DF_1_NODELETE: usize = 0x00000008;
+pub const DF_1_LOADFLTR: usize = 0x00000010;
+pub const DF_1_INITFIRST: usize = 0x00000020;
+pub const DF_1_NOOPEN: usize = 0x00000040;
+pub const DF_1_ORIGIN: usize = 0x00000080;
+pub const DF_1_DIRECT: usize = 0x00000100;
+pub const DF_1_TRANS: usize = 0x00000200;
+pub const DF_1_INTERPOSE: usize = 0x00000400;
+pub const DF_1_NODEFLIB: usize = 0x00000800;
+pub const DF_1_NODUMP: usize = 0x00001000;
+pub const DF_1_CONFALT: usize = 0x00002000;
+pub const DF_1_ENDFILTEE: usize = 0x00004000;
+pub const DF_1_DISPRELDNE: usize = 0x00008000;
+pub const DF_1_DISPRELPND: usize = 0x00010000;
+pub const DF_1_NODIRECT: usize = 0x00020000;
+pub const DF_1_IGNMULDEF: usize = 0x00040000;
+pub const DF_1_NOKSYMS: usize = 0x00080000;
+pub const DF_1_NOHDR: usize = 0x00100000;
+pub const DF_1_EDITED: usize = 0x00200000;
+pub const DF_1_NORELOC: usize = 0x00400000;
+pub const DF_1_SYMINTPOSE: usize = 0x00800000;
+pub const DF_1_GLOBAUDIT: usize = 0x01000000;
+pub const DF_1_SINGLETON: usize = 0x02000000;
+pub const DTF_1_PARINIT: usize = 0x00000001;
+pub const DTF_1_CONFEXP: usize = 0x00000002;
+pub const DF_P1_LAZYLOAD: usize = 0x00000001;
+pub const DF_P1_GROUPPERM: usize = 0x00000002;
+
+#[repr(C)]
+#[derive(Copy,Clone)]
+pub struct Elf32_Verdef {
+    pub vd_version: Elf32_Half,
+    pub vd_flags: Elf32_Half,
+    pub vd_ndx: Elf32_Half,
+    pub vd_cnt: Elf32_Half,
+    pub vd_hash: Elf32_Word,
+    pub vd_aux: Elf32_Word,
+    pub vd_next: Elf32_Word,
+}
+
+#[repr(C)]
+#[derive(Copy,Clone)]
+pub struct Elf64_Verdef {
+    pub vd_version: Elf64_Half,
+    pub vd_flags: Elf64_Half,
+    pub vd_ndx: Elf64_Half,
+    pub vd_cnt: Elf64_Half,
+    pub vd_hash: Elf64_Word,
+    pub vd_aux: Elf64_Word,
+    pub vd_next: Elf64_Word,
+}
+
+pub const VER_DEF_NONE: usize = 0;
+pub const VER_DEF_CURRENT: usize = 1;
+pub const VER_DEF_NUM: usize = 2;
+
+pub const VER_FLG_BASE: usize = 0x1;
+pub const VER_FLG_WEAK: usize = 0x2;
+pub const VER_NDX_LOCAL: usize = 0;
+pub const VER_NDX_GLOBAL: usize = 1;
+pub const VER_NDX_LORESERVE: usize = 0xff00;
+pub const VER_NDX_ELIMINATE: usize = 0xff01;
+
+#[repr(C)]
+#[derive(Copy,Clone)]
+pub struct Elf32_Verdaux {
+    pub vda_name: Elf32_Word,
+    pub vda_next: Elf32_Word,
+}
+
+#[repr(C)]
+#[derive(Copy,Clone)]
+pub struct Elf64_Verdaux {
+    pub vda_name: Elf64_Word,
+    pub vda_next: Elf64_Word,
+}
+
+#[repr(C)]
+#[derive(Copy,Clone)]
+pub struct Elf32_Verneed {
+    pub vn_version: Elf32_Half,
+    pub vn_cnt: Elf32_Half,
+    pub vn_file: Elf32_Word,
+    pub vn_aux: Elf32_Word,
+    pub vn_next: Elf32_Word,
+}
+
+#[repr(C)]
+#[derive(Copy,Clone)]
+pub struct Elf64_Verneed {
+    pub vn_version: Elf64_Half,
+    pub vn_cnt: Elf64_Half,
+    pub vn_file: Elf64_Word,
+    pub vn_aux: Elf64_Word,
+    pub vn_next: Elf64_Word,
+}
+
+pub const VER_NEED_NONE: usize = 0;
+pub const VER_NEED_CURRENT: usize = 1;
+pub const VER_NEED_NUM: usize = 2;
+
+#[repr(C)]
+#[derive(Copy,Clone)]
+pub struct Elf64_Vernaux {
+    pub vna_hash: Elf64_Word,
+    pub vna_flags: Elf64_Half,
+    pub vna_other: Elf64_Half,
+    pub vna_name: Elf64_Word,
+    pub vna_next: Elf64_Word,
+}
+
+#[repr(C)]
+#[derive(Copy,Clone)]
+pub union A_UN {
+    a_val: ::uint64_t,
+}
+
+#[repr(C)]
+#[derive(Copy,Clone)]
+pub struct Elf64_auxv_t {
+    pub a_type: ::uint64_t,
+    pub a_un: A_UN,
+}
+
+pub const AT_NULL: usize = 0;
+pub const AT_IGNORE: usize = 1;
+pub const AT_EXECFD: usize = 2;
+pub const AT_PHDR: usize = 3;
+pub const AT_PHENT: usize = 4;
+pub const AT_PHNUM: usize = 5;
+pub const AT_PAGESZ: usize = 6;
+pub const AT_BASE: usize = 7;
+pub const AT_FLAGS: usize = 8;
+pub const AT_ENTRY: usize = 9;
+pub const AT_NOTELF: usize = 10;
+pub const AT_UID: usize = 11;
+pub const AT_EUID: usize = 12;
+pub const AT_GID: usize = 13;
+pub const AT_EGID: usize = 14;
+pub const AT_CLKTCK: usize = 17;
+pub const AT_PLATFORM: usize = 15;
+pub const AT_HWCAP: usize = 16;
+pub const AT_FPUCW: usize = 18;
+pub const AT_DCACHEBSIZE: usize = 19;
+pub const AT_ICACHEBSIZE: usize = 20;
+pub const AT_UCACHEBSIZE: usize = 21;
+pub const AT_IGNOREPPC: usize = 22;
+pub const AT_SECURE: usize = 23;
+pub const AT_BASE_PLATFORM: usize = 24;
+pub const AT_RANDOM: usize = 25;
+pub const AT_HWCAP2: usize = 26;
+pub const AT_EXECFN: usize = 31;
+pub const AT_SYSINFO: usize = 32;
+pub const AT_SYSINFO_EHDR: usize = 33;
+pub const AT_L1I_CACHESHAPE: usize = 34;
+pub const AT_L1D_CACHESHAPE: usize = 35;
+pub const AT_L2_CACHESHAPE: usize = 36;
+pub const AT_L3_CACHESHAPE: usize = 37;
+
+#[repr(C)]
+#[derive(Copy,Clone)]
+pub struct Elf32_Nhdr {
+    pub n_namesz: Elf32_Word,
+    pub n_descsz: Elf32_Word,
+    pub n_type: Elf32_Word,
+}
+
+#[repr(C)]
+#[derive(Copy,Clone)]
+pub struct Elf64_Nhdr {
+    pub n_namesz: Elf64_Word,
+    pub n_descsz: Elf64_Word,
+    pub n_type: Elf64_Word,
+}
+
+pub const ELF_NOTE_SOLARIS: &'static str = "SUNW Solaris";
+pub const ELF_NOTE_GNU: &'static str = "GNU";
+
+pub const ELF_NOTE_PAGESIZE_HINT: usize = 1;
+
+pub const NT_GNU_ABI_TAG: usize = 1;
+pub const ELF_NOTE_ABI: usize = NT_GNU_ABI_TAG;
+
+pub const ELF_NOTE_OS_LINUX: usize = 0;
+pub const ELF_NOTE_OS_GNU: usize = 1;
+pub const ELF_NOTE_OS_SOLARIS2: usize = 2;
+pub const ELF_NOTE_OS_FREEBSD: usize = 3;
+
+pub const NT_GNU_BUILD_ID: usize = 3;
+pub const NT_GNU_GOLD_VERSION: usize = 4;
+
+#[repr(C)]
+#[derive(Copy,Clone)]
+pub struct Elf64_Move {
+    pub m_value: Elf64_Xword,
+    pub m_info: Elf64_Xword,
+    pub m_poffset: Elf64_Xword,
+    pub m_repeat: Elf64_Half,
+    pub m_stride: Elf64_Half,
+}
+
+pub const R_AARCH64_NONE: usize = 0;
+pub const R_AARCH64_ABS64: usize = 257;
+pub const R_AARCH64_ABS32: usize = 258;
+pub const R_AARCH64_ABS16: usize = 259;
+pub const R_AARCH64_PREL64: usize = 260;
+pub const R_AARCH64_PREL32: usize = 261;
+pub const R_AARCH64_PREL16: usize = 262;
+pub const R_AARCH64_MOVW_UABS_G0: usize = 263;
+pub const R_AARCH64_MOVW_UABS_G0_NC: usize = 264;
+pub const R_AARCH64_MOVW_UABS_G1: usize = 265;
+pub const R_AARCH64_MOVW_UABS_G1_NC: usize = 266;
+pub const R_AARCH64_MOVW_UABS_G2: usize = 267;
+pub const R_AARCH64_MOVW_UABS_G2_NC: usize = 268;
+pub const R_AARCH64_MOVW_UABS_G3: usize = 269;
+pub const R_AARCH64_MOVW_SABS_G0: usize = 270;
+pub const R_AARCH64_MOVW_SABS_G1: usize = 271;
+pub const R_AARCH64_MOVW_SABS_G2: usize = 272;
+pub const R_AARCH64_LD_PREL_LO19: usize = 273;
+pub const R_AARCH64_ADR_PREL_LO21: usize = 274;
+pub const R_AARCH64_ADR_PREL_PG_HI21: usize = 275;
+pub const R_AARCH64_ADR_PREL_PG_HI21_NC: usize = 276;
+pub const R_AARCH64_ADD_ABS_LO12_NC: usize = 277;
+pub const R_AARCH64_LDST8_ABS_LO12_NC: usize = 278;
+pub const R_AARCH64_TSTBR14: usize = 279;
+pub const R_AARCH64_CONDBR19: usize = 280;
+pub const R_AARCH64_JUMP26: usize = 282;
+pub const R_AARCH64_CALL26: usize = 283;
+pub const R_AARCH64_LDST16_ABS_LO12_NC: usize = 284;
+pub const R_AARCH64_LDST32_ABS_LO12_NC: usize = 285;
+pub const R_AARCH64_LDST64_ABS_LO12_NC: usize = 286;
+pub const R_AARCH64_MOVW_PREL_G0: usize = 287;
+pub const R_AARCH64_MOVW_PREL_G0_NC: usize = 288;
+pub const R_AARCH64_MOVW_PREL_G1: usize = 289;
+pub const R_AARCH64_MOVW_PREL_G1_NC: usize = 290;
+pub const R_AARCH64_MOVW_PREL_G2: usize = 291;
+pub const R_AARCH64_MOVW_PREL_G2_NC: usize = 292;
+pub const R_AARCH64_MOVW_PREL_G3: usize = 293;
+pub const R_AARCH64_LDST128_ABS_LO12_NC: usize = 299;
+pub const R_AARCH64_MOVW_GOTOFF_G0: usize = 300;
+pub const R_AARCH64_MOVW_GOTOFF_G0_NC: usize = 301;
+pub const R_AARCH64_MOVW_GOTOFF_G1: usize = 302;
+pub const R_AARCH64_MOVW_GOTOFF_G1_NC: usize = 303;
+pub const R_AARCH64_MOVW_GOTOFF_G2: usize = 304;
+pub const R_AARCH64_MOVW_GOTOFF_G2_NC: usize = 305;
+pub const R_AARCH64_MOVW_GOTOFF_G3: usize = 306;
+pub const R_AARCH64_GOTREL64: usize = 307;
+pub const R_AARCH64_GOTREL32: usize = 308;
+pub const R_AARCH64_GOT_LD_PREL19: usize = 309;
+pub const R_AARCH64_LD64_GOTOFF_LO15: usize = 310;
+pub const R_AARCH64_ADR_GOT_PAGE: usize = 311;
+pub const R_AARCH64_LD64_GOT_LO12_NC: usize = 312;
+pub const R_AARCH64_LD64_GOTPAGE_LO15: usize = 313;
+pub const R_AARCH64_TLSGD_ADR_PREL21: usize = 512;
+pub const R_AARCH64_TLSGD_ADR_PAGE21: usize = 513;
+pub const R_AARCH64_TLSGD_ADD_LO12_NC: usize = 514;
+pub const R_AARCH64_TLSGD_MOVW_G1: usize = 515;
+pub const R_AARCH64_TLSGD_MOVW_G0_NC: usize = 516;
+pub const R_AARCH64_TLSLD_ADR_PREL21: usize = 517;
+pub const R_AARCH64_TLSLD_ADR_PAGE21: usize = 518;
+pub const R_AARCH64_TLSLD_ADD_LO12_NC: usize = 519;
+pub const R_AARCH64_TLSLD_MOVW_G1: usize = 520;
+pub const R_AARCH64_TLSLD_MOVW_G0_NC: usize = 521;
+pub const R_AARCH64_TLSLD_LD_PREL19: usize = 522;
+pub const R_AARCH64_TLSLD_MOVW_DTPREL_G2: usize = 523;
+pub const R_AARCH64_TLSLD_MOVW_DTPREL_G1: usize = 524;
+pub const R_AARCH64_TLSLD_MOVW_DTPREL_G1_NC: usize = 525;
+pub const R_AARCH64_TLSLD_MOVW_DTPREL_G0: usize = 526;
+pub const R_AARCH64_TLSLD_MOVW_DTPREL_G0_NC: usize = 527;
+pub const R_AARCH64_TLSLD_ADD_DTPREL_HI12: usize = 528;
+pub const R_AARCH64_TLSLD_ADD_DTPREL_LO12: usize = 529;
+pub const R_AARCH64_TLSLD_ADD_DTPREL_LO12_NC: usize = 530;
+pub const R_AARCH64_TLSLD_LDST8_DTPREL_LO12: usize = 531;
+pub const R_AARCH64_TLSLD_LDST8_DTPREL_LO12_NC: usize = 532;
+pub const R_AARCH64_TLSLD_LDST16_DTPREL_LO12: usize = 533;
+pub const R_AARCH64_TLSLD_LDST16_DTPREL_LO12_NC: usize = 534;
+pub const R_AARCH64_TLSLD_LDST32_DTPREL_LO12: usize = 535;
+pub const R_AARCH64_TLSLD_LDST32_DTPREL_LO12_NC: usize = 536;
+pub const R_AARCH64_TLSLD_LDST64_DTPREL_LO12: usize = 537;
+pub const R_AARCH64_TLSLD_LDST64_DTPREL_LO12_NC: usize = 538;
+pub const R_AARCH64_TLSIE_MOVW_GOTTPREL_G1: usize = 539;
+pub const R_AARCH64_TLSIE_MOVW_GOTTPREL_G0_NC: usize = 540;
+pub const R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21: usize = 541;
+pub const R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC: usize = 542;
+pub const R_AARCH64_TLSIE_LD_GOTTPREL_PREL19: usize = 543;
+pub const R_AARCH64_TLSLE_MOVW_TPREL_G2: usize = 544;
+pub const R_AARCH64_TLSLE_MOVW_TPREL_G1: usize = 545;
+pub const R_AARCH64_TLSLE_MOVW_TPREL_G1_NC: usize = 546;
+pub const R_AARCH64_TLSLE_MOVW_TPREL_G0: usize = 547;
+pub const R_AARCH64_TLSLE_MOVW_TPREL_G0_NC: usize = 548;
+pub const R_AARCH64_TLSLE_ADD_TPREL_HI12: usize = 549;
+pub const R_AARCH64_TLSLE_ADD_TPREL_LO12: usize = 550;
+pub const R_AARCH64_TLSLE_ADD_TPREL_LO12_NC: usize = 551;
+pub const R_AARCH64_TLSLE_LDST8_TPREL_LO12: usize = 552;
+pub const R_AARCH64_TLSLE_LDST8_TPREL_LO12_NC: usize = 553;
+pub const R_AARCH64_TLSLE_LDST16_TPREL_LO12: usize = 554;
+pub const R_AARCH64_TLSLE_LDST16_TPREL_LO12_NC: usize = 555;
+pub const R_AARCH64_TLSLE_LDST32_TPREL_LO12: usize = 556;
+pub const R_AARCH64_TLSLE_LDST32_TPREL_LO12_NC: usize = 557;
+pub const R_AARCH64_TLSLE_LDST64_TPREL_LO12: usize = 558;
+pub const R_AARCH64_TLSLE_LDST64_TPREL_LO12_NC: usize = 559;
+pub const R_AARCH64_TLSDESC_LD_PREL19: usize = 560;
+pub const R_AARCH64_TLSDESC_ADR_PREL21: usize = 561;
+pub const R_AARCH64_TLSDESC_ADR_PAGE21: usize = 562;
+pub const R_AARCH64_TLSDESC_LD64_LO12: usize = 563;
+pub const R_AARCH64_TLSDESC_ADD_LO12: usize = 564;
+pub const R_AARCH64_TLSDESC_OFF_G1: usize = 565;
+pub const R_AARCH64_TLSDESC_OFF_G0_NC: usize = 566;
+pub const R_AARCH64_TLSDESC_LDR: usize = 567;
+pub const R_AARCH64_TLSDESC_ADD: usize = 568;
+pub const R_AARCH64_TLSDESC_CALL: usize = 569;
+pub const R_AARCH64_TLSLE_LDST128_TPREL_LO12: usize = 570;
+pub const R_AARCH64_TLSLE_LDST128_TPREL_LO12_NC: usize = 571;
+pub const R_AARCH64_TLSLD_LDST128_DTPREL_LO12: usize = 572;
+pub const R_AARCH64_TLSLD_LDST128_DTPREL_LO12_NC: usize = 573;
+pub const R_AARCH64_COPY: usize = 1024;
+pub const R_AARCH64_GLOB_DAT: usize = 1025;
+pub const R_AARCH64_JUMP_SLOT: usize = 1026;
+pub const R_AARCH64_RELATIVE: usize = 1027;
+pub const R_AARCH64_TLS_DTPMOD64: usize = 1028;
+pub const R_AARCH64_TLS_DTPREL64: usize = 1029;
+pub const R_AARCH64_TLS_TPREL64: usize = 1030;
+pub const R_AARCH64_TLSDESC: usize = 1031;
+
+pub const R_X86_64_NONE: usize = 0;
+pub const R_X86_64_64: usize = 1;
+pub const R_X86_64_PC32: usize = 2;
+pub const R_X86_64_GOT32: usize = 3;
+pub const R_X86_64_PLT32: usize = 4;
+pub const R_X86_64_COPY: usize = 5;
+pub const R_X86_64_GLOB_DAT: usize = 6;
+pub const R_X86_64_JUMP_SLOT: usize = 7;
+pub const R_X86_64_RELATIVE: usize = 8;
+pub const R_X86_64_GOTPCREL: usize = 9;
+pub const R_X86_64_32: usize = 10;
+pub const R_X86_64_32S: usize = 11;
+pub const R_X86_64_16: usize = 12;
+pub const R_X86_64_PC16: usize = 13;
+pub const R_X86_64_8: usize = 14;
+pub const R_X86_64_PC8: usize = 15;
+pub const R_X86_64_DTPMOD64: usize = 16;
+pub const R_X86_64_DTPOFF64: usize = 17;
+pub const R_X86_64_TPOFF64: usize = 18;
+pub const R_X86_64_TLSGD: usize = 19;
+pub const R_X86_64_TLSLD: usize = 20;
+pub const R_X86_64_DTPOFF32: usize = 21;
+pub const R_X86_64_GOTTPOFF: usize = 22;
+pub const R_X86_64_TPOFF32: usize = 23;
+pub const R_X86_64_PC64: usize = 24;
+pub const R_X86_64_GOTOFF64: usize = 25;
+pub const R_X86_64_GOTPC32: usize = 26;
+pub const R_X86_64_GOT64: usize = 27;
+pub const R_X86_64_GOTPCREL64: usize = 28;
+pub const R_X86_64_GOTPC64: usize = 29;
+pub const R_X86_64_GOTPLT64: usize = 30;
+pub const R_X86_64_PLTOFF64: usize = 31;
+pub const R_X86_64_SIZE32: usize = 32;
+pub const R_X86_64_SIZE64: usize = 33;
+pub const R_X86_64_GOTPC32_TLSDESC: usize = 34;
+pub const R_X86_64_TLSDESC_CALL: usize = 35;
+pub const R_X86_64_TLSDESC: usize = 36;
+pub const R_X86_64_IRELATIVE: usize = 37;
+pub const R_X86_64_RELATIVE64: usize = 38;
+pub const R_X86_64_NUM: usize = 39;
+
+#[no_mangle]
+pub extern "C" fn stupid_cbindgen_needs_a_function_that_holds_all_elf_structs(
+    a: Elf32_Ehdr,
+    b: Elf64_Ehdr,
+    c: Elf32_Shdr,
+    d: Elf64_Shdr,
+    e: Elf32_Sym,
+    f: Elf64_Sym,
+    g: Elf32_Syminfo,
+    h: Elf64_Syminfo,
+    i: Elf32_Rel,
+    j: Elf64_Rel,
+    k: Elf32_Rela,
+    l: Elf64_Rela,
+    m: Elf32_Phdr,
+    n: Elf64_Phdr,
+    o: Elf32_Dyn,
+    p: Elf64_Dyn,
+    q: Elf32_Verdef,
+    r: Elf64_Verdef,
+    s: Elf32_Verdaux,
+    t: Elf64_Verdaux,
+    u: Elf32_Verneed,
+    v: Elf64_Verneed,
+    w: Elf64_Vernaux,
+    x: Elf64_auxv_t,
+    y: Elf32_Nhdr,
+    z: Elf64_Nhdr,
+    aa: Elf64_Move,
+) {
+}

+ 0 - 0
src/header/errno/cbindgen.toml → dlibc/src/unix/header/errno/cbindgen.toml


+ 298 - 0
dlibc/src/unix/header/errno/mod.rs

@@ -0,0 +1,298 @@
+//! errno implementation for Redox, following http://pubs.opengroup.org/onlinepubs/7908799/xsh/errno.h.html
+use crate::unix::platform;
+//TODO: Consider removing, provided for compatibility with newlib
+#[no_mangle]
+pub unsafe extern "C" fn __errno() -> *mut ::c_int {
+    __errno_location()
+}
+
+#[no_mangle]
+pub unsafe extern "C" fn __errno_location() -> *mut ::c_int {
+    &mut platform::errno
+}
+
+#[no_mangle]
+pub unsafe extern "C" fn __program_invocation_name() -> *mut *mut ::c_char {
+    &mut platform::program_invocation_name
+}
+
+#[no_mangle]
+pub unsafe extern "C" fn __program_invocation_short_name() -> *mut *mut ::c_char {
+    &mut platform::program_invocation_short_name
+}
+
+pub const EPERM: ::c_int = 1; /* Operation not permitted */
+pub const ENOENT: ::c_int = 2; /* No such file or directory */
+pub const ESRCH: ::c_int = 3; /* No such process */
+pub const EINTR: ::c_int = 4; /* Interrupted system call */
+pub const EIO: ::c_int = 5; /* I/O error */
+pub const ENXIO: ::c_int = 6; /* No such device or address */
+pub const E2BIG: ::c_int = 7; /* Argument list too long */
+pub const ENOEXEC: ::c_int = 8; /* Exec format error */
+pub const EBADF: ::c_int = 9; /* Bad file number */
+pub const ECHILD: ::c_int = 10; /* No child processes */
+pub const EAGAIN: ::c_int = 11; /* Try again */
+pub const ENOMEM: ::c_int = 12; /* Out of memory */
+pub const EACCES: ::c_int = 13; /* Permission denied */
+pub const EFAULT: ::c_int = 14; /* Bad address */
+pub const ENOTBLK: ::c_int = 15; /* Block device required */
+pub const EBUSY: ::c_int = 16; /* Device or resource busy */
+pub const EEXIST: ::c_int = 17; /* File exists */
+pub const EXDEV: ::c_int = 18; /* Cross-device link */
+pub const ENODEV: ::c_int = 19; /* No such device */
+pub const ENOTDIR: ::c_int = 20; /* Not a directory */
+pub const EISDIR: ::c_int = 21; /* Is a directory */
+pub const EINVAL: ::c_int = 22; /* Invalid argument */
+pub const ENFILE: ::c_int = 23; /* File table overflow */
+pub const EMFILE: ::c_int = 24; /* Too many open files */
+pub const ENOTTY: ::c_int = 25; /* Not a typewriter */
+pub const ETXTBSY: ::c_int = 26; /* Text file busy */
+pub const EFBIG: ::c_int = 27; /* File too large */
+pub const ENOSPC: ::c_int = 28; /* No space left on device */
+pub const ESPIPE: ::c_int = 29; /* Illegal seek */
+pub const EROFS: ::c_int = 30; /* Read-only file system */
+pub const EMLINK: ::c_int = 31; /* Too many links */
+pub const EPIPE: ::c_int = 32; /* Broken pipe */
+pub const EDOM: ::c_int = 33; /* Math argument out of domain of func */
+pub const ERANGE: ::c_int = 34; /* Math result not representable */
+pub const EDEADLK: ::c_int = 35; /* Resource deadlock would occur */
+pub const ENAMETOOLONG: ::c_int = 36; /* File name too long */
+pub const ENOLCK: ::c_int = 37; /* No record locks available */
+pub const ENOSYS: ::c_int = 38; /* Function not implemented */
+pub const ENOTEMPTY: ::c_int = 39; /* Directory not empty */
+pub const ELOOP: ::c_int = 40; /* Too many symbolic links encountered */
+#[cfg(not(target_os = "dragonos"))]
+pub const EWOULDBLOCK: ::c_int = 41; /* Operation would block */
+#[cfg(target_os = "dragonos")]
+pub const EWOULDBLOCK: ::c_int = EAGAIN; /* Operation would block */
+pub const ENOMSG: ::c_int = 42; /* No message of desired type */
+pub const EIDRM: ::c_int = 43; /* Identifier removed */
+pub const ECHRNG: ::c_int = 44; /* Channel number out of range */
+pub const EL2NSYNC: ::c_int = 45; /* Level 2 not synchronized */
+pub const EL3HLT: ::c_int = 46; /* Level 3 halted */
+pub const EL3RST: ::c_int = 47; /* Level 3 reset */
+pub const ELNRNG: ::c_int = 48; /* Link number out of range */
+pub const EUNATCH: ::c_int = 49; /* Protocol driver not attached */
+pub const ENOCSI: ::c_int = 50; /* No CSI structure available */
+pub const EL2HLT: ::c_int = 51; /* Level 2 halted */
+pub const EBADE: ::c_int = 52; /* Invalid exchange */
+pub const EBADR: ::c_int = 53; /* Invalid request descriptor */
+pub const EXFULL: ::c_int = 54; /* Exchange full */
+pub const ENOANO: ::c_int = 55; /* No anode */
+pub const EBADRQC: ::c_int = 56; /* Invalid request code */
+pub const EBADSLT: ::c_int = 57; /* Invalid slot */
+pub const EDEADLOCK: ::c_int = 58; /* Resource deadlock would occur */
+pub const EBFONT: ::c_int = 59; /* Bad font file format */
+pub const ENOSTR: ::c_int = 60; /* Device not a stream */
+pub const ENODATA: ::c_int = 61; /* No data available */
+pub const ETIME: ::c_int = 62; /* Timer expired */
+pub const ENOSR: ::c_int = 63; /* Out of streams resources */
+pub const ENONET: ::c_int = 64; /* Machine is not on the network */
+pub const ENOPKG: ::c_int = 65; /* Package not installed */
+pub const EREMOTE: ::c_int = 66; /* Object is remote */
+pub const ENOLINK: ::c_int = 67; /* Link has been severed */
+pub const EADV: ::c_int = 68; /* Advertise error */
+pub const ESRMNT: ::c_int = 69; /* Srmount error */
+pub const ECOMM: ::c_int = 70; /* Communication error on send */
+pub const EPROTO: ::c_int = 71; /* Protocol error */
+pub const EMULTIHOP: ::c_int = 72; /* Multihop attempted */
+pub const EDOTDOT: ::c_int = 73; /* RFS specific error */
+pub const EBADMSG: ::c_int = 74; /* Not a data message */
+pub const EOVERFLOW: ::c_int = 75; /* Value too large for defined data type */
+pub const ENOTUNIQ: ::c_int = 76; /* Name not unique on network */
+pub const EBADFD: ::c_int = 77; /* File descriptor in bad state */
+pub const EREMCHG: ::c_int = 78; /* Remote address changed */
+pub const ELIBACC: ::c_int = 79; /* Can not access a needed shared library */
+pub const ELIBBAD: ::c_int = 80; /* Accessing a corrupted shared library */
+pub const ELIBSCN: ::c_int = 81; /* .lib section in a.out corrupted */
+pub const ELIBMAX: ::c_int = 82; /* Attempting to link in too many shared libraries */
+pub const ELIBEXEC: ::c_int = 83; /* Cannot exec a shared library directly */
+pub const EILSEQ: ::c_int = 84; /* Illegal byte sequence */
+pub const ERESTART: ::c_int = 85; /* Interrupted system call should be restarted */
+pub const ESTRPIPE: ::c_int = 86; /* Streams pipe error */
+pub const EUSERS: ::c_int = 87; /* Too many users */
+pub const ENOTSOCK: ::c_int = 88; /* Socket operation on non-socket */
+pub const EDESTADDRREQ: ::c_int = 89; /* Destination address required */
+pub const EMSGSIZE: ::c_int = 90; /* Message too long */
+pub const EPROTOTYPE: ::c_int = 91; /* Protocol wrong type for socket */
+pub const ENOPROTOOPT: ::c_int = 92; /* Protocol not available */
+pub const EPROTONOSUPPORT: ::c_int = 93; /* Protocol not supported */
+pub const ESOCKTNOSUPPORT: ::c_int = 94; /* Socket type not supported */
+pub const EOPNOTSUPP: ::c_int = 95; /* Operation not supported on transport endpoint */
+pub const EPFNOSUPPORT: ::c_int = 96; /* Protocol family not supported */
+pub const EAFNOSUPPORT: ::c_int = 97; /* Address family not supported by protocol */
+pub const EADDRINUSE: ::c_int = 98; /* Address already in use */
+pub const EADDRNOTAVAIL: ::c_int = 99; /* Cannot assign requested address */
+pub const ENETDOWN: ::c_int = 100; /* Network is down */
+pub const ENETUNREACH: ::c_int = 101; /* Network is unreachable */
+pub const ENETRESET: ::c_int = 102; /* Network dropped connection because of reset */
+pub const ECONNABORTED: ::c_int = 103; /* Software caused connection abort */
+pub const ECONNRESET: ::c_int = 104; /* Connection reset by peer */
+pub const ENOBUFS: ::c_int = 105; /* No buffer space available */
+pub const EISCONN: ::c_int = 106; /* Transport endpoint is already connected */
+pub const ENOTCONN: ::c_int = 107; /* Transport endpoint is not connected */
+pub const ESHUTDOWN: ::c_int = 108; /* Cannot send after transport endpoint shutdown */
+pub const ETOOMANYREFS: ::c_int = 109; /* Too many references: cannot splice */
+pub const ETIMEDOUT: ::c_int = 110; /* Connection timed out */
+pub const ECONNREFUSED: ::c_int = 111; /* Connection refused */
+pub const EHOSTDOWN: ::c_int = 112; /* Host is down */
+pub const EHOSTUNREACH: ::c_int = 113; /* No route to host */
+pub const EALREADY: ::c_int = 114; /* Operation already in progress */
+pub const EINPROGRESS: ::c_int = 115; /* Operation now in progress */
+pub const ESTALE: ::c_int = 116; /* Stale NFS file handle */
+pub const EUCLEAN: ::c_int = 117; /* Structure needs cleaning */
+pub const ENOTNAM: ::c_int = 118; /* Not a XENIX named type file */
+pub const ENAVAIL: ::c_int = 119; /* No XENIX semaphores available */
+pub const EISNAM: ::c_int = 120; /* Is a named type file */
+pub const EREMOTEIO: ::c_int = 121; /* Remote I/O error */
+pub const EDQUOT: ::c_int = 122; /* Quota exceeded */
+pub const ENOMEDIUM: ::c_int = 123; /* No medium found */
+pub const EMEDIUMTYPE: ::c_int = 124; /* Wrong medium type */
+pub const ECANCELED: ::c_int = 125; /* Operation Canceled */
+pub const ENOKEY: ::c_int = 126; /* Required key not available */
+pub const EKEYEXPIRED: ::c_int = 127; /* Key has expired */
+pub const EKEYREVOKED: ::c_int = 128; /* Key has been revoked */
+pub const EKEYREJECTED: ::c_int = 129; /* Key was rejected by service */
+pub const EOWNERDEAD: ::c_int = 130; /* Owner died */
+pub const ENOTRECOVERABLE: ::c_int = 131; /* State not recoverable */
+
+pub static STR_ERROR: [&'static str; 132] = [
+    "Success",
+    "Operation not permitted",
+    "No such file or directory",
+    "No such process",
+    "Interrupted system call",
+    "I/O error",
+    "No such device or address",
+    "Argument list too long",
+    "Exec format error",
+    "Bad file number",
+    "No child processes",
+    #[cfg(not(target_os = "dragonos"))]
+    "Try again",
+    #[cfg(target_os = "dragonos")]
+    "Try again or operation would block",
+    "Out of memory",
+    "Permission denied",
+    "Bad address",
+    "Block device required",
+    "Device or resource busy",
+    "File exists",
+    "Cross-device link",
+    "No such device",
+    "Not a directory",
+    "Is a directory",
+    "Invalid argument",
+    "File table overflow",
+    "Too many open files",
+    "Not a typewriter",
+    "Text file busy",
+    "File too large",
+    "No space left on device",
+    "Illegal seek",
+    "Read-only file system",
+    "Too many links",
+    "Broken pipe",
+    "Math argument out of domain of func",
+    "Math result not representable",
+    "Resource deadlock would occur",
+    "File name too long",
+    "No record locks available",
+    "Function not implemented",
+    "Directory not empty",
+    "Too many symbolic links encountered",
+    #[cfg(not(target_os = "dragonos"))]
+    "Operation would block",
+    "No message of desired type",
+    "Identifier removed",
+    "Channel number out of range",
+    "Level 2 not synchronized",
+    "Level 3 halted",
+    "Level 3 reset",
+    "Link number out of range",
+    "Protocol driver not attached",
+    "No CSI structure available",
+    "Level 2 halted",
+    "Invalid exchange",
+    "Invalid request descriptor",
+    "Exchange full",
+    "No anode",
+    "Invalid request code",
+    "Invalid slot",
+    "Resource deadlock would occur",
+    "Bad font file format",
+    "Device not a stream",
+    "No data available",
+    "Timer expired",
+    "Out of streams resources",
+    "Machine is not on the network",
+    "Package not installed",
+    "Object is remote",
+    "Link has been severed",
+    "Advertise error",
+    "Srmount error",
+    "Communication error on send",
+    "Protocol error",
+    "Multihop attempted",
+    "RFS specific error",
+    "Not a data message",
+    "Value too large for defined data type",
+    "Name not unique on network",
+    "File descriptor in bad state",
+    "Remote address changed",
+    "Can not access a needed shared library",
+    "Accessing a corrupted shared library",
+    ".lib section in a.out corrupted",
+    "Attempting to link in too many shared libraries",
+    "Cannot exec a shared library directly",
+    "Illegal byte sequence",
+    "Interrupted system call should be restarted",
+    "Streams pipe error",
+    "Too many users",
+    "Socket operation on non-socket",
+    "Destination address required",
+    "Message too long",
+    "Protocol wrong type for socket",
+    "Protocol not available",
+    "Protocol not supported",
+    "Socket type not supported",
+    "Operation not supported on transport endpoint",
+    "Protocol family not supported",
+    "Address family not supported by protocol",
+    "Address already in use",
+    "Cannot assign requested address",
+    "Network is down",
+    "Network is unreachable",
+    "Network dropped connection because of reset",
+    "Software caused connection abort",
+    "Connection reset by peer",
+    "No buffer space available",
+    "Transport endpoint is already connected",
+    "Transport endpoint is not connected",
+    "Cannot send after transport endpoint shutdown",
+    "Too many references: cannot splice",
+    "Connection timed out",
+    "Connection refused",
+    "Host is down",
+    "No route to host",
+    "Operation already in progress",
+    "Operation now in progress",
+    "Stale NFS file handle",
+    "Structure needs cleaning",
+    "Not a XENIX named type file",
+    "No XENIX semaphores available",
+    "Is a named type file",
+    "Remote I/O error",
+    "Quota exceeded",
+    "No medium found",
+    "Wrong medium type",
+    "Operation Canceled",
+    "Required key not available",
+    "Key has expired",
+    "Key has been revoked",
+    "Key was rejected by service",
+    "Owner died",
+    "State not recoverable",
+    #[cfg(target_os = "dragonos")]
+    "Unknown",
+];

+ 0 - 0
src/header/fcntl/cbindgen.toml → dlibc/src/unix/header/fcntl/cbindgen.toml


+ 32 - 0
dlibc/src/unix/header/fcntl/mod.rs

@@ -0,0 +1,32 @@
+//! fcntl implementation for Redox, following http://pubs.opengroup.org/onlinepubs/7908799/xsh/fcntl.h.html
+
+use crate::unix::c_str::CStr;
+
+pub use self::platform::*;
+use crate::unix::platform;
+
+#[no_mangle]
+pub unsafe extern "C" fn creat(path: *const ::c_char, mode: ::mode_t) -> ::c_int {
+    sys_open(path, O_WRONLY | O_CREAT | O_TRUNC, mode)
+}
+#[repr(C)]
+#[derive(Copy,Clone)]
+pub struct flock {
+    pub l_type: ::c_short,
+    pub l_whence: ::c_short,
+    pub l_start: ::off_t,
+    pub l_len: ::off_t,
+    pub l_pid: ::pid_t,
+}
+#[no_mangle]
+pub extern "C" fn sys_fcntl(fildes: ::c_int, cmd: ::c_int, arg: ::c_int) -> ::c_int {
+    platform::pal::fcntl(fildes, cmd, arg)
+}
+
+#[no_mangle]
+pub unsafe extern "C" fn sys_open(path: *const ::c_char, oflag: ::c_int, mode: ::mode_t) -> ::c_int {
+    platform::pal::open(path, oflag, mode)
+}
+
+#[no_mangle]
+pub unsafe extern "C" fn cbindgen_stupid_struct_user_for_fcntl(a: flock) {}

+ 9 - 0
dlibc/src/unix/header/float/cbindgen.toml

@@ -0,0 +1,9 @@
+sys_includes = ["sys/types.h", "bits/float.h"]
+include_guard = "_RELIBC_FLOAT_H"
+language = "C"
+style = "Tag"
+no_includes = true
+cpp_compat = true
+
+[enum]
+prefix_with_name = true

+ 14 - 0
dlibc/src/unix/header/float/mod.rs

@@ -0,0 +1,14 @@
+//! float.h implementation for Redox, following
+//! http://pubs.opengroup.org/onlinepubs/7908799/xsh/float.h.html
+
+use crate::header::_fenv::{fegetround, FE_TONEAREST};
+
+pub const FLT_RADIX: ::c_int = 2;
+
+#[no_mangle]
+pub unsafe extern "C" fn flt_rounds() -> ::c_int {
+    match fegetround() {
+        FE_TONEAREST => 1,
+        _ => -1,
+    }
+}

+ 8 - 0
dlibc/src/unix/header/fnmatch/cbindgen.toml

@@ -0,0 +1,8 @@
+include_guard = "_RELIBC_FNMATCH_H"
+language = "C"
+style = "Tag"
+no_includes = true
+cpp_compat = true
+
+[enum]
+prefix_with_name = true

+ 141 - 0
dlibc/src/unix/header/fnmatch/mod.rs

@@ -0,0 +1,141 @@
+//! fnmatch implementation
+
+use alloc::{borrow::Cow, vec::Vec};
+use core::slice;
+
+
+use posix_regex::{
+    compile::{Collation, Range, Token},
+    PosixRegex,
+};
+
+const ONCE: Range = Range(1, Some(1));
+
+pub const FNM_NOMATCH: ::c_int = 1;
+
+pub const FNM_NOESCAPE: ::c_int = 1;
+pub const FNM_PATHNAME: ::c_int = 2;
+pub const FNM_PERIOD: ::c_int = 4;
+pub const FNM_CASEFOLD: ::c_int = 8;
+// TODO: FNM_EXTMATCH
+
+unsafe fn tokenize(mut pattern: *const u8, flags: ::c_int) -> Vec<(Token, Range)> {
+    fn any(leading: bool, flags: ::c_int) -> Token {
+        let mut list = Vec::new();
+        if flags & FNM_PATHNAME == FNM_PATHNAME {
+            list.push(Collation::Char(b'/'))
+        }
+        if leading && flags & FNM_PERIOD == FNM_PERIOD {
+            list.push(Collation::Char(b'.'))
+        }
+        Token::OneOf { invert: true, list }
+    }
+    fn can_push(leading: bool, flags: ::c_int, c: u8) -> bool {
+        (c != b'/' || flags & FNM_PATHNAME != FNM_PATHNAME)
+            && (c != b'.' || !leading || flags & FNM_PERIOD != FNM_PERIOD)
+    }
+    fn is_leading(flags: ::c_int, c: u8) -> bool {
+        c == b'/' && flags & FNM_PATHNAME == FNM_PATHNAME
+    }
+
+    let mut tokens = Vec::new();
+    let mut leading = true;
+
+    while *pattern != 0 {
+        let was_leading = leading;
+        leading = false;
+
+        let c = *pattern;
+        pattern = pattern.offset(1);
+
+        tokens.push(match c {
+            b'\\' if flags & FNM_NOESCAPE == FNM_NOESCAPE => {
+                let c = *pattern;
+                if c == 0 {
+                    // Trailing backslash. Maybe error here?
+                    break;
+                }
+                pattern = pattern.offset(1);
+                leading = is_leading(flags, c);
+                (Token::Char(c), ONCE)
+            }
+            b'?' => (any(was_leading, flags), ONCE),
+            b'*' => (any(was_leading, flags), Range(0, None)),
+            b'[' => {
+                let mut list: Vec<Collation> = Vec::new();
+                let invert = if *pattern == b'!' {
+                    pattern = pattern.offset(1);
+                    true
+                } else {
+                    false
+                };
+
+                loop {
+                    let mut c = *pattern;
+                    if c == 0 {
+                        break;
+                    }
+                    pattern = pattern.offset(1);
+                    match c {
+                        b']' => break,
+                        b'\\' => {
+                            c = *pattern;
+                            pattern = pattern.offset(1);
+                            if c == 0 {
+                                // Trailing backslash. Maybe error?
+                                break;
+                            }
+                        }
+                        _ => (),
+                    }
+                    if *pattern == b'-' && *pattern.offset(1) != 0 {
+                        let end = *pattern.offset(1);
+                        pattern = pattern.offset(2);
+                        for c in c..=end {
+                            if can_push(was_leading, flags, c) {
+                                list.push(Collation::Char(c));
+                            }
+                        }
+                    } else if can_push(was_leading, flags, c) {
+                        list.push(Collation::Char(c));
+                    }
+                }
+                // Otherwise, there was no closing ]. Maybe error?
+
+                (Token::OneOf { invert, list }, ONCE)
+            }
+            c => {
+                leading = is_leading(flags, c);
+                (Token::Char(c), ONCE)
+            }
+        })
+    }
+    tokens
+}
+
+#[no_mangle]
+#[linkage = "weak"] // often redefined in GNU programs
+pub unsafe extern "C" fn fnmatch(
+    pattern: *const ::c_char,
+    input: *const ::c_char,
+    flags: ::c_int,
+) -> ::c_int {
+    let mut len = 0;
+    while *input.offset(len) != 0 {
+        len += 1;
+    }
+    let input = slice::from_raw_parts(input as *const u8, len as usize);
+
+    let mut tokens = tokenize(pattern as *const u8, flags);
+    tokens.push((Token::End, ONCE));
+
+    if PosixRegex::new(Cow::Owned(vec![tokens]))
+        .case_insensitive(flags & FNM_CASEFOLD == FNM_CASEFOLD)
+        .matches_exact(input)
+        .is_some()
+    {
+        0
+    } else {
+        FNM_NOMATCH
+    }
+}

+ 0 - 0
src/header/getopt/cbindgen.toml → dlibc/src/unix/header/getopt/cbindgen.toml


+ 40 - 43
src/header/getopt/mod.rs → dlibc/src/unix/header/getopt/mod.rs

@@ -1,37 +1,34 @@
 //! getopt implementation for relibc
 
-use crate::{
-    header::{
+use crate::unix::header::{
         stdio, string,
         unistd::{optarg, opterr, optind, optopt},
-    },
-    platform::types::*, c_str,
-};
+    };
 use core::ptr;
 
-static mut CURRENT_OPT: *mut c_char = ptr::null_mut();
+static mut CURRENT_OPT: *mut ::c_char = ptr::null_mut();
 
-pub const no_argument: c_int = 0;
-pub const required_argument: c_int = 1;
-pub const optional_argument: c_int = 2;
+pub const no_argument: ::c_int = 0;
+pub const required_argument: ::c_int = 1;
+pub const optional_argument: ::c_int = 2;
 
 #[repr(C)]
 pub struct option {
-    name: *const c_char,
-    has_arg: c_int,
-    flag: *mut c_int,
-    val: c_int,
+    name: *const ::c_char,
+    has_arg: ::c_int,
+    flag: *mut ::c_int,
+    val: ::c_int,
 }
 
 #[no_mangle]
 #[linkage = "weak"] // often redefined in GNU programs
 pub unsafe extern "C" fn getopt_long(
-    argc: c_int,
-    argv: *const *mut c_char,
-    optstring: *const c_char,
+    argc: ::c_int,
+    argv: *const *mut ::c_char,
+    optstring: *const ::c_char,
     longopts: *const option,
-    longindex: *mut c_int,
-) -> c_int {
+    longindex: *mut ::c_int,
+) -> ::c_int {
     // if optarg is not set, we still don't want the previous value leaking
     optarg = ptr::null_mut();
 
@@ -47,7 +44,7 @@ pub unsafe extern "C" fn getopt_long(
         } else {
             let current_arg = *argv.offset(optind as isize);
             if current_arg.is_null()
-                || *current_arg != b'-' as c_char
+                || *current_arg != b'-' as ::c_char
                 || *current_arg.offset(1) == 0
             {
                 -1
@@ -58,7 +55,7 @@ pub unsafe extern "C" fn getopt_long(
                 // remove the '-'
                 let current_arg = current_arg.offset(1);
 
-                if *current_arg == b'-' as c_char && !longopts.is_null() {
+                if *current_arg == b'-' as ::c_char && !longopts.is_null() {
                     let current_arg = current_arg.offset(1);
                     // is a long option
                     for i in 0.. {
@@ -70,27 +67,27 @@ pub unsafe extern "C" fn getopt_long(
                         let mut end = 0;
                         while {
                             let c = *current_arg.offset(end);
-                            c != 0 && c != b'=' as c_char
+                            c != 0 && c != b'=' as ::c_char
                         } {
                             end += 1;
                         }
 
-                        if string::strncmp(current_arg, opt.name, end as size_t) == 0 {
+                        if string::strncmp(current_arg, opt.name, end as ::size_t) == 0 {
                             optind += 1;
-                            *longindex = i as c_int;
+                            *longindex = i as ::c_int;
 
                             if opt.has_arg == optional_argument {
-                                if *current_arg.offset(end) == b'=' as c_char {
+                                if *current_arg.offset(end) == b'=' as ::c_char {
                                     optarg = current_arg.offset(end + 1);
                                 }
                             } else if opt.has_arg == required_argument {
-                                if *current_arg.offset(end) == b'=' as c_char {
+                                if *current_arg.offset(end) == b'=' as ::c_char {
                                     optarg = current_arg.offset(end + 1);
                                 } else if optind < argc {
                                     optarg = *argv.offset(optind as isize);
                                     optind += 1;
-                                } else if *optstring == b':' as c_char {
-                                    return b':' as c_int;
+                                } else if *optstring == b':' as ::c_char {
+                                    return b':' as ::c_int;
                                 } else {
                                     stdio::fputs(*argv as _, &mut *stdio::stderr);
                                     stdio::fputs(
@@ -102,7 +99,7 @@ pub unsafe extern "C" fn getopt_long(
                                         "' requires an argument\n\0".as_ptr() as _,
                                         &mut *stdio::stderr,
                                     );
-                                    return b'?' as c_int;
+                                    return b'?' as ::c_int;
                                 }
                             }
 
@@ -125,11 +122,11 @@ pub unsafe extern "C" fn getopt_long(
 }
 
 unsafe fn parse_arg(
-    argc: c_int,
-    argv: *const *mut c_char,
-    current_arg: *mut c_char,
-    optstring: *const c_char,
-) -> c_int {
+    argc: ::c_int,
+    argv: *const *mut ::c_char,
+    current_arg: *mut ::c_char,
+    optstring: *const ::c_char,
+) -> ::c_int {
     let update_current_opt = || {
         CURRENT_OPT = current_arg.offset(1);
         if *CURRENT_OPT == 0 {
@@ -149,7 +146,7 @@ unsafe fn parse_arg(
         Some(GetoptOption::Flag) => {
             update_current_opt();
 
-            *current_arg as c_int
+            *current_arg as ::c_int
         }
         Some(GetoptOption::OptArg) => {
             CURRENT_OPT = b"\0".as_ptr() as _;
@@ -158,8 +155,8 @@ unsafe fn parse_arg(
                 if optind > argc {
                     CURRENT_OPT = ptr::null_mut();
 
-                    optopt = *current_arg as c_int;
-                    let errch = if *optstring == b':' as c_char {
+                    optopt = *current_arg as ::c_int;
+                    let errch = if *optstring == b':' as ::c_char {
                         b':'
                     } else {
                         if opterr != 0 {
@@ -168,17 +165,17 @@ unsafe fn parse_arg(
 
                         b'?'
                     };
-                    errch as c_int
+                    errch as ::c_int
                 } else {
                     optarg = *argv.offset(optind as isize - 1);
 
-                    *current_arg as c_int
+                    *current_arg as ::c_int
                 }
             } else {
                 optarg = current_arg.offset(1);
                 optind += 1;
 
-                *current_arg as c_int
+                *current_arg as ::c_int
             }
         }
         None => {
@@ -189,8 +186,8 @@ unsafe fn parse_arg(
 
             update_current_opt();
 
-            optopt = *current_arg as c_int;
-            b'?' as c_int
+            optopt = *current_arg as ::c_int;
+            b'?' as ::c_int
         }
     }
 }
@@ -200,12 +197,12 @@ enum GetoptOption {
     OptArg,
 }
 
-unsafe fn find_option(ch: c_char, optstring: *const c_char) -> Option<GetoptOption> {
+unsafe fn find_option(ch: ::c_char, optstring: *const ::c_char) -> Option<GetoptOption> {
     let mut i = 0;
 
     while *optstring.offset(i) != 0 {
         if *optstring.offset(i) == ch {
-            let result = if *optstring.offset(i + 1) == b':' as c_char {
+            let result = if *optstring.offset(i + 1) == b':' as ::c_char {
                 GetoptOption::OptArg
             } else {
                 GetoptOption::Flag

+ 12 - 0
dlibc/src/unix/header/grp/cbindgen.toml

@@ -0,0 +1,12 @@
+sys_includes = []
+include_guard = "_RELIBC_GRP_H"
+language = "C"
+style = "Tag"
+no_includes = true
+cpp_compat = true
+
+[enum]
+prefix_with_name = true
+
+[export]
+include = ["group"]

+ 65 - 0
dlibc/src/unix/header/grp/mod.rs

@@ -0,0 +1,65 @@
+//! grp implementation for Redox, following http://pubs.opengroup.org/onlinepubs/7908799/xsh/grp.h.html
+
+
+
+#[repr(C)]
+pub struct group {
+    pub gr_name: *mut ::c_char,
+    pub gr_passwd: *mut ::c_char,
+    pub gr_gid: ::gid_t,
+    pub gr_mem: *mut *mut ::c_char,
+}
+
+// #[no_mangle]
+pub extern "C" fn getgrgid(gid: ::gid_t) -> *mut group {
+    unimplemented!();
+}
+
+// #[no_mangle]
+pub extern "C" fn getgrnam(name: *const ::c_char) -> *mut group {
+    unimplemented!();
+}
+
+// #[no_mangle]
+pub extern "C" fn getgrgid_r(
+    gid: ::gid_t,
+    grp: *mut group,
+    buffer: *mut ::c_char,
+    bufsize: usize,
+    result: *mut *mut group,
+) -> ::c_int {
+    unimplemented!();
+}
+
+// #[no_mangle]
+pub extern "C" fn getgrnam_r(
+    name: *const ::c_char,
+    grp: *mut group,
+    buffer: *mut ::c_char,
+    bufsize: usize,
+    result: *mut *mut group,
+) -> ::c_int {
+    unimplemented!();
+}
+
+// #[no_mangle]
+pub extern "C" fn getgrent() -> *mut group {
+    unimplemented!();
+}
+
+// #[no_mangle]
+pub extern "C" fn endgrent() {
+    unimplemented!();
+}
+
+// #[no_mangle]
+pub extern "C" fn setgrent() {
+    unimplemented!();
+}
+
+/*
+#[no_mangle]
+pub extern "C" fn func(args) -> ::c_int {
+    unimplemented!();
+}
+*/

+ 10 - 0
dlibc/src/unix/header/inttypes/cbindgen.toml

@@ -0,0 +1,10 @@
+sys_includes = ["stdint.h", "wchar.h"]
+include_guard = "_RELIBC_INTTYPES_H"
+trailer = "#include <bits/inttypes.h>"
+language = "C"
+style = "Type"
+no_includes = true
+cpp_compat = true
+
+[enum]
+prefix_with_name = true

+ 75 - 0
dlibc/src/unix/header/inttypes/mod.rs

@@ -0,0 +1,75 @@
+use crate::unix::header::{ctype, errno::*, stdlib::*};
+
+#[no_mangle]
+pub extern "C" fn imaxabs(i: ::intmax_t) -> ::intmax_t {
+    i.abs()
+}
+
+#[no_mangle]
+#[repr(C)]
+pub struct imaxdiv_t {
+    quot: ::intmax_t,
+    rem: ::intmax_t,
+}
+
+#[no_mangle]
+pub extern "C" fn imaxdiv(i: ::intmax_t, j: ::intmax_t) -> imaxdiv_t {
+    imaxdiv_t {
+        quot: i / j,
+        rem: i % j,
+    }
+}
+
+#[no_mangle]
+pub unsafe extern "C" fn strtoimax(
+    s: *const ::c_char,
+    endptr: *mut *mut ::c_char,
+    base: ::c_int,
+) -> ::intmax_t {
+    strto_impl!(
+        ::intmax_t,
+        false,
+        ::intmax_t::max_value(),
+        ::intmax_t::min_value(),
+        s,
+        endptr,
+        base
+    )
+}
+
+#[no_mangle]
+pub unsafe extern "C" fn strtoumax(
+    s: *const ::c_char,
+    endptr: *mut *mut ::c_char,
+    base: ::c_int,
+) -> ::uintmax_t {
+    strto_impl!(
+        ::uintmax_t,
+        false,
+        ::uintmax_t::max_value(),
+        ::uintmax_t::min_value(),
+        s,
+        endptr,
+        base
+    )
+}
+
+#[allow(unused)]
+// #[no_mangle]
+pub extern "C" fn wcstoimax(
+    nptr: *const ::wchar_t,
+    endptr: *mut *mut ::wchar_t,
+    base: ::c_int,
+) -> ::intmax_t {
+    unimplemented!();
+}
+
+#[allow(unused)]
+// #[no_mangle]
+pub extern "C" fn wcstoumax(
+    nptr: *const ::wchar_t,
+    endptr: *mut *mut ::wchar_t,
+    base: ::c_int,
+) -> ::uintmax_t {
+    unimplemented!();
+}

+ 0 - 0
src/header/libgen/cbindgen.toml → dlibc/src/unix/header/libgen/cbindgen.toml


+ 45 - 0
dlibc/src/unix/header/libgen/mod.rs

@@ -0,0 +1,45 @@
+//! libgen implementation for Redox, following http://pubs.opengroup.org/onlinepubs/7908799/xsh/libgen.h.html
+
+use crate::header::string::strlen;
+
+#[no_mangle]
+pub unsafe extern "C" fn basename(str: *mut ::c_char) -> *mut ::c_char {
+    if str.is_null() || strlen(str) == 0 {
+        return ".\0".as_ptr() as *mut ::c_char;
+    }
+    let mut end = strlen(str) as isize - 1;
+    while end >= 0 && *str.offset(end) == b'/' as ::c_char {
+        end -= 1;
+    }
+    if end == -1 {
+        return "/\0".as_ptr() as *mut ::c_char;
+    }
+    let mut begin = end;
+    while begin >= 0 && *str.offset(begin) != b'/' as ::c_char {
+        begin -= 1;
+    }
+    *str.offset(end + 1) = 0;
+    str.offset(begin + 1) as *mut ::c_char
+}
+
+#[no_mangle]
+pub unsafe extern "C" fn dirname(str: *mut ::c_char) -> *mut ::c_char {
+    if str.is_null() || strlen(str) == 0 {
+        return ".\0".as_ptr() as *mut ::c_char;
+    }
+    let mut end = strlen(str) as isize - 1;
+    while end > 0 && *str.offset(end) == b'/' as ::c_char {
+        end -= 1;
+    }
+    while end >= 0 && *str.offset(end) != b'/' as ::c_char {
+        end -= 1;
+    }
+    while end > 0 && *str.offset(end) == b'/' as ::c_char {
+        end -= 1;
+    }
+    if end == -1 {
+        return ".\0".as_ptr() as *mut ::c_char;
+    }
+    *str.offset(end + 1) = 0;
+    str
+}

+ 0 - 0
src/header/limits/cbindgen.toml → dlibc/src/unix/header/limits/cbindgen.toml


+ 0 - 0
src/header/limits/mod.rs → dlibc/src/unix/header/limits/mod.rs


+ 9 - 0
dlibc/src/unix/header/locale/cbindgen.toml

@@ -0,0 +1,9 @@
+include_guard = "_RELIBC_LOCALE_H"
+trailer = "#include <bits/locale.h>"
+language = "C"
+style = "Tag"
+no_includes = true
+cpp_compat = true
+
+[enum]
+prefix_with_name = true

+ 70 - 0
dlibc/src/unix/header/locale/mod.rs

@@ -0,0 +1,70 @@
+//! locale implementation for Redox, following http://pubs.opengroup.org/onlinepubs/7908799/xsh/locale.h.html
+
+use core::ptr;
+
+
+
+const EMPTY_PTR: *const ::c_char = "\0" as *const _ as *const ::c_char;
+// Can't use &str because of the mutability
+static mut C_LOCALE: [::c_char; 2] = [b'C' as ::c_char, 0];
+
+#[repr(C)]
+#[no_mangle]
+pub struct lconv {
+    currency_symbol: *const ::c_char,
+    decimal_point: *const ::c_char,
+    frac_digits: ::c_char,
+    grouping: *const ::c_char,
+    int_curr_symbol: *const ::c_char,
+    int_frac_digits: ::c_char,
+    mon_decimal_point: *const ::c_char,
+    mon_grouping: *const ::c_char,
+    mon_thousands_sep: *const ::c_char,
+    negative_sign: *const ::c_char,
+    n_cs_precedes: ::c_char,
+    n_sep_by_space: ::c_char,
+    n_sign_posn: ::c_char,
+    positive_sign: *const ::c_char,
+    p_cs_precedes: ::c_char,
+    p_sep_by_space: ::c_char,
+    p_sign_posn: ::c_char,
+    thousands_sep: *const ::c_char,
+}
+unsafe impl Sync for lconv {}
+
+// Mutable because POSIX demands a mutable pointer, even though it warns
+// against mutating it
+static mut CURRENT_LOCALE: lconv = lconv {
+    currency_symbol: EMPTY_PTR,
+    decimal_point: ".\0" as *const _ as *const ::c_char,
+    frac_digits: ::c_char::max_value(),
+    grouping: EMPTY_PTR,
+    int_curr_symbol: EMPTY_PTR,
+    int_frac_digits: ::c_char::max_value(),
+    mon_decimal_point: EMPTY_PTR,
+    mon_grouping: EMPTY_PTR,
+    mon_thousands_sep: EMPTY_PTR,
+    negative_sign: EMPTY_PTR,
+    n_cs_precedes: ::c_char::max_value(),
+    n_sep_by_space: ::c_char::max_value(),
+    n_sign_posn: ::c_char::max_value(),
+    positive_sign: EMPTY_PTR,
+    p_cs_precedes: ::c_char::max_value(),
+    p_sep_by_space: ::c_char::max_value(),
+    p_sign_posn: ::c_char::max_value(),
+    thousands_sep: EMPTY_PTR,
+};
+
+#[no_mangle]
+pub unsafe extern "C" fn localeconv() -> *mut lconv {
+    &mut CURRENT_LOCALE as *mut _
+}
+
+#[no_mangle]
+pub unsafe extern "C" fn setlocale(_option: ::c_int, val: *const ::c_char) -> *mut ::c_char {
+    if val.is_null() {
+        return C_LOCALE.as_mut_ptr() as *mut ::c_char;
+    }
+    // TODO actually implement
+    ptr::null_mut()
+}

+ 67 - 0
dlibc/src/unix/header/mod.rs

@@ -0,0 +1,67 @@
+pub mod _aio;
+pub mod _fenv;
+pub mod arpa_inet;
+pub mod assert;
+pub mod ctype;
+pub mod dirent;
+#[path = "dl-tls/mod.rs"]
+pub mod dl_tls;
+pub mod dlfcn;
+pub mod elf;
+pub mod errno;
+pub mod fcntl;
+pub mod float;
+pub mod fnmatch;
+pub mod getopt;
+pub mod grp;
+pub mod inttypes;
+pub mod libgen;
+pub mod limits;
+pub mod locale;
+pub mod netdb;
+pub mod netinet_in;
+pub mod netinet_ip;
+pub mod netinet_tcp;
+pub mod poll;
+pub mod pwd;
+pub mod regex;
+pub mod semaphore;
+pub mod setjmp;
+pub mod sgtty;
+pub mod signal;
+pub mod stdio;
+pub mod stdlib;
+pub mod string;
+pub mod strings;
+pub mod sys_auxv;
+pub mod sys_epoll;
+pub mod sys_file;
+pub mod sys_ioctl;
+pub mod sys_mman;
+pub mod sys_ptrace;
+pub mod sys_resource;
+pub mod sys_select;
+pub mod sys_socket;
+pub mod sys_stat;
+pub mod sys_statvfs;
+pub mod sys_time;
+pub mod sys_timeb;
+//pub mod sys_times;
+pub mod arch_aarch64_user;
+pub mod arch_x64_user;
+#[cfg(not(target_arch = "x86"))] // TODO: x86
+pub mod sys_procfs;
+pub mod sys_random;
+pub mod sys_types;
+pub mod sys_uio;
+pub mod sys_un;
+pub mod sys_utsname;
+pub mod sys_wait;
+pub mod termios;
+pub mod time;
+pub mod unistd;
+pub mod utime;
+pub mod wchar;
+pub mod wctype;
+
+pub use self::unistd::*;

+ 13 - 0
dlibc/src/unix/header/netdb/cbindgen.toml

@@ -0,0 +1,13 @@
+sys_includes = ["sys/socket.h", "netinet/in.h"]
+include_guard = "_RELIBC_NETDB_H"
+trailer = "#include <bits/netdb.h>"
+language = "C"
+style = "Tag"
+no_includes = true
+cpp_compat = true
+
+[export.rename]
+"sockaddr" = "struct sockaddr"
+
+[enum]
+prefix_with_name = true

+ 21 - 0
dlibc/src/unix/header/netdb/dns/answer.rs

@@ -0,0 +1,21 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use alloc::{string::String, vec::Vec};
+
+#[derive(Clone, Debug)]
+pub struct DnsAnswer {
+    pub name: String,
+    pub a_type: u16,
+    pub a_class: u16,
+    pub ttl_a: u16,
+    pub ttl_b: u16,
+    pub data: Vec<u8>,
+}

+ 212 - 0
dlibc/src/unix/header/netdb/dns/mod.rs

@@ -0,0 +1,212 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+pub use self::{answer::DnsAnswer, query::DnsQuery};
+
+use alloc::{string::String, vec::Vec};
+use core::{slice, u16};
+
+mod answer;
+mod query;
+
+use core::ptr;
+use mem;
+use alloc::boxed::Box;
+
+#[allow(non_camel_case_types)]
+#[derive(Copy, Clone, Debug, Default)]
+#[repr(packed)]
+pub struct n16 {
+    inner: u16,
+}
+
+impl n16 {
+    pub fn as_bytes(&self) -> &[u8] {
+        let left_8bits = (self.inner >> 8) as u8;
+        let right_8bits = self.inner as u8;
+        unsafe {
+            let bytes: [u8; 2] = [left_8bits, right_8bits];
+            slice::from_raw_parts(bytes.as_ptr(), 2)
+        }
+    }
+    // pub fn as_bytes(&self) -> &[u8] {
+    //     unsafe { slice::from_raw_parts((&self.inner as *const u16) as *const u8, 2) }
+    // }
+
+    pub fn from_bytes(bytes: &[u8]) -> Self {
+        n16 {
+            inner: unsafe {
+                slice::from_raw_parts(bytes.as_ptr() as *const u16, bytes.len() / 2)[0]
+            },
+        }
+    }
+}
+
+impl From<u16> for n16 {
+    fn from(value: u16) -> Self {
+        n16 {
+            inner: value.to_be(),
+        }
+    }
+}
+
+impl From<n16> for u16 {
+    fn from(value: n16) -> Self {
+        u16::from_be(value.inner)
+    }
+}
+
+#[derive(Clone, Debug)]
+pub struct Dns {
+    pub transaction_id: u16,
+    pub flags: u16,
+    pub queries: Vec<DnsQuery>,
+    pub answers: Vec<DnsAnswer>,
+}
+
+impl Dns {
+    pub fn compile(&self) -> Vec<u8> {
+        let mut data = Vec::new();
+
+        macro_rules! push_u8 {
+            ($value:expr) => {
+                data.push($value);
+            };
+        };
+
+        macro_rules! push_n16 {
+            ($value:expr) => {
+                data.extend_from_slice(n16::from($value).as_bytes());
+            };
+        };
+
+        push_n16!(self.transaction_id);
+        push_n16!(self.flags);
+        push_n16!(self.queries.len() as u16);
+        push_n16!(self.answers.len() as u16);
+        push_n16!(0);
+        push_n16!(0);
+
+        for query in self.queries.iter() {
+            for part in query.name.split('.') {
+                push_u8!(part.len() as u8);
+                data.extend_from_slice(part.as_bytes());
+            }
+            push_u8!(0);
+            push_n16!(query.q_type);
+            push_n16!(query.q_class);
+        }
+        data
+    }
+
+    pub fn parse(data: &[u8]) -> Result<Self, String> {
+        let name_ind = 0b1100_0000;
+        let mut i = 0;
+
+        macro_rules! pop_u8 {
+            () => {{
+                i += 1;
+                if i > data.len() {
+                    return Err(format!("{}: {}: pop_u8", file!(), line!()));
+                }
+                data[i - 1]
+            }};
+        };
+
+        macro_rules! pop_n16 {
+            () => {{
+                i += 2;
+                if i > data.len() {
+                    return Err(format!("{}: {}: pop_n16", file!(), line!()));
+                }
+                u16::from(n16::from_bytes(&data[i - 2..i]))
+            }};
+        };
+
+        macro_rules! pop_data {
+            () => {{
+                let mut data = Vec::new();
+
+                let data_len = pop_n16!();
+                for _data_i in 0..data_len {
+                    data.push(pop_u8!());
+                }
+
+                data
+            }};
+        };
+
+        macro_rules! pop_name {
+            () => {{
+                let mut name = String::new();
+                let old_i = i;
+
+                loop {
+                    let name_len = pop_u8!();
+                    if name_len & name_ind == name_ind {
+                        i -= 1;
+                        i = (pop_n16!() - ((name_ind as u16) << 8)) as usize;
+                        continue;
+                    }
+                    if name_len == 0 {
+                        break;
+                    }
+                    if !name.is_empty() {
+                        name.push('.');
+                    }
+                    for _name_i in 0..name_len {
+                        name.push(pop_u8!() as char);
+                    }
+                }
+
+                if i <= old_i {
+                    i = old_i + 2;
+                }
+
+                name
+            }};
+        };
+
+        let transaction_id = pop_n16!();
+        let flags = pop_n16!();
+        let queries_len = pop_n16!();
+        let answers_len = pop_n16!();
+        pop_n16!();
+        pop_n16!();
+
+        let mut queries = Vec::new();
+        for _query_i in 0..queries_len {
+            queries.push(DnsQuery {
+                name: pop_name!(),
+                q_type: pop_n16!(),
+                q_class: pop_n16!(),
+            });
+        }
+
+        let mut answers = Vec::new();
+        for _answer_i in 0..answers_len {
+            answers.push(DnsAnswer {
+                name: pop_name!(),
+                a_type: pop_n16!(),
+                a_class: pop_n16!(),
+                ttl_a: pop_n16!(),
+                ttl_b: pop_n16!(),
+                data: pop_data!(),
+            });
+        }
+
+        Ok(Dns {
+            transaction_id,
+            flags,
+            queries,
+            answers,
+        })
+    }
+}

+ 18 - 0
dlibc/src/unix/header/netdb/dns/query.rs

@@ -0,0 +1,18 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use alloc::string::String;
+
+#[derive(Clone, Debug)]
+pub struct DnsQuery {
+    pub name: String,
+    pub q_type: u16,
+    pub q_class: u16,
+}

+ 29 - 0
dlibc/src/unix/header/netdb/dragonos.rs

@@ -0,0 +1,29 @@
+use unix::{
+    c_str::CString,
+    fs::File,
+    header::fcntl,
+    io::{BufRead, BufReader},
+};
+use alloc::string::String;
+
+pub fn get_dns_server() -> String {
+    let file = match File::open(&CString::new("/etc/resolv.conf").unwrap(), fcntl::O_RDONLY) {
+        Ok(file) => file,
+        Err(_) => return String::new(), // TODO: better error handling
+    };
+    let file = BufReader::new(file);
+
+    for line in file.split(b'\n') {
+        let mut line = match line {
+            Ok(line) => line,
+            Err(_) => return String::new(), // TODO: pls handle errors
+        };
+        if line.starts_with(b"nameserver ") {
+            line.drain(..11);
+            return String::from_utf8(line).unwrap_or_default();
+        }
+    }
+
+    // TODO: better error handling
+    String::new()
+}

+ 124 - 0
dlibc/src/unix/header/netdb/host.rs

@@ -0,0 +1,124 @@
+use alloc::{boxed::Box, str::SplitWhitespace, vec::Vec};
+use core::{mem, ptr};
+
+use crate::unix::platform;
+use crate::unix::{
+    c_str::CString,
+    header::{
+        arpa_inet::inet_aton, fcntl::O_RDONLY, netinet_in::in_addr, sys_socket::constants::AF_INET,
+        unistd::SEEK_SET,
+    },
+    platform::rlb::{Line, RawLineBuffer},
+};
+
+use super::{bytes_to_box_str, hostent};
+
+static mut HOSTDB: ::c_int = -1;
+pub static mut HOST_ENTRY: hostent = hostent {
+    h_name: ptr::null_mut(),
+    h_aliases: ptr::null_mut(),
+    h_addrtype: 0,
+    h_length: 0,
+    h_addr_list: ptr::null_mut(),
+};
+pub static mut HOST_NAME: Option<Vec<u8>> = None;
+pub static mut HOST_ALIASES: Option<Vec<Vec<u8>>> = None;
+static mut _HOST_ALIASES: Option<Vec<*mut i8>> = None;
+pub static mut HOST_ADDR: Option<in_addr> = None;
+pub static mut HOST_ADDR_LIST: [*mut ::c_char; 2] = [ptr::null_mut(); 2];
+pub static mut _HOST_ADDR_LIST: [u8; 4] = [0u8; 4];
+static mut H_POS: usize = 0;
+pub static mut HOST_STAYOPEN: ::c_int = 0;
+
+#[no_mangle]
+pub unsafe extern "C" fn endhostent() {
+    if HOSTDB >= 0 {
+        platform::pal::close(HOSTDB);
+    }
+    HOSTDB = -1;
+}
+
+#[no_mangle]
+pub unsafe extern "C" fn sethostent(stayopen: ::c_int) {
+    HOST_STAYOPEN = stayopen;
+    if HOSTDB < 0 {
+        HOSTDB = platform::pal::open("/etc/hosts".as_ptr() as *const i8, O_RDONLY, 0)
+    } else {
+        platform::pal::lseek(HOSTDB, 0, SEEK_SET);
+    }
+    H_POS = 0;
+}
+
+#[no_mangle]
+pub unsafe extern "C" fn gethostent() -> *mut hostent {
+    if HOSTDB < 0 {
+        HOSTDB = platform::pal::open("/etc/hosts".as_ptr() as *const i8, O_RDONLY, 0);
+    }
+    let mut rlb = RawLineBuffer::new(HOSTDB);
+    rlb.seek(H_POS);
+
+    let mut r: Box<str> = Box::default();
+    while r.is_empty() || r.split_whitespace().next() == None || r.starts_with('#') {
+        r = match rlb.next() {
+            Line::Some(s) => bytes_to_box_str(s),
+            _ => {
+                if HOST_STAYOPEN == 0 {
+                    endhostent();
+                }
+                return ptr::null_mut();
+            }
+        };
+    }
+    rlb.next();
+    H_POS = rlb.line_pos();
+
+    let mut iter: SplitWhitespace = r.split_whitespace();
+
+    let mut addr_vec = iter.next().unwrap().as_bytes().to_vec();
+    addr_vec.push(b'\0');
+    let addr_cstr = addr_vec.as_slice().as_ptr() as *const i8;
+    let mut addr = mem::MaybeUninit::uninit();
+    inet_aton(addr_cstr, addr.as_mut_ptr());
+    let addr = addr.assume_init();
+
+    _HOST_ADDR_LIST = mem::transmute::<u32, [u8; 4]>(addr.s_addr);
+    HOST_ADDR_LIST = [_HOST_ADDR_LIST.as_mut_ptr() as *mut ::c_char, ptr::null_mut()];
+
+    HOST_ADDR = Some(addr);
+
+    let mut host_name = iter.next().unwrap().as_bytes().to_vec();
+    host_name.push(b'\0');
+
+    let mut _host_aliases: Vec<Vec<u8>> = Vec::new();
+
+    for s in iter {
+        let mut alias = s.as_bytes().to_vec();
+        alias.push(b'\0');
+        _host_aliases.push(alias);
+    }
+    HOST_ALIASES = Some(_host_aliases);
+
+    let mut host_aliases: Vec<*mut i8> = HOST_ALIASES
+        .as_mut()
+        .unwrap()
+        .iter_mut()
+        .map(|x| x.as_mut_ptr() as *mut i8)
+        .collect();
+    host_aliases.push(ptr::null_mut());
+    host_aliases.push(ptr::null_mut());
+
+    HOST_NAME = Some(host_name);
+
+    HOST_ENTRY = hostent {
+        h_name: HOST_NAME.as_mut().unwrap().as_mut_ptr() as *mut ::c_char,
+        h_aliases: host_aliases.as_mut_slice().as_mut_ptr() as *mut *mut i8,
+        h_addrtype: AF_INET,
+        h_length: 4,
+        h_addr_list: HOST_ADDR_LIST.as_mut_ptr(),
+    };
+    _HOST_ALIASES = Some(host_aliases);
+    if HOST_STAYOPEN == 0 {
+        endhostent();
+    }
+    &mut HOST_ENTRY as *mut hostent
+}

+ 29 - 0
dlibc/src/unix/header/netdb/linux.rs

@@ -0,0 +1,29 @@
+use crate::{
+    c_str::CString,
+    fs::File,
+    header::fcntl,
+    io::{BufRead, BufReader},
+};
+use alloc::string::String;
+
+pub fn get_dns_server() -> String {
+    let file = match File::open(&CString::new("/etc/resolv.conf").unwrap(), fcntl::O_RDONLY) {
+        Ok(file) => file,
+        Err(_) => return String::new(), // TODO: better error handling
+    };
+    let file = BufReader::new(file);
+
+    for line in file.split(b'\n') {
+        let mut line = match line {
+            Ok(line) => line,
+            Err(_) => return String::new(), // TODO: pls handle errors
+        };
+        if line.starts_with(b"nameserver ") {
+            line.drain(..11);
+            return String::from_utf8(line).unwrap_or_default();
+        }
+    }
+
+    // TODO: better error handling
+    String::new()
+}

+ 256 - 0
dlibc/src/unix/header/netdb/lookup.rs

@@ -0,0 +1,256 @@
+use alloc::{
+    boxed::Box,
+    string::{String, ToString},
+    vec::{IntoIter, Vec},
+};
+use core::mem;
+
+use crate::unix::header::{
+    arpa_inet::htons,
+    errno::*,
+    netinet_in::{in_addr, sockaddr_in, IPPROTO_UDP},
+    sys_socket::{
+        self,
+        constants::{AF_INET, SOCK_DGRAM},
+        socklen_t,
+    },
+    time,
+};
+use unix::platform;
+use super::{
+    dns::{Dns, DnsQuery},
+    sys::get_dns_server,
+};
+
+pub struct LookupHost(IntoIter<in_addr>);
+
+impl Iterator for LookupHost {
+    type Item = in_addr;
+    fn next(&mut self) -> Option<Self::Item> {
+        self.0.next()
+    }
+}
+
+pub fn lookup_host(host: &str) -> Result<LookupHost, ::c_int> {
+    let dns_string = get_dns_server();
+
+    let dns_vec: Vec<u8> = dns_string
+        .trim()
+        .split('.')
+        .map(|octet| octet.parse::<u8>().unwrap_or(0))
+        .collect();
+
+    if dns_vec.len() == 4 {
+        let mut dns_arr = [0u8; 4];
+        for (i, octet) in dns_vec.iter().enumerate() {
+            dns_arr[i] = *octet;
+        }
+        let dns_addr = unsafe { mem::transmute::<[u8; 4], u32>(dns_arr) };
+
+        let mut timespec = ::timespec::default();
+        unsafe{platform::pal::clock_gettime(::CLOCK_REALTIME, &mut timespec);}
+        let tid = (timespec.tv_nsec >> 16) as u16;
+
+        let packet = Dns {
+            transaction_id: tid,
+            flags: 0x0100,
+            queries: vec![DnsQuery {
+                name: host.to_string(),
+                q_type: 0x0001,
+                q_class: 0x0001,
+            }],
+            answers: vec![],
+        };
+
+        let packet_data = packet.compile();
+        let packet_data_len = packet_data.len();
+
+        let packet_data_box = packet_data.into_boxed_slice();
+        let packet_data_ptr = Box::into_raw(packet_data_box) as *mut _ as *mut ::c_void;
+
+        let dest = sockaddr_in {
+            sin_family: AF_INET as u16,
+            sin_port: htons(53),
+            sin_addr: in_addr { s_addr: dns_addr },
+            ..Default::default()
+        };
+        let dest_ptr = &dest as *const _ as *const ::sockaddr;
+
+        let sock = unsafe {
+            let sock = ::socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP as i32);
+            if ::connect(sock, dest_ptr, mem::size_of_val(&dest) as socklen_t) < 0 {
+                return Err(EIO);
+            }
+            if ::send(sock, packet_data_ptr, packet_data_len, 0) < 0 {
+                Box::from_raw(packet_data_ptr);
+                return Err(EIO);
+            }
+            sock
+        };
+
+        unsafe {
+            Box::from_raw(packet_data_ptr);
+        }
+
+        let i = 0 as socklen_t;
+        let mut buf = vec![0u8; 65536];
+        let buf_ptr = buf.as_mut_ptr() as *mut ::c_void;
+
+        let count = unsafe { ::recv(sock, buf_ptr, 65536, 0) };
+        if count < 0 {
+            return Err(EIO);
+        }
+
+        match Dns::parse(&buf[..count as usize]) {
+            Ok(response) => {
+                let mut addrs = vec![];
+                for answer in response.answers.iter() {
+                    if answer.a_type == 0x0001 && answer.a_class == 0x0001 && answer.data.len() == 4
+                    {
+                        let addr = in_addr {
+                            s_addr: unsafe {
+                                mem::transmute::<[u8; 4], u32>([
+                                    answer.data[0],
+                                    answer.data[1],
+                                    answer.data[2],
+                                    answer.data[3],
+                                ])
+                            },
+                        };
+                        addrs.push(addr);
+                    }
+                }
+                Ok(LookupHost(addrs.into_iter()))
+            }
+            Err(_err) => Err(EINVAL),
+        }
+    } else {
+        Err(EINVAL)
+    }
+}
+
+pub fn lookup_addr(addr: in_addr) -> Result<Vec<Vec<u8>>, ::c_int> {
+    let dns_string = get_dns_server();
+
+    let dns_vec: Vec<u8> = dns_string
+        .trim()
+        .split('.')
+        .map(|octet| octet.parse::<u8>().unwrap_or(0))
+        .collect();
+
+    let mut dns_arr = [0u8; 4];
+
+    for (i, octet) in dns_vec.iter().enumerate() {
+        dns_arr[i] = *octet;
+    }
+
+    let mut addr_vec: Vec<u8> = unsafe { mem::transmute::<u32, [u8; 4]>(addr.s_addr).to_vec() };
+    addr_vec.reverse();
+    let mut name: Vec<u8> = vec![];
+    for octet in addr_vec {
+        for ch in format!("{}", octet).as_bytes() {
+            name.push(*ch);
+        }
+        name.push(b"."[0]);
+    }
+    name.pop();
+    for ch in b".IN-ADDR.ARPA" {
+        name.push(*ch);
+    }
+
+    if dns_vec.len() == 4 {
+        let mut timespec = ::timespec::default();
+        unsafe{platform::pal::clock_gettime(::CLOCK_REALTIME, &mut timespec);}
+        let tid = (timespec.tv_nsec >> 16) as u16;
+
+        let packet = Dns {
+            transaction_id: tid,
+            flags: 0x0100,
+            queries: vec![DnsQuery {
+                name: String::from_utf8(name).unwrap(),
+                q_type: 0x000C,
+                q_class: 0x0001,
+            }],
+            answers: vec![],
+        };
+
+        let packet_data = packet.compile();
+        let packet_data_len = packet_data.len();
+        let packet_data_box = packet_data.into_boxed_slice();
+        let packet_data_ptr = Box::into_raw(packet_data_box) as *mut _ as *mut ::c_void;
+
+        let dest = sockaddr_in {
+            sin_family: AF_INET as u16,
+            sin_port: htons(53),
+            sin_addr: in_addr {
+                s_addr: unsafe { mem::transmute::<[u8; 4], u32>(dns_arr) },
+            },
+            ..Default::default()
+        };
+
+        let dest_ptr = &dest as *const _ as *const ::sockaddr;
+
+        let sock = unsafe {
+            let sock = ::socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP as i32);
+            if ::connect(sock, dest_ptr, mem::size_of_val(&dest) as socklen_t) < 0 {
+                return Err(EIO);
+            }
+            sock
+        };
+
+        unsafe {
+            if ::send(sock, packet_data_ptr, packet_data_len, 0) < 0 {
+                return Err(EIO);
+            }
+        }
+
+        unsafe {
+            Box::from_raw(packet_data_ptr);
+        }
+
+        let i = mem::size_of::<sockaddr_in>() as socklen_t;
+        let mut buf = [0u8; 65536];
+        let buf_ptr = buf.as_mut_ptr() as *mut ::c_void;
+
+        let count = unsafe { ::recv(sock, buf_ptr, 65536, 0) };
+        if count < 0 {
+            return Err(EIO);
+        }
+
+        match Dns::parse(&buf[..count as usize]) {
+            Ok(response) => {
+                let mut names = vec![];
+                for answer in response.answers.iter() {
+                    if answer.a_type == 0x000C && answer.a_class == 0x0001 {
+                        // answer.data is encoded kinda weird.
+                        // Basically length-prefixed strings for each
+                        // subsection of the domain.
+                        // We need to parse this to insert periods where
+                        // they belong (ie at the end of each string)
+                        let data = parse_revdns_answer(&answer.data);
+                        names.push(data);
+                    }
+                }
+                Ok(names)
+            }
+            Err(_err) => Err(EINVAL),
+        }
+    } else {
+        Err(EINVAL)
+    }
+}
+
+fn parse_revdns_answer(data: &[u8]) -> Vec<u8> {
+    let mut cursor = 0;
+    let mut index = 0;
+    let mut output = data.to_vec();
+    while index < data.len() - 1 {
+        let offset = data[index] as usize;
+        index = cursor + offset + 1;
+        output[index] = b'.';
+        cursor = index;
+    }
+    //we don't want an extra period at the end
+    output.pop();
+    output
+}

+ 911 - 0
dlibc/src/unix/header/netdb/mod.rs

@@ -0,0 +1,911 @@
+//! netdb implementation for Redox, following http://pubs.opengroup.org/onlinepubs/7908799/xns/netdb.h.html
+
+mod dns;
+
+use core::{
+    mem, ptr, slice,
+    str::{self, FromStr},
+};
+
+use alloc::{borrow::ToOwned, boxed::Box, str::SplitWhitespace, vec::Vec};
+use crate::unix::header::{
+    arpa_inet::{htons, inet_aton, ntohl},
+    errno::*,
+    fcntl::O_RDONLY,
+    netinet_in::{in_addr, sockaddr_in, sockaddr_in6},
+    stdlib::atoi,
+    strings::strcasecmp,
+    sys_socket::{constants::AF_INET, sa_family_t, socklen_t},
+    unistd::SEEK_SET,
+};
+
+use sockaddr;
+
+use crate::unix::{
+    c_str::{CStr, CString},
+    platform::{
+        self,
+        rlb::{Line, RawLineBuffer},
+    },
+};
+
+#[cfg(target_os = "linux")]
+#[path = "linux.rs"]
+pub mod sys;
+
+#[cfg(target_os = "dragonos")]
+#[path = "dragonos.rs"]
+pub mod sys;
+
+#[cfg(target_os = "redox")]
+#[path = "redox.rs"]
+pub mod sys;
+
+pub use self::host::*;
+pub mod host;
+
+pub use self::lookup::*;
+pub mod lookup;
+
+#[repr(C)]
+pub struct hostent {
+    h_name: *mut ::c_char,
+    h_aliases: *mut *mut ::c_char,
+    h_addrtype: ::c_int,
+    h_length: ::c_int,
+    h_addr_list: *mut *mut ::c_char,
+}
+
+#[repr(C)]
+pub struct netent {
+    n_name: *mut ::c_char,         /* official name of net */
+    n_aliases: *mut *mut ::c_char, /* alias list */
+    n_addrtype: ::c_int,           /* net address type */
+    n_net: ::c_ulong,              /* network # */
+}
+
+#[repr(C)]
+pub struct protoent {
+    p_name: *mut ::c_char,         /* official protocol name */
+    p_aliases: *mut *mut ::c_char, /* alias list */
+    p_proto: ::c_int,              /* protocol # */
+}
+
+#[repr(C)]
+pub struct servent {
+    s_name: *mut ::c_char,         /* official service name */
+    s_aliases: *mut *mut ::c_char, /* alias list */
+    s_port: ::c_int,               /* port # */
+    s_proto: *mut ::c_char,        /* protocol to use */
+}
+
+#[repr(C)]
+#[derive(Debug)]
+pub struct addrinfo {
+    ai_flags: ::c_int,           /* AI_PASSIVE, AI_CANONNAME, AI_NUMERICHOST */
+    ai_family: ::c_int,          /* PF_xxx */
+    ai_socktype: ::c_int,        /* SOCK_xxx */
+    ai_protocol: ::c_int,        /* 0 or IPPROTO_xxx for IPv4 and IPv6 */
+    ai_addrlen: ::size_t,        /* length of ai_addr */
+    ai_canonname: *mut ::c_char, /* canonical name for hostname */
+    ai_addr: *mut sockaddr,    /* binary address */
+    ai_next: *mut addrinfo,    /* next structure in linked list */
+}
+
+pub const AI_PASSIVE: ::c_int = 0x0001;
+pub const AI_CANONNAME: ::c_int = 0x0002;
+pub const AI_NUMERICHOST: ::c_int = 0x0004;
+pub const AI_V4MAPPED: ::c_int = 0x0008;
+pub const AI_ALL: ::c_int = 0x0010;
+pub const AI_ADDRCONFIG: ::c_int = 0x0020;
+pub const AI_NUMERICSERV: ::c_int = 0x0400;
+
+pub const EAI_BADFLAGS: ::c_int = -1;
+pub const EAI_NONAME: ::c_int = -2;
+pub const EAI_AGAIN: ::c_int = -3;
+pub const EAI_FAIL: ::c_int = -4;
+pub const EAI_NODATA: ::c_int = -5;
+pub const EAI_FAMILY: ::c_int = -6;
+pub const EAI_SOCKTYPE: ::c_int = -7;
+pub const EAI_SERVICE: ::c_int = -8;
+pub const EAI_ADDRFAMILY: ::c_int = -9;
+pub const EAI_MEMORY: ::c_int = -10;
+pub const EAI_SYSTEM: ::c_int = -11;
+pub const EAI_OVERFLOW: ::c_int = -12;
+
+pub const NI_MAXHOST: ::c_int = 1025;
+pub const NI_MAXSERV: ::c_int = 32;
+
+pub const NI_NUMERICHOST: ::c_int = 0x0001;
+pub const NI_NUMERICSERV: ::c_int = 0x0002;
+pub const NI_NOFQDN: ::c_int = 0x0004;
+pub const NI_NAMEREQD: ::c_int = 0x0008;
+pub const NI_DGRAM: ::c_int = 0x0010;
+
+static mut NETDB: ::c_int = 0;
+pub static mut NET_ENTRY: netent = netent {
+    n_name: ptr::null_mut(),
+    n_aliases: ptr::null_mut(),
+    n_addrtype: 0,
+    n_net: 0,
+};
+pub static mut NET_NAME: Option<Vec<u8>> = None;
+pub static mut NET_ALIASES: Option<Vec<Vec<u8>>> = None;
+pub static mut NET_ADDR: Option<u32> = None;
+static mut N_POS: usize = 0;
+static mut NET_STAYOPEN: ::c_int = 0;
+
+#[allow(non_upper_case_globals)]
+#[no_mangle]
+pub static mut h_errno: ::c_int = 0;
+pub const HOST_NOT_FOUND: ::c_int = 1;
+pub const NO_DATA: ::c_int = 2;
+pub const NO_RECOVERY: ::c_int = 3;
+pub const TRY_AGAIN: ::c_int = 4;
+
+static mut PROTODB: ::c_int = 0;
+static mut PROTO_ENTRY: protoent = protoent {
+    p_name: ptr::null_mut(),
+    p_aliases: ptr::null_mut(),
+    p_proto: 0 as ::c_int,
+};
+static mut PROTO_NAME: Option<Vec<u8>> = None;
+static mut PROTO_ALIASES: Option<Vec<Vec<u8>>> = None;
+static mut PROTO_NUM: Option<::c_int> = None;
+static mut P_POS: usize = 0;
+static mut PROTO_STAYOPEN: ::c_int = 0;
+
+static mut SERVDB: ::c_int = 0;
+static mut SERV_ENTRY: servent = servent {
+    s_name: ptr::null_mut(),
+    s_aliases: ptr::null_mut(),
+    s_port: 0 as ::c_int,
+    s_proto: ptr::null_mut(),
+};
+static mut SERV_NAME: Option<Vec<u8>> = None;
+static mut SERV_ALIASES: Option<Vec<Vec<u8>>> = None;
+static mut SERV_PORT: Option<::c_int> = None;
+static mut SERV_PROTO: Option<Vec<u8>> = None;
+static mut S_POS: usize = 0;
+static mut SERV_STAYOPEN: ::c_int = 0;
+
+fn bytes_to_box_str(bytes: &[u8]) -> Box<str> {
+    Box::from(core::str::from_utf8(bytes).unwrap_or(""))
+}
+
+#[no_mangle]
+pub unsafe extern "C" fn endnetent() {
+    platform::pal::close(NETDB);
+    NETDB = 0;
+}
+
+#[no_mangle]
+pub unsafe extern "C" fn endprotoent() {
+    platform::pal::close(PROTODB);
+    PROTODB = 0;
+}
+
+#[no_mangle]
+pub unsafe extern "C" fn endservent() {
+    platform::pal::close(SERVDB);
+    SERVDB = 0;
+}
+
+#[no_mangle]
+pub unsafe extern "C" fn gethostbyaddr(
+    v: *const ::c_void,
+    length: socklen_t,
+    format: ::c_int,
+) -> *mut hostent {
+    let addr: in_addr = *(v as *mut in_addr);
+
+    // check the hosts file first
+    let mut p: *mut hostent;
+    sethostent(HOST_STAYOPEN);
+    while {
+        p = gethostent();
+        !p.is_null()
+    } {
+        let mut cp = (*p).h_addr_list;
+        loop {
+            if cp.is_null() {
+                break;
+            }
+            if (*cp).is_null() {
+                break;
+            }
+            let mut cp_slice: [i8; 4] = [0i8; 4];
+            (*cp).copy_to(cp_slice.as_mut_ptr(), 4);
+            let cp_s_addr = mem::transmute::<[i8; 4], u32>(cp_slice);
+            if cp_s_addr == addr.s_addr {
+                sethostent(HOST_STAYOPEN);
+                return p;
+            }
+            cp = cp.offset(1);
+        }
+    }
+
+    //TODO actually get aliases
+    let mut _host_aliases: Vec<Vec<u8>> = Vec::new();
+    _host_aliases.push(vec![b'\0']);
+    let mut host_aliases: Vec<*mut i8> = Vec::new();
+    host_aliases.push(ptr::null_mut());
+    HOST_ALIASES = Some(_host_aliases);
+
+    match lookup_addr(addr) {
+        Ok(s) => {
+            _HOST_ADDR_LIST = mem::transmute::<u32, [u8; 4]>(addr.s_addr);
+            HOST_ADDR_LIST = [_HOST_ADDR_LIST.as_mut_ptr() as *mut ::c_char, ptr::null_mut()];
+            let host_name = s[0].to_vec();
+            HOST_NAME = Some(host_name);
+            HOST_ENTRY = hostent {
+                h_name: HOST_NAME.as_mut().unwrap().as_mut_ptr() as *mut ::c_char,
+                h_aliases: host_aliases.as_mut_slice().as_mut_ptr() as *mut *mut i8,
+                h_addrtype: format,
+                h_length: length as i32,
+                h_addr_list: HOST_ADDR_LIST.as_mut_ptr(),
+            };
+            &mut HOST_ENTRY
+        }
+        Err(e) => {
+            platform::errno = e;
+            ptr::null_mut()
+        }
+    }
+}
+
+#[no_mangle]
+pub unsafe extern "C" fn gethostbyname(name: *const ::c_char) -> *mut hostent {
+    // check if some idiot gave us an address instead of a name
+    let name_cstr = CStr::from_ptr(name);
+    let mut octets = str::from_utf8_unchecked(name_cstr.to_bytes()).split('.');
+    let mut s_addr = [0u8; 4];
+    let mut is_addr = true;
+    for item in &mut s_addr {
+        if let Some(n) = octets.next().and_then(|x| u8::from_str(x).ok()) {
+            *item = n;
+        } else {
+            is_addr = false;
+        }
+    }
+    if octets.next() != None {
+        is_addr = false;
+    }
+
+    if is_addr {
+        let addr = in_addr {
+            s_addr: mem::transmute::<[u8; 4], u32>(s_addr),
+        };
+        return gethostbyaddr(&addr as *const _ as *const ::c_void, 4, AF_INET);
+    }
+
+    // check the hosts file first
+    let mut p: *mut hostent;
+    sethostent(HOST_STAYOPEN);
+    while {
+        p = gethostent();
+        !p.is_null()
+    } {
+        if strcasecmp((*p).h_name, name) == 0 {
+            sethostent(HOST_STAYOPEN);
+            return p;
+        }
+        let mut cp = (*p).h_aliases;
+        loop {
+            if cp.is_null() {
+                break;
+            }
+            if (*cp).is_null() {
+                break;
+            }
+            if strcasecmp(*cp, name) == 0 {
+                sethostent(HOST_STAYOPEN);
+                return p;
+            }
+            cp = cp.offset(1);
+        }
+    }
+
+    let name_cstr = CStr::from_ptr(name);
+
+    let mut host = match lookup_host(str::from_utf8_unchecked(name_cstr.to_bytes())) {
+        Ok(lookuphost) => lookuphost,
+        Err(e) => {
+            platform::errno = e;
+            return ptr::null_mut();
+        }
+    };
+    let host_addr = match host.next() {
+        Some(result) => result,
+        None => {
+            platform::errno = ENOENT;
+            return ptr::null_mut();
+        }
+    };
+
+    let host_name: Vec<u8> = name_cstr.to_bytes().to_vec();
+    HOST_NAME = Some(host_name);
+    _HOST_ADDR_LIST = mem::transmute::<u32, [u8; 4]>(host_addr.s_addr);
+    HOST_ADDR_LIST = [_HOST_ADDR_LIST.as_mut_ptr() as *mut ::c_char, ptr::null_mut()];
+    HOST_ADDR = Some(host_addr);
+
+    //TODO actually get aliases
+    let mut _host_aliases: Vec<Vec<u8>> = Vec::new();
+    _host_aliases.push(vec![b'\0']);
+    let mut host_aliases: Vec<*mut i8> = Vec::new();
+    host_aliases.push(ptr::null_mut());
+    host_aliases.push(ptr::null_mut());
+    HOST_ALIASES = Some(_host_aliases);
+
+    HOST_ENTRY = hostent {
+        h_name: HOST_NAME.as_mut().unwrap().as_mut_ptr() as *mut ::c_char,
+        h_aliases: host_aliases.as_mut_slice().as_mut_ptr() as *mut *mut i8,
+        h_addrtype: AF_INET,
+        h_length: 4,
+        h_addr_list: HOST_ADDR_LIST.as_mut_ptr(),
+    };
+    sethostent(HOST_STAYOPEN);
+    &mut HOST_ENTRY as *mut hostent
+}
+
+pub unsafe extern "C" fn getnetbyaddr(net: u32, net_type: ::c_int) -> *mut netent {
+    unimplemented!();
+}
+
+#[no_mangle]
+pub unsafe extern "C" fn getnetbyname(name: *const ::c_char) -> *mut netent {
+    let mut n: *mut netent;
+    setnetent(NET_STAYOPEN);
+    while {
+        n = getnetent();
+        !n.is_null()
+    } {
+        if strcasecmp((*n).n_name, name) == 0 {
+            setnetent(NET_STAYOPEN);
+            return n;
+        }
+    }
+    setnetent(NET_STAYOPEN);
+
+    platform::errno = ENOENT;
+    ptr::null_mut() as *mut netent
+}
+
+#[no_mangle]
+pub unsafe extern "C" fn getnetent() -> *mut netent {
+    if NETDB == 0 {
+        NETDB = platform::pal::open("/etc/networks".as_ptr() as *const i8, O_RDONLY, 0);
+    }
+
+    let mut rlb = RawLineBuffer::new(NETDB);
+    rlb.seek(N_POS);
+
+    let mut r: Box<str> = Box::default();
+    while r.is_empty() || r.split_whitespace().next() == None || r.starts_with('#') {
+        r = match rlb.next() {
+            Line::Some(s) => bytes_to_box_str(s),
+            _ => {
+                if NET_STAYOPEN == 0 {
+                    endnetent();
+                }
+                return ptr::null_mut();
+            }
+        };
+    }
+    rlb.next();
+    N_POS = rlb.line_pos();
+
+    let mut iter: SplitWhitespace = r.split_whitespace();
+
+    let mut net_name = iter.next().unwrap().as_bytes().to_vec();
+    net_name.push(b'\0');
+    NET_NAME = Some(net_name);
+
+    let mut addr_vec = iter.next().unwrap().as_bytes().to_vec();
+    addr_vec.push(b'\0');
+    let addr_cstr = addr_vec.as_slice().as_ptr() as *const i8;
+    let mut addr = mem::MaybeUninit::uninit();
+    inet_aton(addr_cstr, addr.as_mut_ptr());
+    let addr = addr.assume_init();
+    NET_ADDR = Some(ntohl(addr.s_addr));
+
+    let mut _net_aliases: Vec<Vec<u8>> = Vec::new();
+    for s in iter {
+        let mut alias = s.as_bytes().to_vec();
+        alias.push(b'\0');
+        _net_aliases.push(alias);
+    }
+    let mut net_aliases: Vec<*mut i8> = _net_aliases
+        .iter_mut()
+        .map(|x| x.as_mut_ptr() as *mut i8)
+        .collect();
+    net_aliases.push(ptr::null_mut());
+    NET_ALIASES = Some(_net_aliases);
+
+    NET_ENTRY = netent {
+        n_name: NET_NAME.as_mut().unwrap().as_mut_ptr() as *mut ::c_char,
+        n_aliases: net_aliases.as_mut_slice().as_mut_ptr() as *mut *mut i8,
+        n_addrtype: AF_INET,
+        n_net: NET_ADDR.unwrap() as ::c_ulong,
+    };
+    &mut NET_ENTRY as *mut netent
+}
+
+#[no_mangle]
+pub unsafe extern "C" fn getprotobyname(name: *const ::c_char) -> *mut protoent {
+    let mut p: *mut protoent;
+    setprotoent(PROTO_STAYOPEN);
+    while {
+        p = getprotoent();
+        !p.is_null()
+    } {
+        if strcasecmp((*p).p_name, name) == 0 {
+            setprotoent(PROTO_STAYOPEN);
+            return p;
+        }
+
+        let mut cp = (*p).p_aliases;
+        loop {
+            if cp.is_null() {
+                setprotoent(PROTO_STAYOPEN);
+                break;
+            }
+            if (*cp).is_null() {
+                setprotoent(PROTO_STAYOPEN);
+                break;
+            }
+            if strcasecmp(*cp, name) == 0 {
+                setprotoent(PROTO_STAYOPEN);
+                return p;
+            }
+            cp = cp.offset(1);
+        }
+    }
+    setprotoent(PROTO_STAYOPEN);
+
+    platform::errno = ENOENT;
+    ptr::null_mut() as *mut protoent
+}
+
+#[no_mangle]
+pub unsafe extern "C" fn getprotobynumber(number: ::c_int) -> *mut protoent {
+    setprotoent(PROTO_STAYOPEN);
+    let mut p: *mut protoent;
+    while {
+        p = getprotoent();
+        !p.is_null()
+    } {
+        if (*p).p_proto == number {
+            setprotoent(PROTO_STAYOPEN);
+            return p;
+        }
+    }
+    setprotoent(PROTO_STAYOPEN);
+    platform::errno = ENOENT;
+    ptr::null_mut() as *mut protoent
+}
+
+#[no_mangle]
+pub unsafe extern "C" fn getprotoent() -> *mut protoent {
+    if PROTODB == 0 {
+        PROTODB = platform::pal::open("/etc/protocols".as_ptr() as *const i8, O_RDONLY, 0);
+    }
+
+    let mut rlb = RawLineBuffer::new(PROTODB);
+    rlb.seek(P_POS);
+
+    let mut r: Box<str> = Box::default();
+    while r.is_empty() || r.split_whitespace().next() == None || r.starts_with('#') {
+        r = match rlb.next() {
+            Line::Some(s) => bytes_to_box_str(s),
+            _ => {
+                if PROTO_STAYOPEN == 0 {
+                    endprotoent();
+                }
+                return ptr::null_mut();
+            }
+        };
+    }
+    rlb.next();
+    P_POS = rlb.line_pos();
+
+    let mut iter: SplitWhitespace = r.split_whitespace();
+
+    let mut proto_name: Vec<u8> = iter.next().unwrap().as_bytes().to_vec();
+    proto_name.push(b'\0');
+
+    let mut num = iter.next().unwrap().as_bytes().to_vec();
+    num.push(b'\0');
+    PROTO_NUM = Some(atoi(num.as_mut_slice().as_mut_ptr() as *mut i8));
+
+    let mut _proto_aliases: Vec<Vec<u8>> = Vec::new();
+    for s in iter {
+        let mut alias = s.as_bytes().to_vec();
+        alias.push(b'\0');
+        _proto_aliases.push(alias);
+    }
+    let mut proto_aliases: Vec<*mut i8> = _proto_aliases
+        .iter_mut()
+        .map(|x| x.as_mut_ptr() as *mut i8)
+        .collect();
+    proto_aliases.push(ptr::null_mut());
+
+    PROTO_ALIASES = Some(_proto_aliases);
+    PROTO_NAME = Some(proto_name);
+
+    PROTO_ENTRY = protoent {
+        p_name: PROTO_NAME.as_mut().unwrap().as_mut_slice().as_mut_ptr() as *mut ::c_char,
+        p_aliases: proto_aliases.as_mut_slice().as_mut_ptr() as *mut *mut i8,
+        p_proto: PROTO_NUM.unwrap(),
+    };
+    if PROTO_STAYOPEN == 0 {
+        endprotoent();
+    }
+    &mut PROTO_ENTRY as *mut protoent
+}
+
+#[no_mangle]
+pub unsafe extern "C" fn getservbyname(name: *const ::c_char, proto: *const ::c_char) -> *mut servent {
+    setservent(SERV_STAYOPEN);
+    let mut p: *mut servent;
+    if proto.is_null() {
+        while {
+            p = getservent();
+            !p.is_null()
+        } {
+            if strcasecmp((*p).s_name, name) == 0 {
+                setservent(SERV_STAYOPEN);
+                return p;
+            }
+        }
+    } else {
+        while {
+            p = getservent();
+            !p.is_null()
+        } {
+            if strcasecmp((*p).s_name, name) == 0 && strcasecmp((*p).s_proto, proto) == 0 {
+                setservent(SERV_STAYOPEN);
+                return p;
+            }
+        }
+    }
+    setservent(SERV_STAYOPEN);
+    platform::errno = ENOENT;
+    ptr::null_mut() as *mut servent
+}
+
+#[no_mangle]
+pub unsafe extern "C" fn getservbyport(port: ::c_int, proto: *const ::c_char) -> *mut servent {
+    setservent(SERV_STAYOPEN);
+    let mut p: *mut servent;
+    if proto.is_null() {
+        while {
+            p = getservent();
+            !p.is_null()
+        } {
+            if (*p).s_port == port {
+                setservent(SERV_STAYOPEN);
+                return p;
+            }
+        }
+    } else {
+        while {
+            p = getservent();
+            !p.is_null()
+        } {
+            if (*p).s_port == port && strcasecmp((*p).s_proto, proto) == 0 {
+                setservent(SERV_STAYOPEN);
+                return p;
+            }
+        }
+    }
+    setservent(SERV_STAYOPEN);
+    platform::errno = ENOENT;
+    ptr::null_mut()
+}
+
+#[no_mangle]
+pub unsafe extern "C" fn getservent() -> *mut servent {
+    if SERVDB == 0 {
+        SERVDB = platform::pal::open("/etc/services".as_ptr() as *const i8, O_RDONLY, 0);
+    }
+    let mut rlb = RawLineBuffer::new(SERVDB);
+    rlb.seek(S_POS);
+
+    let r: Box<str> = Box::default();
+
+    loop {
+        let r = match rlb.next() {
+            Line::Some(s) => bytes_to_box_str(s),
+            _ => {
+                if SERV_STAYOPEN == 0 {
+                    endservent();
+                }
+                return ptr::null_mut();
+            }
+        };
+
+        let mut iter = r.split_whitespace();
+        let mut serv_name = match iter.next() {
+            Some(serv_name) => serv_name.as_bytes().to_vec(),
+            None => continue,
+        };
+        serv_name.push(b'\0');
+        let port_proto = match iter.next() {
+            Some(port_proto) => port_proto,
+            None => continue,
+        };
+        let mut split = port_proto.split('/');
+        let mut port = match split.next() {
+            Some(port) => port.as_bytes().to_vec(),
+            None => continue,
+        };
+        port.push(b'\0');
+        SERV_PORT =
+            Some(htons(atoi(port.as_mut_slice().as_mut_ptr() as *mut i8) as u16) as u32 as i32);
+        let mut proto = match split.next() {
+            Some(proto) => proto.as_bytes().to_vec(),
+            None => continue,
+        };
+        proto.push(b'\0');
+
+        rlb.next();
+        S_POS = rlb.line_pos();
+
+        /*
+         *let mut _serv_aliases: Vec<Vec<u8>> = Vec::new();
+         *loop {
+         *    let mut alias = match iter.next() {
+         *        Some(s) => s.as_bytes().to_vec(),
+         *        _ => break
+         *    };
+         *    alias.push(b'\0');
+         *    _serv_aliases.push(alias);
+         *}
+         *let mut serv_aliases: Vec<*mut i8> = _serv_aliases.iter_mut().map(|x| x.as_mut_ptr() as *mut i8).collect();
+         *serv_aliases.push(ptr::null_mut());
+         *
+         */
+        let mut _serv_aliases: Vec<Vec<u8>> = Vec::new();
+        _serv_aliases.push(vec![b'\0']);
+        let mut serv_aliases: Vec<*mut i8> = Vec::new();
+        serv_aliases.push(ptr::null_mut());
+        serv_aliases.push(ptr::null_mut());
+
+        SERV_ALIASES = Some(_serv_aliases);
+        SERV_NAME = Some(serv_name);
+        SERV_PROTO = Some(proto);
+
+        SERV_ENTRY = servent {
+            s_name: SERV_NAME.as_mut().unwrap().as_mut_slice().as_mut_ptr() as *mut ::c_char,
+            s_aliases: serv_aliases.as_mut_slice().as_mut_ptr() as *mut *mut i8,
+            s_port: SERV_PORT.unwrap(),
+            s_proto: SERV_PROTO.as_mut().unwrap().as_mut_slice().as_mut_ptr() as *mut ::c_char,
+        };
+
+        if SERV_STAYOPEN == 0 {
+            endservent();
+        }
+        break &mut SERV_ENTRY as *mut servent;
+    }
+}
+
+#[no_mangle]
+pub unsafe extern "C" fn setnetent(stayopen: ::c_int) {
+    NET_STAYOPEN = stayopen;
+    if NETDB == 0 {
+        NETDB = platform::pal::open("/etc/networks".as_ptr() as *const i8, O_RDONLY, 0)
+    } else {
+        platform::pal::lseek(NETDB, 0, SEEK_SET);
+        N_POS = 0;
+    }
+}
+
+#[no_mangle]
+pub unsafe extern "C" fn setprotoent(stayopen: ::c_int) {
+    PROTO_STAYOPEN = stayopen;
+    if PROTODB == 0 {
+        PROTODB = platform::pal::open("/etc/protocols".as_ptr() as *const i8, O_RDONLY, 0)
+    } else {
+        platform::pal::lseek(PROTODB, 0, SEEK_SET);
+        P_POS = 0;
+    }
+}
+
+#[no_mangle]
+pub unsafe extern "C" fn setservent(stayopen: ::c_int) {
+    SERV_STAYOPEN = stayopen;
+    if SERVDB == 0 {
+        SERVDB = platform::pal::open("/etc/services".as_ptr() as *const i8, O_RDONLY, 0)
+    } else {
+        platform::pal::lseek(SERVDB, 0, SEEK_SET);
+        S_POS = 0;
+    }
+}
+
+#[no_mangle]
+pub unsafe extern "C" fn getaddrinfo(
+    node: *const ::c_char,
+    service: *const ::c_char,
+    hints: *const addrinfo,
+    res: *mut *mut addrinfo,
+) -> ::c_int {
+    //TODO: getaddrinfo
+    let node_opt = if node.is_null() {
+        None
+    } else {
+        Some(CStr::from_ptr(node))
+    };
+
+    let service_opt = if service.is_null() {
+        None
+    } else {
+        Some(CStr::from_ptr(service))
+    };
+
+    let hints_opt = if hints.is_null() { None } else { Some(&*hints) };
+
+    trace!(
+        "getaddrinfo({:?}, {:?}, {:?})",
+        node_opt.map(|c| str::from_utf8_unchecked(c.to_bytes())),
+        service_opt.map(|c| str::from_utf8_unchecked(c.to_bytes())),
+        hints_opt
+    );
+
+    //TODO: Use hints
+    let mut ai_flags = hints_opt.map_or(0, |hints| hints.ai_flags);
+    let mut ai_family; // = hints_opt.map_or(AF_UNSPEC, |hints| hints.ai_family);
+    let ai_socktype = hints_opt.map_or(0, |hints| hints.ai_socktype);
+    let mut ai_protocol; // = hints_opt.map_or(0, |hints| hints.ai_protocol);
+
+    *res = ptr::null_mut();
+
+    let mut port = 0;
+    if let Some(service) = service_opt {
+        //TODO: Support other service definitions as well as AI_NUMERICSERV
+        match str::from_utf8_unchecked(service.to_bytes()).parse::<u16>() {
+            Ok(ok) => port = ok,
+            Err(_err) => (),
+        }
+    }
+
+    //TODO: Check hosts file
+    if let Some(node) = node_opt {
+        //TODO: Support AI_NUMERICHOST
+        let lookuphost = match lookup_host(str::from_utf8_unchecked(node.to_bytes())) {
+            Ok(lookuphost) => lookuphost,
+            Err(e) => {
+                platform::errno = e;
+                return EAI_SYSTEM;
+            }
+        };
+
+        for in_addr in lookuphost {
+            ai_family = AF_INET;
+            ai_protocol = 0;
+
+            let ai_addr = Box::into_raw(Box::new(sockaddr_in {
+                sin_family: ai_family as sa_family_t,
+                sin_port: htons(port),
+                sin_addr: in_addr,
+                sin_zero: [0; 8],
+            })) as *mut sockaddr;
+
+            let ai_addrlen = mem::size_of::<sockaddr_in>();
+
+            let ai_canonname = if ai_flags & AI_CANONNAME > 0 {
+                ai_flags &= !AI_CANONNAME;
+                node.to_owned().into_raw()
+            } else {
+                ptr::null_mut()
+            };
+
+            let addrinfo = Box::new(addrinfo {
+                ai_flags: 0,
+                ai_family,
+                ai_socktype,
+                ai_protocol,
+                ai_addrlen,
+                ai_canonname,
+                ai_addr,
+                ai_next: ptr::null_mut(),
+            });
+
+            let mut indirect = res;
+            while !(*indirect).is_null() {
+                indirect = &mut (**indirect).ai_next;
+            }
+            *indirect = Box::into_raw(addrinfo);
+        }
+    }
+
+    0
+}
+
+#[no_mangle]
+pub unsafe extern "C" fn getnameinfo(
+    addr: *const sockaddr,
+    addrlen: socklen_t,
+    host: *mut ::c_char,
+    hostlen: socklen_t,
+    serv: *mut ::c_char,
+    servlen: socklen_t,
+    flags: ::c_int,
+) -> ::c_int {
+    //TODO: getnameinfo
+    if addrlen as usize != mem::size_of::<sockaddr_in>() {
+        return EAI_FAMILY;
+    }
+
+    let addr = &*(addr as *const sockaddr_in);
+
+    let host_opt = if host.is_null() {
+        None
+    } else {
+        Some(slice::from_raw_parts_mut(host, hostlen as usize))
+    };
+
+    let serv_opt = if serv.is_null() {
+        None
+    } else {
+        Some(slice::from_raw_parts_mut(serv, servlen as usize))
+    };
+
+    eprintln!("getnameinfo({:p}, {}, {:#x})", addr, addrlen, flags);
+
+    platform::errno = ENOSYS;
+    EAI_SYSTEM
+}
+
+#[no_mangle]
+pub unsafe extern "C" fn freeaddrinfo(res: *mut addrinfo) {
+    let mut ai = res;
+    while !ai.is_null() {
+        let bai = Box::from_raw(ai);
+        if !bai.ai_canonname.is_null() {
+            CString::from_raw(bai.ai_canonname);
+        }
+        if !bai.ai_addr.is_null() {
+            if bai.ai_addrlen == mem::size_of::<sockaddr_in>() {
+                Box::from_raw(bai.ai_addr as *mut sockaddr_in);
+            } else if bai.ai_addrlen == mem::size_of::<sockaddr_in6>() {
+                Box::from_raw(bai.ai_addr as *mut sockaddr_in6);
+            } else {
+                eprintln!("freeaddrinfo: unknown ai_addrlen {}", bai.ai_addrlen);
+            }
+        }
+        ai = bai.ai_next;
+    }
+}
+
+#[no_mangle]
+pub extern "C" fn gai_strerror(errcode: ::c_int) -> *const ::c_char {
+    match errcode {
+        EAI_BADFLAGS => c_str!("Invalid flags"),
+        EAI_NONAME => c_str!("Name does not resolve"),
+        EAI_AGAIN => c_str!("Try again"),
+        EAI_FAIL => c_str!("Non-recoverable error"),
+        EAI_NODATA => c_str!("Unknown error"),
+        EAI_FAMILY => c_str!("Unrecognized address family or invalid length"),
+        EAI_SOCKTYPE => c_str!("Unrecognized socket type"),
+        EAI_SERVICE => c_str!("Unrecognized service"),
+        EAI_ADDRFAMILY => c_str!("Address family for name not supported"),
+        EAI_MEMORY => c_str!("Out of memory"),
+        EAI_SYSTEM => c_str!("System error"),
+        EAI_OVERFLOW => c_str!("Overflow"),
+        _ => c_str!("Unknown error"),
+    }
+    .as_ptr()
+}
+
+#[no_mangle]
+pub extern "C" fn hstrerror(errcode: ::c_int) -> *const ::c_char {
+    match errcode {
+        HOST_NOT_FOUND => c_str!("Unknown hostname"),
+        NO_DATA => c_str!("No address for hostname"),
+        NO_RECOVERY => c_str!("Unknown server error"),
+        TRY_AGAIN => c_str!("Hostname lookup failure"),
+        _ => c_str!("Unknown error"),
+    }
+    .as_ptr()
+}

+ 9 - 0
dlibc/src/unix/header/netdb/redox.rs

@@ -0,0 +1,9 @@
+use crate::{c_str::CString, fs::File, header::fcntl, io::Read};
+use alloc::string::String;
+
+pub fn get_dns_server() -> String {
+    let mut string = String::new();
+    let mut file = File::open(&CString::new("/etc/net/dns").unwrap(), fcntl::O_RDONLY).unwrap(); // TODO: error handling
+    file.read_to_string(&mut string).unwrap(); // TODO: error handling
+    string
+}

+ 13 - 0
dlibc/src/unix/header/netinet_in/cbindgen.toml

@@ -0,0 +1,13 @@
+sys_includes = ["sys/types.h", "sys/socket.h"]
+include_guard = "_NETINET_IN_H"
+trailer = "#include <bits/netinet/in.h>"
+language = "C"
+style = "Tag"
+no_includes = true
+cpp_compat = true
+
+[export]
+include = ["sockaddr_in6", "sockaddr_in", "ipv6_mreq"]
+
+[enum]
+prefix_with_name = true

+ 74 - 0
dlibc/src/unix/header/netinet_in/mod.rs

@@ -0,0 +1,74 @@
+#![allow(non_camel_case_types)]
+
+use crate::header::sys_socket::sa_family_t;
+
+pub type in_addr_t = u32;
+pub type in_port_t = u16;
+
+#[repr(C)]
+#[derive(Debug, Clone, Copy, Default)]
+pub struct in_addr {
+    pub s_addr: in_addr_t,
+}
+
+#[repr(C)]
+pub struct in6_addr {
+    pub s6_addr: [u8; 16],
+}
+
+#[repr(C)]
+#[derive(Debug, Default)]
+pub struct sockaddr_in {
+    pub sin_family: sa_family_t,
+    pub sin_port: in_port_t,
+    pub sin_addr: in_addr,
+    pub sin_zero: [::c_char; 8],
+}
+
+#[repr(C)]
+pub struct sockaddr_in6 {
+    pub sin6_family: sa_family_t,
+    pub sin6_port: in_port_t,
+    pub sin6_flowinfo: u32,
+    pub sin6_addr: in6_addr,
+    pub sin6_scope_id: u32,
+}
+
+#[repr(C)]
+pub struct ipv6_mreq {
+    pub ipv6mr_multiaddr: in6_addr,
+    pub ipv6mr_interface: u32,
+}
+
+// Address String Lengths
+pub const INET_ADDRSTRLEN: ::c_int = 16;
+pub const INET6_ADDRSTRLEN: ::c_int = 46;
+
+// Protocol Numbers
+pub const IPPROTO_IP: u8 = 0x00;
+pub const IPPROTO_ICMP: u8 = 0x01;
+pub const IPPROTO_TCP: u8 = 0x06;
+pub const IPPROTO_UDP: u8 = 0x11;
+pub const IPPROTO_IPV6: u8 = 0x29;
+pub const IPPROTO_RAW: u8 = 0xff;
+pub const IPPROTO_MAX: u8 = 0xff;
+
+pub const INADDR_ANY: u32 = 0; // Can't use in_addr_t alias because cbindgen :(
+pub const INADDR_BROADCAST: u32 = 0xFFFF_FFFF; // Can't use core::u32::MAX because cbindgen :(
+pub const INADDR_NONE: u32 = 0xFFFF_FFFF;
+pub const INADDR_LOOPBACK: u32 = 0x7F00_0001;
+
+pub const INADDR_UNSPEC_GROUP: u32 = 0xE000_0000;
+pub const INADDR_ALLHOSTS_GROUP: u32 = 0xE000_0001;
+pub const INADDR_ALLRTRS_GROUP: u32 = 0xE000_0002;
+pub const INADDR_MAX_LOCAL_GROUP: u32 = 0xE000_00FF;
+
+#[no_mangle]
+pub static in6addr_any: in6_addr = in6_addr {
+    s6_addr: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+};
+
+#[no_mangle]
+pub static in6addr_loopback: in6_addr = in6_addr {
+    s6_addr: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
+};

Some files were not shown because too many files changed in this diff