pax_global_header00006660000000000000000000000064142642315110014511gustar00rootroot0000000000000052 comment=e47efae5cd6dfa60d386c0034db958976289ea5a purelibc-1.0.6/000077500000000000000000000000001426423151100133225ustar00rootroot00000000000000purelibc-1.0.6/CMakeLists.txt000066400000000000000000000025411426423151100160640ustar00rootroot00000000000000cmake_minimum_required(VERSION 3.13) project(purelibc VERSION 1.0.4 DESCRIPTION "A glibc overlay library for process self-virtualization." HOMEPAGE_URL "https://github.com/virtualsquare/purelibc" LANGUAGES C) include(GNUInstallDirs) include(CheckPrototypeDefinition) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -D_FORTIFY_SOURCE=2 -ggdb -Wall -Wextra -pedantic -std=gnu11 -Wno-incompatible-pointer-types -Wno-unused-parameter") find_library(LIBDL dl) add_definitions(-D_GNU_SOURCE) include_directories(${CMAKE_CURRENT_SOURCE_DIR}) set(HEADERS purelibc.h) check_prototype_definition(gettimeofday "int gettimeofday(struct timeval *tv, struct timezone *tz)" "0" "sys/time.h" GETTIMEOFDAY_TZ) check_prototype_definition(gettimeofday "int gettimeofday(struct timeval *tv, void *tz)" "0" "sys/time.h" GETTIMEOFDAY_VOID) if(${GETTIMEOFDAY_TZ}) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DGETTIMEOFDAY_TZ") endif() add_library(purelibc SHARED dir.c exec.c socketcalls.c stdio.c syscalls.c ) target_link_libraries(purelibc ${LIBDL}) set_target_properties(purelibc PROPERTIES VERSION ${PROJECT_VERSION} SOVERSION ${PROJECT_VERSION_MAJOR}) install(TARGETS purelibc LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}) install(FILES ${HEADERS} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) add_custom_target(uninstall "${CMAKE_COMMAND}" -P "${PROJECT_SOURCE_DIR}/Uninstall.cmake") purelibc-1.0.6/COPYING000066400000000000000000000635041426423151100143650ustar00rootroot00000000000000 GNU LESSER GENERAL PUBLIC LICENSE Version 2.1, February 1999 Copyright (C) 1991, 1999 Free Software Foundation, Inc. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. [This is the first released version of the Lesser GPL. It also counts as the successor of the GNU Library Public License, version 2, hence the version number 2.1.] Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public Licenses are intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This license, the Lesser General Public License, applies to some specially designated software packages--typically libraries--of the Free Software Foundation and other authors who decide to use it. You can use it too, but we suggest you first think carefully about whether this license or the ordinary General Public License is the better strategy to use in any particular case, based on the explanations below. When we speak of free software, we are referring to freedom of use, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish); that you receive source code or can get it if you want it; that you can change the software and use pieces of it in new free programs; and that you are informed that you can do these things. To protect your rights, we need to make restrictions that forbid distributors to deny you these rights or to ask you to surrender these rights. These restrictions translate to certain responsibilities for you if you distribute copies of the library or if you modify it. For example, if you distribute copies of the library, whether gratis or for a fee, you must give the recipients all the rights that we gave you. You must make sure that they, too, receive or can get the source code. If you link other code with the library, you must provide complete object files to the recipients, so that they can relink them with the library after making changes to the library and recompiling it. And you must show them these terms so they know their rights. We protect your rights with a two-step method: (1) we copyright the library, and (2) we offer you this license, which gives you legal permission to copy, distribute and/or modify the library. To protect each distributor, we want to make it very clear that there is no warranty for the free library. Also, if the library is modified by someone else and passed on, the recipients should know that what they have is not the original version, so that the original author's reputation will not be affected by problems that might be introduced by others. Finally, software patents pose a constant threat to the existence of any free program. We wish to make sure that a company cannot effectively restrict the users of a free program by obtaining a restrictive license from a patent holder. Therefore, we insist that any patent license obtained for a version of the library must be consistent with the full freedom of use specified in this license. Most GNU software, including some libraries, is covered by the ordinary GNU General Public License. This license, the GNU Lesser General Public License, applies to certain designated libraries, and is quite different from the ordinary General Public License. We use this license for certain libraries in order to permit linking those libraries into non-free programs. When a program is linked with a library, whether statically or using a shared library, the combination of the two is legally speaking a combined work, a derivative of the original library. The ordinary General Public License therefore permits such linking only if the entire combination fits its criteria of freedom. The Lesser General Public License permits more lax criteria for linking other code with the library. We call this license the "Lesser" General Public License because it does Less to protect the user's freedom than the ordinary General Public License. It also provides other free software developers Less of an advantage over competing non-free programs. These disadvantages are the reason we use the ordinary General Public License for many libraries. However, the Lesser license provides advantages in certain special circumstances. For example, on rare occasions, there may be a special need to encourage the widest possible use of a certain library, so that it becomes a de-facto standard. To achieve this, non-free programs must be allowed to use the library. A more frequent case is that a free library does the same job as widely used non-free libraries. In this case, there is little to gain by limiting the free library to free software only, so we use the Lesser General Public License. In other cases, permission to use a particular library in non-free programs enables a greater number of people to use a large body of free software. For example, permission to use the GNU C Library in non-free programs enables many more people to use the whole GNU operating system, as well as its variant, the GNU/Linux operating system. Although the Lesser General Public License is Less protective of the users' freedom, it does ensure that the user of a program that is linked with the Library has the freedom and the wherewithal to run that program using a modified version of the Library. The precise terms and conditions for copying, distribution and modification follow. Pay close attention to the difference between a "work based on the library" and a "work that uses the library". The former contains code derived from the library, whereas the latter must be combined with the library in order to run. GNU LESSER GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License Agreement applies to any software library or other program which contains a notice placed by the copyright holder or other authorized party saying it may be distributed under the terms of this Lesser General Public License (also called "this License"). Each licensee is addressed as "you". A "library" means a collection of software functions and/or data prepared so as to be conveniently linked with application programs (which use some of those functions and data) to form executables. The "Library", below, refers to any such software library or work which has been distributed under these terms. A "work based on the Library" means either the Library or any derivative work under copyright law: that is to say, a work containing the Library or a portion of it, either verbatim or with modifications and/or translated straightforwardly into another language. (Hereinafter, translation is included without limitation in the term "modification".) "Source code" for a work means the preferred form of the work for making modifications to it. For a library, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the library. Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running a program using the Library is not restricted, and output from such a program is covered only if its contents constitute a work based on the Library (independent of the use of the Library in a tool for writing it). Whether that is true depends on what the Library does and what the program that uses the Library does. 1. You may copy and distribute verbatim copies of the Library's complete source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and distribute a copy of this License along with the Library. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Library or any portion of it, thus forming a work based on the Library, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) The modified work must itself be a software library. b) You must cause the files modified to carry prominent notices stating that you changed the files and the date of any change. c) You must cause the whole of the work to be licensed at no charge to all third parties under the terms of this License. d) If a facility in the modified Library refers to a function or a table of data to be supplied by an application program that uses the facility, other than as an argument passed when the facility is invoked, then you must make a good faith effort to ensure that, in the event an application does not supply such function or table, the facility still operates, and performs whatever part of its purpose remains meaningful. (For example, a function in a library to compute square roots has a purpose that is entirely well-defined independent of the application. Therefore, Subsection 2d requires that any application-supplied function or table used by this function must be optional: if the application does not supply it, the square root function must still compute square roots.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Library, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Library, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Library. In addition, mere aggregation of another work not based on the Library with the Library (or with a work based on the Library) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may opt to apply the terms of the ordinary GNU General Public License instead of this License to a given copy of the Library. To do this, you must alter all the notices that refer to this License, so that they refer to the ordinary GNU General Public License, version 2, instead of to this License. (If a newer version than version 2 of the ordinary GNU General Public License has appeared, then you can specify that version instead if you wish.) Do not make any other change in these notices. Once this change is made in a given copy, it is irreversible for that copy, so the ordinary GNU General Public License applies to all subsequent copies and derivative works made from that copy. This option is useful when you wish to copy part of the code of the Library into a program that is not a library. 4. You may copy and distribute the Library (or a portion or derivative of it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange. If distribution of object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place satisfies the requirement to distribute the source code, even though third parties are not compelled to copy the source along with the object code. 5. A program that contains no derivative of any portion of the Library, but is designed to work with the Library by being compiled or linked with it, is called a "work that uses the Library". Such a work, in isolation, is not a derivative work of the Library, and therefore falls outside the scope of this License. However, linking a "work that uses the Library" with the Library creates an executable that is a derivative of the Library (because it contains portions of the Library), rather than a "work that uses the library". The executable is therefore covered by this License. Section 6 states terms for distribution of such executables. When a "work that uses the Library" uses material from a header file that is part of the Library, the object code for the work may be a derivative work of the Library even though the source code is not. Whether this is true is especially significant if the work can be linked without the Library, or if the work is itself a library. The threshold for this to be true is not precisely defined by law. If such an object file uses only numerical parameters, data structure layouts and accessors, and small macros and small inline functions (ten lines or less in length), then the use of the object file is unrestricted, regardless of whether it is legally a derivative work. (Executables containing this object code plus portions of the Library will still fall under Section 6.) Otherwise, if the work is a derivative of the Library, you may distribute the object code for the work under the terms of Section 6. Any executables containing that work also fall under Section 6, whether or not they are linked directly with the Library itself. 6. As an exception to the Sections above, you may also combine or link a "work that uses the Library" with the Library to produce a work containing portions of the Library, and distribute that work under terms of your choice, provided that the terms permit modification of the work for the customer's own use and reverse engineering for debugging such modifications. You must give prominent notice with each copy of the work that the Library is used in it and that the Library and its use are covered by this License. You must supply a copy of this License. If the work during execution displays copyright notices, you must include the copyright notice for the Library among them, as well as a reference directing the user to the copy of this License. Also, you must do one of these things: a) Accompany the work with the complete corresponding machine-readable source code for the Library including whatever changes were used in the work (which must be distributed under Sections 1 and 2 above); and, if the work is an executable linked with the Library, with the complete machine-readable "work that uses the Library", as object code and/or source code, so that the user can modify the Library and then relink to produce a modified executable containing the modified Library. (It is understood that the user who changes the contents of definitions files in the Library will not necessarily be able to recompile the application to use the modified definitions.) b) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (1) uses at run time a copy of the library already present on the user's computer system, rather than copying library functions into the executable, and (2) will operate properly with a modified version of the library, if the user installs one, as long as the modified version is interface-compatible with the version that the work was made with. c) Accompany the work with a written offer, valid for at least three years, to give the same user the materials specified in Subsection 6a, above, for a charge no more than the cost of performing this distribution. d) If distribution of the work is made by offering access to copy from a designated place, offer equivalent access to copy the above specified materials from the same place. e) Verify that the user has already received a copy of these materials or that you have already sent this user a copy. For an executable, the required form of the "work that uses the Library" must include any data and utility programs needed for reproducing the executable from it. However, as a special exception, the materials to be distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. It may happen that this requirement contradicts the license restrictions of other proprietary libraries that do not normally accompany the operating system. Such a contradiction means you cannot use both them and the Library together in an executable that you distribute. 7. You may place library facilities that are a work based on the Library side-by-side in a single library together with other library facilities not covered by this License, and distribute such a combined library, provided that the separate distribution of the work based on the Library and of the other library facilities is otherwise permitted, and provided that you do these two things: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities. This must be distributed under the terms of the Sections above. b) Give prominent notice with the combined library of the fact that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 8. You may not copy, modify, sublicense, link with, or distribute the Library except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense, link with, or distribute the Library is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 9. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Library or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Library (or any work based on the Library), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Library or works based on it. 10. Each time you redistribute the Library (or any work based on the Library), the recipient automatically receives a license from the original licensor to copy, distribute, link with or modify the Library subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties with this License. 11. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Library at all. For example, if a patent license would not permit royalty-free redistribution of the Library by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Library. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply, and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 12. If the distribution and/or use of the Library is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Library under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 13. The Free Software Foundation may publish revised and/or new versions of the Lesser 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 Library specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Library does not specify a license version number, you may choose any version ever published by the Free Software Foundation. 14. If you wish to incorporate parts of the Library into other free programs whose distribution conditions are incompatible with these, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY "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 LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE LIBRARY 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 LIBRARY (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 LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Libraries If you develop a new library, and you want it to be of the greatest possible use to the public, we recommend making it free software that everyone can redistribute and change. You can do so by permitting redistribution under these terms (or, alternatively, under the terms of the ordinary General Public License). To apply these terms, attach the following notices to the library. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Also add information on how to contact you by electronic and paper mail. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the library, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the library `Frob' (a library for tweaking knobs) written by James Random Hacker. , 1 April 1990 Ty Coon, President of Vice That's all there is to it! purelibc-1.0.6/README.md000066400000000000000000000132341426423151100146040ustar00rootroot00000000000000# purelibc A glibc overlay library for process self-virtualization This is PURE\_LIBC: an overlay library for glibc that allows system call capturing. (C) 2006,2008 Renzo Davoli University of Bologna (ITALY) (C) 2006 Andrea Gasparini University of Bologna (ITALY) This is LIBRE software: this work has been released under the LGPLv2,1+ license (see the file COPYING and the header note in the source files). Pure\_libc converts glibc from a libc+system interfacing library into a libc-only library. A process can trace the system call generated by itself by purelibc. Pure\_libc is not complete yet. Stdio has been implemented onto the fopencookie call. Due to current limitations of fopencookie, freopen may not work properly when reopening files different from std{in,out,err}. This function: ```C fun _pure_start(sfun pure_syscall,int flags); ``` starts the syscall tracing. All the system call of the programs are converted into calls of the `pure_syscall` function. `pure_socketcall` is meaningful only for architectures where all the berkeley socket calls get sent to the kernel using one shared system call (`__NR_socketcall`) if `pure_socketcall` is not NULL, purelibc calls it for each Berkeley socket call. If `pure_socketcall` is NULL and `__NR_socketcall` is defined purelibc calls ```C pure_syscall(__NR_socketcall,socketcall_id,argv) ``` (purelibc mimics the same call received by the kernel). ### FLAGS * `PUREFLAG_STDIN, PUREFLAG_STDOUT, PUREFLAG_STDERR`: The standard streams gets opened by libc before purelibc starts. Without these flags stdio calls on standard streams will not be traced. (e.g. getchar, printf). These flags force _pure_start to reopen the stdio standard streams to trace the calls on them. `PUREFLAG_STDALL` is a shortcut for `(PUREFLAG_STDIN|PUREFLAG_STDOUT|PUREFLAG_STDERR)` ### RETURN VALUE _pure_start returns a pointer to the original libc syscall function. this function must be stored in a global variable and must be used to bypass purelibc and send a system call to the kernel. WARNING: libc '`syscall(2)`' call itself gets diverted to the `pure_syscall` function, too. ## Installation purelibc uses the cmake, so the standard procedure to compile and install the library is: ```sh $ mkdir build $ cd build $ cmake .. $ make $ sudo make install ``` ## Uninstallation From the build directory run: ```sh $ sudo make uninstall ``` ## Examples The following test program prints the number of each system call before actually calling it (it is a 'cat' like stdin to stdout copy, when EOF is sent it prints "hello world"): ```C #define _GNU_SOURCE #include #include #include #include #include #include #include static sfun _native_syscall; static char buf[128]; static long int mysc(long int sysno, ...){ va_list ap; long int a1,a2,a3,a4,a5,a6; va_start (ap, sysno); snprintf(buf,128,"SC=%d\n",sysno); _native_syscall(__NR_write,2,buf,strlen(buf)); a1=va_arg(ap,long int); a2=va_arg(ap,long int); a3=va_arg(ap,long int); a4=va_arg(ap,long int); a5=va_arg(ap,long int); a6=va_arg(ap,long int); va_end(ap); return _native_syscall(sysno,a1,a2,a3,a4,a5,a6); } int main() { int c; _native_syscall=_pure_start(mysc,PUREFLAG_STDALL); while ((c=getchar()) != EOF) putchar(c); printf("hello world\n"); return 0; } ``` To run this example just compile it and link it together with the library in this way: ``` $ gcc -o puretest puretest.c -lpurelibc ``` if you installed purelibc library in /usr/local/lib you need to add this directory to the linker search path, with CSH: ``` $ setenv LD_LIBRARY_PATH /usr/local/lib ``` or with BASH: ``` $ export LD_LIBRARY_PATH="/usr/local/lib" ``` Unfortunately if you load purelibc as a dynamic library by dlopen it does not work. The following example solves the problem. More specifically: * It is possible to use purelibc to track the calling process and all the dynamic libraries loaded at run time. * The code does not depend on purelibc. If you run it un a host without purelibc, it will not be able to track its system calls but it works. ```C #define _GNU_SOURCE #include #include #include #include #include #include #include #include static sfun _native_syscall; static char buf[128]; static long int mysc(long int sysno, ...){ va_list ap; long int a1,a2,a3,a4,a5,a6; va_start (ap, sysno); snprintf(buf,128,"SC=%d\n",sysno); _native_syscall(__NR_write,2,buf,strlen(buf)); a1=va_arg(ap,long int); a2=va_arg(ap,long int); a3=va_arg(ap,long int); a4=va_arg(ap,long int); a5=va_arg(ap,long int); a6=va_arg(ap,long int); va_end(ap); return _native_syscall(sysno,a1,a2,a3,a4,a5,a6); } int main(int argc,char *argv[]) { int c; sfun (*_pure_start_p)(); void *handle; /* does pure_libc exist ? */ if ((_pure_start_p=dlsym(RTLD_DEFAULT,"_pure_start")) == NULL && (handle=dlopen("libpurelibc.so",RTLD_LAZY))!=NULL) { char *path; dlclose(handle); /* get the executable from /proc */ asprintf(&path,"/proc/%d/exe",getpid()); /* preload the pure_libc library */ setenv("LD_PRELOAD","libpurelibc.so",1); printf("pure_libc dynamically loaded, exec again\n"); /* reload the executable */ execv(path,argv); /* useless cleanup */ free(path); } if ((_pure_start_p=dlsym(RTLD_DEFAULT,"_pure_start")) != NULL) { printf("pure_libc library found: syscall tracing allowed\n"); _native_syscall=_pure_start_p(mysc,NULL,PUREFLAG_STDALL); } while ((c=getchar()) != EOF) putchar(c); printf("hello world\n"); return 0; } ``` To run this example just compile it and link it with the dl library in this way: ``` $ gcc -o puretest2 puretest2.c -ldl ``` purelibc-1.0.6/TODO000066400000000000000000000003171426423151100140130ustar00rootroot00000000000000purelibc is not complete. ... a lot of secondary calls are still missing. those tightly linked to the syscall routines in glibs must be reimplemented, all the others have been already diverted to purelibc. purelibc-1.0.6/Uninstall.cmake000066400000000000000000000010361426423151100162750ustar00rootroot00000000000000cmake_minimum_required(VERSION 3.13) set(MANIFEST "${CMAKE_CURRENT_BINARY_DIR}/install_manifest.txt") if(NOT EXISTS ${MANIFEST}) message(FATAL_ERROR "Cannot find install manifest: '${MANIFEST}'") endif() file(STRINGS ${MANIFEST} files) foreach(file ${files}) if(EXISTS ${file} OR IS_SYMLINK ${file}) message(STATUS "Removing: ${file}") execute_process( COMMAND rm -f ${file} RESULT_VARIABLE retcode ) if(NOT "${retcode}" STREQUAL "0") message(WARNING "Failed to remove: ${file}") endif() endif() endforeach(file) purelibc-1.0.6/config.h000066400000000000000000000000001426423151100147260ustar00rootroot00000000000000purelibc-1.0.6/dir.c000066400000000000000000000131401426423151100142430ustar00rootroot00000000000000/* This is part of pure_libc (a project related to ViewOS and Virtual Square) * * dir.c: Directory management * * Copyright 2006-2017 Renzo Davoli University of Bologna - Italy * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * The GNU C Library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with the GNU C Library; if not, write to the Free * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * 02110-1301, USA. */ #include #include #include #include #include #include #include #include #include #define PURE_DIRSTREAM_SIZE 2048 #define PURE_DIRBUF_SIZE (PURE_DIRSTREAM_SIZE - 3*sizeof(int)) struct __dirstream { int fd; int bufsize; int bufpos; char buf[PURE_DIRBUF_SIZE]; struct dirent de32; }; DIR *fdopendir(int fd) { DIR *newdir = (DIR *) malloc (sizeof (struct __dirstream)); if (!newdir) return NULL; else { newdir->fd=fd; newdir->bufsize=newdir->bufpos=0; } return newdir; } DIR *opendirat(int dirfd, const char *name) { int fd; DIR *newdir=NULL; if (dirfd == AT_FDCWD) fd = open(name, O_RDONLY | O_DIRECTORY); else fd = openat(dirfd, name, O_RDONLY | O_DIRECTORY); if (fd >= 0) { if (fcntl (fd, F_SETFD, FD_CLOEXEC) < 0) close(fd); else { newdir = fdopendir(fd); if (!newdir) { close(fd); return NULL; } } } return newdir; } DIR *opendir(const char *name) { return opendirat(AT_FDCWD, name); } int closedir(DIR *dir){ int fd=dir->fd; free(dir); return close(fd); } #define _MAX_OFF_T ((__off_t) -1) struct dirent *readdir(DIR *dir){ register struct dirent64 *de64=readdir64(dir); if(de64 == NULL) return NULL; else { dir->de32.d_ino=de64->d_ino; dir->de32.d_off=(de64->d_off > _MAX_OFF_T)?_MAX_OFF_T:de64->d_off; dir->de32.d_reclen=de64->d_reclen; dir->de32.d_type=de64->d_type; strcpy(dir->de32.d_name,de64->d_name); return &(dir->de32); } } ssize_t getdents64(int fd, void *buffer, size_t length); struct dirent64 *readdir64(DIR *dir){ register struct dirent64 *this; this=((struct dirent64 *) (dir->buf + dir->bufpos)); if (dir->bufsize == 0 || (dir->bufpos += this->d_reclen) >= dir->bufsize) { dir->bufsize = getdents64(dir->fd,(struct dirent64 *)dir->buf,PURE_DIRBUF_SIZE-1); if (dir->bufsize <= 0) return NULL; else dir->bufpos=0; } this=((struct dirent64 *) (dir->buf + dir->bufpos)); return this; } int dirfd(DIR *dir){ return dir->fd; } void rewinddir(DIR *dir){ lseek(dir->fd,0,SEEK_SET); dir->bufsize=dir->bufpos=0; } void seekdir(DIR *dir, long int offset){ lseek(dir->fd,offset,SEEK_SET); dir->bufsize=dir->bufpos=0; } long int telldir(DIR *dir){ off_t pos = lseek(dir->fd,0,SEEK_CUR); if (pos != (off_t) -1) return -1; else return pos + dir->bufpos; } #define NL_SIZE_INCR 100 typedef int(*filter_t)(const void *); typedef int(*compar_t)(const void *, const void *); typedef void *(*xreaddir_t)(DIR *dirp); static int common_scandir(int dirfd, const char *dir, void ***namelist, filter_t filter, compar_t compar, xreaddir_t xreaddir, size_t elsize){ int n = 0; int size = 0; DIR *d = opendirat(dirfd, dir); void *de; if (d == NULL) return -1; *namelist = NULL; while ((errno = 0, de = xreaddir(d)) != NULL) { if (filter && filter(de) == 0) continue; if (n >= size) { int newsize = size + NL_SIZE_INCR; void **newnamelist = realloc(*namelist, newsize * sizeof(void **)); if (newnamelist == NULL) goto error; size = newsize; *namelist = newnamelist; } void *newel = malloc(elsize); if (newel == NULL) goto error; (*namelist)[n] = newel; memcpy(newel, de, elsize); n++; } *namelist = realloc(*namelist, n * sizeof(void **)); if (n > 0) qsort(*namelist, n, sizeof(void *), compar); return n; error: if (*namelist) { int i; for (i = 0; i < n; i++) free((*namelist)[i]); free(namelist); } return -1; } int scandir(const char *dirp, struct dirent ***namelist, int (*filter)(const struct dirent *), int (*compar)(const struct dirent **, const struct dirent **)) { return common_scandir(AT_FDCWD, dirp, (void *) namelist, (filter_t) filter, (compar_t) compar, (xreaddir_t) readdir, sizeof(struct dirent)); } int scandir64(const char *dirp, struct dirent64 ***namelist, int (*filter)(const struct dirent64 *), int (*compar)(const struct dirent64 **, const struct dirent64 **)) { return common_scandir(AT_FDCWD, dirp, (void *) namelist, (filter_t) filter, (compar_t) compar, (xreaddir_t) readdir, sizeof(struct dirent64)); } int scandirat(int dirfd, const char *dirp, struct dirent ***namelist, int (*filter)(const struct dirent *), int (*compar)(const struct dirent **, const struct dirent **)) { return common_scandir(dirfd, dirp, (void *) namelist, (filter_t) filter, (compar_t) compar, (xreaddir_t) readdir, sizeof(struct dirent)); } int scandirat64(int dirfd, const char *dirp, struct dirent64 ***namelist, int (*filter)(const struct dirent64 *), int (*compar)(const struct dirent64 **, const struct dirent64 **)) { return common_scandir(dirfd, dirp, (void *) namelist, (filter_t) filter, (compar_t) compar, (xreaddir_t) readdir, sizeof(struct dirent64)); } purelibc-1.0.6/exec.c000066400000000000000000000060131426423151100144120ustar00rootroot00000000000000/* This is part of pure_libc (a project related to ViewOS and Virtual Square) * * exec.c: exec to execve conversion * * Copyright 2006-2017 Renzo Davoli University of Bologna - Italy * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * The GNU C Library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with the GNU C Library; if not, write to the Free * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * 02110-1301, USA. */ #include #include #include #include #include #include #include #include #include #define _PURE_DEFAULT_PATH "/bin:/usr/bin" int execl(const char *path, const char *arg, ...){ va_list ap; int argc=2,i; va_start(ap,arg); while(va_arg(ap,char *) != 0) argc++; va_end(ap); char *argv[argc]; argv[0]=(char *)arg; va_start(ap,arg); for (i=1;i #include #define __KERNEL_NCCS 19 struct __kernel_termios { tcflag_t c_iflag; /* input mode flags */ tcflag_t c_oflag; /* output mode flags */ tcflag_t c_cflag; /* control mode flags */ tcflag_t c_lflag; /* local mode flags */ cc_t c_cc[__KERNEL_NCCS]; /* control characters */ cc_t c_line; /* line discipline */ speed_t c_ispeed; /* input speed */ speed_t c_ospeed; /* output speed */ }; #define _HAVE_C_ISPEED 1 #define _HAVE_C_OSPEED 1 /* We have the kernel termios structure, so we can presume this code knows what it's doing... */ #undef TCGETS #undef TCSETS #undef TCSETSW #undef TCSETSF #define TCGETS _IOR ('t', 19, struct __kernel_termios) #define TCSETS _IOW ('t', 20, struct __kernel_termios) #define TCSETSW _IOW ('t', 21, struct __kernel_termios) #define TCSETSF _IOW ('t', 22, struct __kernel_termios) #endif /* kernel_termios.h */ purelibc-1.0.6/purelibc.h000066400000000000000000000006171426423151100153040ustar00rootroot00000000000000#ifndef _PURELIBC_H #define _PURELIBC_H typedef long int (*sfun)(long int __sysno, ...); #define PUREFLAG_STDIN (1< #include #include #include #include #include #include #include "purelibc.h" extern sfun _pure_syscall; int socket(int domain, int type, int protocol){ return _pure_syscall(__NR_socket,domain,type,protocol); } int bind(int sockfd, __CONST_SOCKADDR_ARG my_addr, socklen_t addrlen){ return _pure_syscall(__NR_bind,sockfd,my_addr,addrlen); } int connect(int sockfd, __CONST_SOCKADDR_ARG serv_addr, socklen_t addrlen){ return _pure_syscall(__NR_connect,sockfd,serv_addr,addrlen); } int listen(int sockfd, int backlog){ return _pure_syscall(__NR_listen,sockfd,backlog); } int accept(int sockfd, __SOCKADDR_ARG addr, socklen_t *addrlen){ return _pure_syscall(__NR_accept4,sockfd,addr,addrlen,0); } int accept4(int sockfd, __SOCKADDR_ARG addr, socklen_t *addrlen,int flags){ return _pure_syscall(__NR_accept4,sockfd,addr,addrlen,flags); } int getsockname(int s, __SOCKADDR_ARG name, socklen_t *namelen){ return _pure_syscall(__NR_getsockname,s,name,namelen); } int getpeername(int s, __SOCKADDR_ARG name, socklen_t *namelen){ return _pure_syscall(__NR_getpeername,s,name,namelen); } int socketpair(int d, int type, int protocol, int sv[2]){ return _pure_syscall(__NR_socketpair,d,type,protocol,sv); } ssize_t send(int s, const void *buf, size_t len, int flags){ return sendto(s,buf,len,flags,NULL,0); } ssize_t recv(int s, void *buf, size_t len, int flags){ return recvfrom(s,buf,len,flags,NULL,0); } ssize_t sendto(int s, const void *buf, size_t len, int flags, __CONST_SOCKADDR_ARG to, socklen_t tolen){ return _pure_syscall(__NR_sendto,s,buf,len,flags,to,tolen); } ssize_t recvfrom(int s, void *buf, size_t len, int flags, __SOCKADDR_ARG from, socklen_t *fromlen){ return _pure_syscall(__NR_recvfrom,s,buf,len,flags,from,fromlen); } int shutdown(int s, int how){ return _pure_syscall(__NR_shutdown,s,how); } int setsockopt(int s, int level, int optname, const void *optval, socklen_t optlen){ return _pure_syscall(__NR_setsockopt,s,level,optname,optval,optlen); } int getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen){ return _pure_syscall(__NR_getsockopt,s,level,optname,optval,optlen); } ssize_t sendmsg(int s, const struct msghdr *msg, int flags){ return _pure_syscall(__NR_sendmsg,s,msg,flags); } ssize_t recvmsg(int s, struct msghdr *msg, int flags){ return _pure_syscall(__NR_recvmsg,s,msg,flags); } purelibc-1.0.6/stdio.c000066400000000000000000000162131426423151100146130ustar00rootroot00000000000000/* This is part of pure_libc (a project related to ViewOS and Virtual Square) * * stdio.c: stdio calls * * Copyright 2006-2017 Renzo Davoli University of Bologna - Italy * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * The GNU C Library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with the GNU C Library; if not, write to the Free * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * 02110-1301, USA. */ #include #include #include #include #include #include #include #include #include #include #include #define PURE_HASHSIZE 64 long _pure_debug_printf(const char *format, ...); struct pure_file { int fd; FILE *f; struct pure_file *next; }; static struct pure_file *pure_hash[PURE_HASHSIZE]; pthread_mutex_t _pure_mutex = PTHREAD_MUTEX_INITIALIZER; static int pure_hfun(FILE *f) { unsigned long l=(long)f; return (l+(l>>8)+(l>>16)) % PURE_HASHSIZE; } static ssize_t myread(void *cookie, char *buf, size_t count) { struct pure_file *p=cookie; return read(p->fd,buf,count); } static ssize_t mywrite(void *cookie, const char *buf, size_t count) { struct pure_file *p=cookie; return write(p->fd,buf,count); } static int mylseek(void *cookie, off64_t *offset, int whence) { struct pure_file *p=cookie; *offset=lseek64(p->fd,*offset,whence); if (*offset == -1) return -1; else return 0; } static void del_pure_file(struct pure_file *x); static int myclose(void *cookie) { struct pure_file *p=cookie; int rv; rv=close(p->fd); del_pure_file(p); return rv; } static cookie_io_functions_t _pure_funcs={ myread, mywrite, mylseek, myclose}; static FILE *new_pure_file(int fd, const char *modes) { struct pure_file *n=malloc(sizeof(struct pure_file)); if (n) { FILE *f=fopencookie(n,modes,_pure_funcs); if (f) { int hkey=pure_hfun(f); pthread_mutex_lock(&_pure_mutex); n->fd=fd; n->f=f; n->next=pure_hash[hkey]; pure_hash[hkey]=n; pthread_mutex_unlock(&_pure_mutex); //_pure_debug_printf("+%p %d\n",n,hkey); return f; } else { free(n); return NULL; } } else return NULL; } static int _pure_file_fd(FILE *f,int locked) { int hkey=pure_hfun(f); struct pure_file *n; int fd= -1; if (locked) pthread_mutex_lock(&_pure_mutex); n=pure_hash[hkey]; while (n && n->f != f) n=n->next; if (n) fd=n->fd; if (locked) pthread_mutex_unlock(&_pure_mutex); return fd; } static void del_pure_file(struct pure_file *x) { int hkey=pure_hfun(x->f); struct pure_file **n; pthread_mutex_lock(&_pure_mutex); n=&(pure_hash[hkey]); while (*n && *n != x) n=&((*n)->next); if (*n == x) *n=x->next; //_pure_debug_printf("-%p %d\n",x,hkey); pthread_mutex_unlock(&_pure_mutex); free(x); } int _pure_parse_mode(const char *modes) { int flags=0; while (*modes) { switch (*modes) { case 'r':flags=O_RDONLY;break; case 'w':flags=O_WRONLY|O_CREAT|O_TRUNC;break; case 'a':flags=O_WRONLY|O_CREAT|O_APPEND;break; case '+':flags &= ~(O_WRONLY | O_RDONLY); flags |= O_RDWR;break; } modes++; } return flags; } static FILE *_pure_fopen (const char *filename, const char * modes, int flags){ int fd; //_pure_debug_printf("_pure_fopen %s\n",filename); if ((fd=open(filename,flags,0666)) < 0) return NULL; else return new_pure_file(fd,modes); } FILE *fopen (const char *filename, const char *modes){ return _pure_fopen(filename, modes, _pure_parse_mode(modes)); } FILE *fopen64 (const char *filename, const char *modes){ return _pure_fopen(filename, modes, _pure_parse_mode(modes)|O_LARGEFILE); } FILE *fdopen (int fd, const char *modes){ return new_pure_file(fd,modes); } FILE *tmpfile (void){ int fd; char template[20] = "/tmp/tmpfile-XXXXXX"; if ((fd=mkstemp(template))<0) return 0; else { unlink(template); return new_pure_file(fd,"rw"); } } FILE *tmpfile64 (void){ int fd; char template[20] = "/tmp/tmpfile-XXXXXX"; if ((fd=mkstemp(template))<0) return 0; else { unlink(template); return new_pure_file(fd,"rw"); } } static FILE *_pure_freopen (const char *filename, const char *modes, FILE *stream){ if (stream == NULL) { errno=EINVAL; return NULL; } else { FILE *newstream=NULL; int fd=-1; int fdtmp=open(filename,_pure_parse_mode(modes),0666); if (fdtmp >= 0) { if (stream == stdout) fd=STDOUT_FILENO; else if (stream == stdin) fd=STDIN_FILENO; else if (stream == stderr) fd=STDERR_FILENO; fclose(stream); if (fd>=0) fd=dup2(fdtmp,fd); else fd=fdtmp; if (fd>=0) newstream=fdopen(fd,modes); if (isatty(fd)) setlinebuf(newstream); close(fdtmp); if (fd==STDOUT_FILENO) { stdout=newstream; return stdout; } else if (fd==STDIN_FILENO) { stdin=newstream; return stdin; } else if (fd==STDERR_FILENO) { stderr=newstream; return stderr; } else return newstream; } return newstream; } } FILE *freopen (const char *filename, const char *modes, FILE *stream){ return _pure_freopen(filename, modes, stream); } FILE *freopen64 (const char *filename, const char *modes, FILE *stream){ return _pure_freopen(filename, modes, stream); } int printf (const char *format, ...) { va_list arg; int done; va_start (arg, format); done = vfprintf (stdout, format, arg); va_end (arg); return done; } int putchar (c) int c; { return putc (c, stdout); } int scanf (const char *format, ...) { va_list arg; int done; va_start (arg, format); done = vfscanf (stdin, format, arg); va_end (arg); return done; } int getchar (void) { return getc(stdin); } char *gets(char *s) { return fgets(s, INT_MAX, stdin); } int puts(const char *s) { int rv; rv=fputs(s,stdout); if (rv!=EOF) rv=putc('\n',stdout); return rv; } /* this is convenient since casting the return value of dlsym() to * a function pointer erroneously procudes a warning */ #pragma GCC diagnostic ignored "-Wpedantic" int fileno (FILE *stream){ /*char buf[]="FNOxx\n"; buf[3]=(stream == NULL)?'X':'-'; buf[4]=(!_pure_magic(stream))?'X':'-'; write (2,buf,6);*/ if (stream == NULL) return -1; else { int rv=0; int (*_fileno)()=dlsym(RTLD_NEXT,"fileno"); if (_fileno) { rv=_fileno(stream); if (rv<0) { rv=_pure_file_fd(stream,1); if (rv>=0) errno=0; } } else rv= -1; return rv; } } int fileno_unlocked (FILE *stream){ /*char buf[]="FNOxx\n"; buf[3]=(stream == NULL)?'X':'-'; buf[4]=(!_pure_magic(stream))?'X':'-'; write (2,buf,6);*/ if (stream == NULL) return -1; else { int rv=0; int (*_fileno)()=dlsym(RTLD_NEXT,"fileno"); if (_fileno) { rv=_fileno(stream); if (rv<0) { rv=_pure_file_fd(stream,0); if (rv>=0) errno=0; } } else rv= -1; return rv; } } purelibc-1.0.6/syscalls.c000066400000000000000000001327561426423151100153410ustar00rootroot00000000000000/* This is part of pure_libc (a project related to ViewOS and Virtual Square) * * syscalls.c: syscall mgmt * * Copyright 2006-2021 Renzo Davoli University of Bologna - Italy * Copyright 2005 Andrea Gasparini University of Bologna - Italy * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * The GNU C Library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with the GNU C Library; if not, write to the Free * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * 02110-1301, USA. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "purelibc.h" /* in case of pre-init call, use syscall */ sfun _pure_syscall = syscall; sfun _pure_native_syscall; #if defined(__NR_mmap2) static int _pageshift() { static int ps=0; if (ps == 0) { long pagesize=pagesize = sysconf(_SC_PAGESIZE); for (ps = -1;pagesize > 0; ps++, pagesize >>= 1) ; } return ps; } #endif long _pure_debug_printf(const char *format, ...) { char *s; int rv; va_list ap; va_start(ap, format); rv=vasprintf(&s, format, ap); if (rv>0) _pure_native_syscall(__NR_write,2,s,strlen(s)); free(s); va_end(ap); return rv; } // open must consider two mode of calling: with two or three arguments int __open_2(const char* pathname,int flags){ #if defined(__NR_openat) && ! defined(__NR_open) return _pure_syscall(__NR_openat,AT_FDCWD,pathname,flags); #else return _pure_syscall(__NR_open,pathname,flags); #endif } static int __open_3(const char* pathname,int flags, mode_t mode) { #if defined(__NR_openat) && ! defined(__NR_open) return _pure_syscall(__NR_openat,AT_FDCWD,pathname,flags,mode); #else return _pure_syscall(__NR_open,pathname,flags,mode); #endif } int open(const char* pathname,int flags,...){ va_list arg_list; if( flags & O_CREAT ){ mode_t mode; va_start(arg_list,flags); mode = va_arg(arg_list,mode_t); va_end(arg_list); return __open_3(pathname,flags,mode); } else return __open_2(pathname,flags); } int open64(const char* pathname,int flags,...){ va_list arg_list; if( flags & O_CREAT ){ mode_t mode; va_start(arg_list,flags); mode = va_arg(arg_list,mode_t); va_end(arg_list); return __open_3(pathname,flags|O_LARGEFILE,mode); } else return __open_2(pathname,flags|O_LARGEFILE); } int __open64_2 (const char* pathname,int flags){ return __open_2(pathname,flags|O_LARGEFILE); } int creat(const char *pathname, mode_t mode) { return __open_3(pathname,O_CREAT|O_WRONLY|O_TRUNC,mode); } int creat64(const char *pathname, mode_t mode) { return __open_3(pathname,O_CREAT|O_WRONLY|O_TRUNC|O_LARGEFILE,mode); } int close(int fd){ return _pure_syscall(__NR_close,fd); } ssize_t read(int fd,void* buf,size_t count){ return _pure_syscall(__NR_read,fd,buf,count); } ssize_t write(int fd,const void* buf,size_t count){ return _pure_syscall(__NR_write,fd,buf,count); } ssize_t readv(int filedes, const struct iovec *vector, int count) { return _pure_syscall(__NR_readv, filedes, vector, count); } ssize_t writev(int filedes, const struct iovec *vector, int count) { return _pure_syscall(__NR_writev, filedes, vector, count); } int dup(int oldfd){ return _pure_syscall(__NR_dup, oldfd); } int dup2(int oldfd, int newfd){ #if defined(__NR_dup3) && ! defined(__NR_dup2) return _pure_syscall(__NR_dup3, oldfd, newfd, 0); #else return _pure_syscall(__NR_dup2, oldfd, newfd); #endif } #ifdef __NR_dup3 int dup3(int oldfd, int newfd, int flags){ return _pure_syscall(__NR_dup3, oldfd, newfd, flags); } #endif /* When is included, inline #defines for {,l,f}stat{,64} are * inserted and they make calls to __{,l,f}xstat{,64}. So we don't need * to define them. */ /* Since libc developers seem to be quite sadic in writing unreadable code, * making me go crazy trying to understand it, I decided to have some fun * myself. The following not-so-readable stuff takes care of calling the * correct 64-bit function on both 32 bit and 64 bit architectures.*/ /* update: glibc 2.33 has a simpler API, no more __ functions */ #ifdef __NR_fstatat64 #define __NR_FSTATAT64 __NR_fstatat64 #endif #ifdef __NR_newfstatat #define __NR_FSTATAT64 __NR_newfstatat #endif #if __WORDSIZE == 64 || defined(__ILP32__) # if defined(__NR_FSTATAT64) && ! defined(__NR_stat) # define __USE_FSTATAT64 # endif # define arch_stat64 stat # define IFNOT64(x) #else # if defined(__NR_FSTATAT64) && ! defined(__NR_stat64) # define __USE_FSTATAT64 # endif # define arch_stat64 stat64 # define IFNOT64(x) x #endif #define INTERNAL_MAKE_NAME(a, b) a ## b #define MAKE_NAME(a, b) INTERNAL_MAKE_NAME(a, b) static void arch_stat64_2_stat(struct arch_stat64 *from, struct stat *to) { if ((void*)from == (void*)to) return; to->st_dev = from->st_dev; to->st_ino = from->st_ino; to->st_mode = from->st_mode; to->st_nlink = from->st_nlink; to->st_uid = from->st_uid; to->st_gid = from->st_gid; to->st_rdev = from->st_rdev; to->st_size = from->st_size; to->st_blksize = from->st_blksize; to->st_blocks = from->st_blocks; to->st_atim = from->st_atim; to->st_mtim = from->st_mtim; to->st_ctim = from->st_ctim; return; } #if __GNUC_PREREQ (2,33) int stat(const char* pathname, struct stat* buf_stat) { IFNOT64(struct stat64 *buf_stat64 = alloca(sizeof(struct stat64));) int rv; #ifdef __USE_FSTATAT64 rv = _pure_syscall(__NR_FSTATAT64, AT_FDCWD, pathname, MAKE_NAME(buf_, arch_stat64), 0); #else rv = _pure_syscall(MAKE_NAME(__NR_, arch_stat64), pathname, MAKE_NAME(buf_, arch_stat64)); #endif if (rv >= 0) arch_stat64_2_stat(MAKE_NAME(buf_, arch_stat64), buf_stat); return rv; } int lstat(const char* pathname, struct stat* buf_stat) { IFNOT64(struct stat64 *buf_stat64 = alloca(sizeof(struct stat64));) int rv; #ifdef __USE_FSTATAT64 rv = _pure_syscall(__NR_FSTATAT64, AT_FDCWD, pathname, MAKE_NAME(buf_, arch_stat64), AT_SYMLINK_NOFOLLOW); #else rv = _pure_syscall(MAKE_NAME(__NR_l, arch_stat64), pathname, MAKE_NAME(buf_, arch_stat64)); #endif if (rv >= 0) arch_stat64_2_stat(MAKE_NAME(buf_, arch_stat64), buf_stat); return rv; } int fstat(int fildes, struct stat* buf_stat) { IFNOT64(struct stat64 *buf_stat64 = alloca(sizeof(struct stat64));) int rv; rv = _pure_syscall(MAKE_NAME(__NR_f, arch_stat64), fildes, MAKE_NAME(buf_, arch_stat64)); if (rv >= 0) arch_stat64_2_stat(MAKE_NAME(buf_, arch_stat64), buf_stat); return rv; } int stat64(const char* pathname,struct stat64* buf){ #ifdef __USE_FSTATAT64 return _pure_syscall(__NR_FSTATAT64, AT_FDCWD, pathname, buf, 0); #else return _pure_syscall(MAKE_NAME(__NR_, arch_stat64), pathname, buf); #endif } int lstat64(const char* pathname,struct stat64* buf){ #ifdef __USE_FSTATAT64 return _pure_syscall(__NR_FSTATAT64, AT_FDCWD, pathname, buf, AT_SYMLINK_NOFOLLOW); #else return _pure_syscall(MAKE_NAME(__NR_l, arch_stat64), pathname, buf); #endif } int fstat64 (int fildes, struct stat64 *buf){ return _pure_syscall(MAKE_NAME(__NR_f, arch_stat64), fildes, buf); } int mknod(const char *pathname, mode_t mode, dev_t dev) { #if defined(__NR_mknodat) && ! defined(__NR_mknod) return _pure_syscall(__NR_mknodat,AT_FDCWD,pathname,mode,dev); #else return _pure_syscall(__NR_mknod,pathname,mode,dev); #endif } #else int __xstat(int ver, const char* pathname, struct stat* buf_stat) { IFNOT64(struct stat64 *buf_stat64 = alloca(sizeof(struct stat64));) int rv; switch(ver) { case _STAT_VER_LINUX: #ifdef __USE_FSTATAT64 rv = _pure_syscall(__NR_FSTATAT64, AT_FDCWD, pathname, MAKE_NAME(buf_, arch_stat64), 0); #else rv = _pure_syscall(MAKE_NAME(__NR_, arch_stat64), pathname, MAKE_NAME(buf_, arch_stat64)); #endif break; default: _pure_debug_printf("*** BUG! *** __xstat can't manage version %d!\n", ver); abort(); } if (rv >= 0) arch_stat64_2_stat(MAKE_NAME(buf_, arch_stat64), buf_stat); return rv; } int __lxstat(int ver, const char* pathname, struct stat* buf_stat) { IFNOT64(struct stat64 *buf_stat64 = alloca(sizeof(struct stat64));) int rv; switch(ver) { case _STAT_VER_LINUX: #ifdef __USE_FSTATAT64 rv = _pure_syscall(__NR_FSTATAT64, AT_FDCWD, pathname, MAKE_NAME(buf_, arch_stat64), AT_SYMLINK_NOFOLLOW); #else rv = _pure_syscall(MAKE_NAME(__NR_l, arch_stat64), pathname, MAKE_NAME(buf_, arch_stat64)); #endif break; default: _pure_debug_printf("*** BUG! *** __lxstat can't manage version %d!\n", ver); abort(); } if (rv >= 0) arch_stat64_2_stat(MAKE_NAME(buf_, arch_stat64), buf_stat); return rv; } int __fxstat(int ver, int fildes, struct stat* buf_stat) { IFNOT64(struct stat64 *buf_stat64 = alloca(sizeof(struct stat64));) int rv; switch(ver) { case _STAT_VER_LINUX: rv = _pure_syscall(MAKE_NAME(__NR_f, arch_stat64), fildes, MAKE_NAME(buf_, arch_stat64)); break; default: _pure_debug_printf("*** BUG! *** __fxstat can't manage version %d!\n", ver); abort(); } if (rv >= 0) arch_stat64_2_stat(MAKE_NAME(buf_, arch_stat64), buf_stat); return rv; } int __xstat64(int ver,const char* pathname,struct stat64* buf){ #ifdef __USE_FSTATAT64 return _pure_syscall(__NR_FSTATAT64, AT_FDCWD, pathname, buf, 0); #else return _pure_syscall(MAKE_NAME(__NR_, arch_stat64), pathname, buf); #endif } int __lxstat64(int ver,const char* pathname,struct stat64* buf){ #ifdef __USE_FSTATAT64 return _pure_syscall(__NR_FSTATAT64, AT_FDCWD, pathname, buf, AT_SYMLINK_NOFOLLOW); #else return _pure_syscall(MAKE_NAME(__NR_l, arch_stat64), pathname, buf); #endif } int __fxstat64 (int ver, int fildes, struct stat64 *buf){ return _pure_syscall(MAKE_NAME(__NR_f, arch_stat64), fildes, buf); } #ifdef __NR_FSTATAT64 int __fxstatat64 (int ver, int dirfd, const char *pathname, struct stat64 *buf, int flags){ return _pure_syscall(__NR_FSTATAT64,dirfd,pathname,buf,flags); } int __fxstatat(int ver, int fildes, const char *pathname, struct stat* buf_stat,int flags) { IFNOT64(struct stat64 *buf_stat64 = alloca(sizeof(struct stat64));) int rv; switch(ver) { case _STAT_VER_LINUX: rv = _pure_syscall(__NR_FSTATAT64, fildes, pathname, MAKE_NAME(buf_, arch_stat64), flags); break; default: _pure_debug_printf("*** BUG! *** __fxstatat can't manage version %d!\n", ver); abort(); } if (rv >= 0) arch_stat64_2_stat(MAKE_NAME(buf_, arch_stat64), buf_stat); return rv; } #endif int __xmknod (int ver, const char *path, mode_t mode, dev_t *dev) { #if defined(__NR_mknodat) && ! defined(__NR_mknod) return _pure_syscall(__NR_mknodat,AT_FDCWD,path,mode,dev); #else return _pure_syscall(__NR_mknod,path,mode,dev); #endif } /* end of unreadable code */ #endif #ifdef __NR_FSTATAT64 int fstatat(int dirfd, const char *pathname, struct stat *buf, int flags) { return _pure_syscall(__NR_FSTATAT64,dirfd,pathname,buf,flags); } #endif #ifdef __NR_statx int statx(int dirfd, const char *pathname, int flags, unsigned int mask, struct statx *statxbuf) { return _pure_syscall(__NR_statx, dirfd, pathname, flags, mask, statxbuf); } #endif int access(const char* pathname,int mode){ #if defined(__NR_faccessat) && ! defined(__NR_access) return _pure_syscall(__NR_faccessat,AT_FDCWD,pathname,mode,0); #else return _pure_syscall(__NR_access,pathname,mode); #endif } int __access(const char* pathname,int mode){ return access(pathname,mode); } ssize_t readlink(const char* pathname,char* buf, size_t bufsize){ #if defined(__NR_readlinkat) && ! defined(__NR_readlink) return _pure_syscall(__NR_readlinkat,AT_FDCWD,pathname,buf,bufsize); #else return _pure_syscall(__NR_readlink,pathname,buf,bufsize); #endif } int mkdir(const char* pathname,mode_t mode){ #if defined(__NR_mkdirat) && ! defined(__NR_mkdir) return _pure_syscall(__NR_mkdirat,AT_FDCWD,pathname,mode); #else return _pure_syscall(__NR_mkdir,pathname,mode); #endif } int rmdir(const char* pathname){ #if defined(__NR_unlinkat) && ! defined(__NR_rmdir) return _pure_syscall(__NR_unlinkat,AT_FDCWD,pathname,AT_REMOVEDIR); #else return _pure_syscall(__NR_rmdir,pathname); #endif } int chmod(const char* pathname,mode_t mode){ #if defined(__NR_fchownat) && ! defined(__NR_chmod) return _pure_syscall(__NR_fchownat,AT_FDCWD,pathname,mode,0); #else return _pure_syscall(__NR_chmod,pathname,mode); #endif } int fchmod(int fd,mode_t mode){ return _pure_syscall(__NR_fchmod,fd,mode); } int chown(const char* pathname,uid_t owner,gid_t group){ #if defined(__NR_fchownat) && ! defined(__NR_chown) return _pure_syscall(__NR_fchownat,AT_FDCWD,pathname,owner,group,0); #else return _pure_syscall(__NR_chown,pathname,owner,group); #endif } int lchown(const char* pathname,uid_t owner,gid_t group){ #if defined(__NR_fchownat) && ! defined(__NR_lchown) return _pure_syscall(__NR_fchownat,AT_FDCWD,pathname,owner,group,AT_SYMLINK_NOFOLLOW); #else return _pure_syscall(__NR_lchown,pathname,owner,group); #endif } int fchown(int fd,uid_t owner,gid_t group){ return _pure_syscall(__NR_fchown,fd,owner,group); } int link(const char* pathname,const char*newpath){ #if defined(__NR_linkat) && ! defined(__NR_link) return _pure_syscall(__NR_linkat,AT_FDCWD,pathname,AT_FDCWD,newpath,0); #else return _pure_syscall(__NR_link,pathname,newpath); #endif } int unlink(const char* pathname){ #if defined(__NR_unlinkat) && ! defined(__NR_unlink) return _pure_syscall(__NR_unlinkat,AT_FDCWD,pathname,0); #else return _pure_syscall(__NR_unlink,pathname); #endif } int symlink(const char* pathname,const char* newpath){ #if defined(__NR_symlinkat) && ! defined(__NR_symlink) return _pure_syscall(__NR_symlinkat,pathname,AT_FDCWD,newpath,0); #else return _pure_syscall(__NR_symlink,pathname,newpath); #endif } int rename(const char *oldpath, const char *newpath){ #if defined(__NR_renameat2) && ! defined(__NR_rename) return _pure_syscall(__NR_renameat2,AT_FDCWD,oldpath,AT_FDCWD,newpath,0); #else return _pure_syscall(__NR_rename,oldpath,newpath); #endif } int chdir(const char *path) { return _pure_syscall(__NR_chdir,path); } int fchdir(int fd) { return _pure_syscall(__NR_fchdir,fd); } int utimes(const char* pathname,const struct timeval tv[2]){ #if defined(__NR_utimensat) && ! defined(__NR_utimes) struct timespec ts[2] = { {tv[0].tv_sec, tv[0].tv_usec * 1000}, {tv[1].tv_sec, tv[1].tv_usec * 1000}}; return _pure_syscall(__NR_utimensat, AT_FDCWD, pathname, ts, 0); #else return _pure_syscall(__NR_utimes,pathname,tv); #endif } int utime(const char* pathname,const struct utimbuf *buf){ #ifdef __NR_utime return _pure_syscall(__NR_utime,pathname,buf); #else struct timeval tv[2]; tv[0].tv_sec = buf->actime; tv[1].tv_sec = buf->modtime; tv[0].tv_usec = tv[1].tv_usec = 0; return utimes(pathname, tv); #endif } #ifdef __NR_pread ssize_t pread(int fs,void* buf, size_t count, __off_t offset){ return _pure_syscall(__NR_pread,fs,buf,count,offset); } #endif #ifdef __NR_pwrite ssize_t pwrite(int fs,const void* buf, size_t count, __off_t offset){ return _pure_syscall(__NR_pwrite,fs,buf,count,offset); } #endif #ifdef __NR_pread64 ssize_t pread64(int fs,void* buf, size_t count, __off64_t offset){ return _pure_syscall(__NR_pread64,fs,buf,count, #if defined(__powerpc__) || defined(__arm__) 0, #endif __LONG_LONG_PAIR( (__off_t)(offset>>32),(__off_t)(offset&0xffffffff))); } ssize_t pread(int fs,void* buf, size_t count, __off_t offset){ return pread64(fs,buf,count,(__off64_t)offset); } #endif #ifdef __NR_pwrite64 ssize_t pwrite64(int fs,const void* buf, size_t count, __off64_t offset){ return _pure_syscall(__NR_pwrite64,fs,buf,count, #if defined(__powerpc__) || defined(__arm__) 0, #endif __LONG_LONG_PAIR( (__off_t)(offset>>32),(__off_t)(offset&0xffffffff))); } ssize_t pwrite(int fs,const void* buf, size_t count, __off_t offset){ return pwrite64(fs,buf,count,(__off64_t)offset); } #endif #ifdef __NR_preadv ssize_t preadv64(int fs,const struct iovec *iov, int iovcnt, __off64_t offset){ ssize_t rv=_pure_syscall(__NR_preadv,fs,iov,iovcnt, #ifdef __NR_pread64 #if defined(__powerpc__) || defined(__arm__) 0, #endif __LONG_LONG_PAIR( (__off_t)(offset>>32),(__off_t)(offset&0xffffffff)) #else offset #endif ); if (rv==-1 && errno==ENOSYS) { ssize_t totalsize; unsigned char *buf,*scan; int i; for (i=totalsize=0; i0; i++, scan+=iov[i].iov_len, totalsize-=iov[i].iov_len) memcpy(iov[i].iov_base, scan, iov[i].iov_len); free(buf); } return rv; } ssize_t preadv(int fs,const struct iovec *iov, int iovcnt, __off_t offset){ return preadv64(fs,iov,iovcnt,(__off64_t)offset); } #endif #ifdef __NR_pwritev ssize_t pwritev64(int fs,const struct iovec *iov, int iovcnt, __off64_t offset){ ssize_t rv=_pure_syscall(__NR_pwritev,fs,iov,iovcnt, #ifdef __NR_pwrite64 #if defined(__powerpc__) || defined(__arm__) 0, #endif __LONG_LONG_PAIR( (__off_t)(offset>>32),(__off_t)(offset&0xffffffff)) #else offset #endif ); if (rv==-1 && errno==ENOSYS) { ssize_t totalsize; unsigned char *buf,*scan; int i; for (i=totalsize=0; i> (sizeof(unsigned long) * 8); unsigned long offset_low=offset; __off64_t result; int rv=_pure_syscall(__NR__llseek,fd,offset_high,offset_low,&result,whence); if (rv<0) return rv; else return result; } __off64_t llseek(int fd, __off64_t offset, int whence){ return lseek64(fd,offset,whence); } int _llseek(unsigned int fd, unsigned long offset_high, unsigned long offset_low, loff_t *result, unsigned int whence){ return _pure_syscall(__NR__llseek,fd,offset_high,offset_low,result,whence); } #endif int fsync(int fd){ return _pure_syscall(__NR_fsync,fd); } #if defined(__powerpc__) /* DAMNED! Another kernel specific structure needs lib conversion! */ #include #include #include"kernel_termios.ppc.h" static void termios_k2l(struct termios *dst,struct __kernel_termios *src) { register int i; dst->c_iflag = src->c_iflag; dst->c_oflag = src->c_oflag; dst->c_cflag = src->c_cflag; dst->c_lflag = src->c_lflag; dst->c_line = src->c_line; dst->c_ispeed = src->c_ispeed; dst->c_ospeed = src->c_ospeed; for (i=0; i<__KERNEL_NCCS; i++) dst->c_cc[i]=src->c_cc[i]; for (;ic_cc[i]=_POSIX_VDISABLE; } static void termios_l2k(struct __kernel_termios *dst,struct termios *src) { register int i; dst->c_iflag = src->c_iflag; dst->c_oflag = src->c_oflag; dst->c_cflag = src->c_cflag; dst->c_lflag = src->c_lflag; dst->c_line = src->c_line; dst->c_ispeed = src->c_ispeed; dst->c_ospeed = src->c_ospeed; for (i=0; i<__KERNEL_NCCS; i++) dst->c_cc[i]=src->c_cc[i]; } static int ioctl_ppc(int fd,unsigned long int request, long int arg){ int result; switch (request) { case TCGETS: { struct __kernel_termios kt; result = _pure_syscall (__NR_ioctl, fd, request, &kt); termios_k2l((struct termios *) arg, &kt); break; } case TCSETS: case TCSETSW: case TCSETSF: { struct __kernel_termios kt; termios_l2k(&kt,(struct termios *) arg); result = _pure_syscall (__NR_ioctl, fd, request, &kt); break; } default: result = _pure_syscall (__NR_ioctl, fd, request, arg); break; } return result; } #endif int ioctl(int fd,unsigned long int request, ...){ va_list ap; long int arg; va_start(ap, request); arg=va_arg(ap, long int); va_end(ap); int rv=0; #if defined(__powerpc__) ioctl_ppc(fd,request,arg); #else rv= _pure_syscall(__NR_ioctl,fd,request,arg); #endif return rv; } int fcntl(int fd, int cmd, ...){ va_list ap; long int arg1; long int arg2; va_start(ap, cmd); arg1=va_arg(ap, long int); arg2=va_arg(ap, long int); va_end(ap); /* XXX Check the fcntl->fcntl64 conversion */ #ifdef __NR_fcntl64 switch (cmd) { case F_GETLK: case F_SETLK: case F_SETLKW: return _pure_syscall(__NR_fcntl,fd,cmd,arg1,arg2); default: return _pure_syscall(__NR_fcntl64,fd,cmd,arg1,arg2); } #else return _pure_syscall(__NR_fcntl,fd,cmd,arg1,arg2); #endif } #ifdef __NR_fcntl64 int fcntl64(int fd, int cmd, ...){ va_list ap; long int arg1; long int arg2; va_start(ap, cmd); arg1=va_arg(ap, long int); arg2=va_arg(ap, long int); va_end(ap); return _pure_syscall(__NR_fcntl64,fd,cmd,arg1,arg2); } #endif int mount(const char *source, const char *target, const char *filesystemtype, unsigned mountflags, const void *data){ return _pure_syscall(__NR_mount,source,target,filesystemtype,mountflags,data); } #ifndef __NR_umount #define __NR_umount __NR_umount2 #endif int umount(const char *target){ // umount ignore the last argument, is only for umount2 return _pure_syscall(__NR_umount,target,0); } int umount2(const char *target, int flags){ return _pure_syscall(__NR_umount,target,flags); } pid_t getpid(void){ return _pure_syscall(__NR_getpid); } pid_t getppid(void){ return _pure_syscall(__NR_getppid); } int setpgid(pid_t pid, pid_t pgid){ return _pure_syscall(__NR_setpgid,pid,pgid); } pid_t getpgid(pid_t pid){ return _pure_syscall(__NR_getpgid,pid); } int setpgrp(void){ return _pure_syscall(__NR_setpgid,0,0); } pid_t getpgrp(void){ return _pure_syscall(__NR_getpgid,0); } int setuid(uid_t uid){ return _pure_syscall(__NR_setuid,uid); } int setgid(gid_t gid){ return _pure_syscall(__NR_setgid,gid); } int seteuid(uid_t euid){ return _pure_syscall(__NR_setreuid,-1,euid); } int setegid(gid_t egid){ return _pure_syscall(__NR_setregid,-1,egid); } uid_t getuid(void) { return _pure_syscall(__NR_getuid); } uid_t __getuid(void) { return getuid(); } gid_t getgid(void) { return _pure_syscall(__NR_getgid); } gid_t __getgid(void) { return getgid(); } uid_t geteuid(void) { return _pure_syscall(__NR_geteuid); } uid_t __geteuid(void) { return geteuid(); } gid_t getegid(void) { return _pure_syscall(__NR_getegid); } gid_t __getegid(void) { return getegid(); } int setreuid(uid_t ruid, uid_t euid){ return _pure_syscall(__NR_setreuid,ruid,euid); } int setregid(gid_t rgid, gid_t egid){ return _pure_syscall(__NR_setregid,rgid,egid); } int setresuid(uid_t ruid, uid_t euid, uid_t suid){ return _pure_syscall(__NR_setresuid,ruid,euid,suid); } int setresgid(gid_t rgid, gid_t egid, gid_t sgid){ return _pure_syscall(__NR_setresgid,rgid,egid,sgid); } int pipe(int filedes[2]) { #if defined(__NR_pipe2) && ! defined(__NR_pipe) return _pure_syscall(__NR_pipe2,filedes, 0); #else return _pure_syscall(__NR_pipe,filedes); #endif } #ifdef __NR_pipe2 int pipe2(int filedes[2],int flags) { return _pure_syscall(__NR_pipe2,filedes,flags); } #endif mode_t umask(mode_t mask){ return _pure_syscall(__NR_umask,mask); } int chroot(const char *path){ return _pure_syscall(__NR_chroot,path); } int execve(const char *filename, char *const argv [], char *const envp[]) { return _pure_syscall(__NR_execve,filename,argv,envp); } void _exit(int status){ _pure_syscall(__NR_exit,status); /* never reached, just to avoid "noreturn" warnings */ _exit(status); } void _Exit(int status){ _pure_syscall(__NR_exit,status); /* never reached, just to avoid "noreturn" warnings */ _exit(status); } pid_t fork(void){ #if defined(__ia64__) int child_tid; if (_pure_syscall(__NR_clone2, CLONE_CHILD_SETTID | CLONE_CHILD_CLEARTID | SIGCHLD, NULL, 0, NULL, &child_tid, NULL) < 0) return -1; else return child_tid; #elif defined(__aarch64__) || defined(__riscv) && __riscv_xlen==64 int child_tid; if (_pure_syscall(__NR_clone, NULL, CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, &child_tid) < 0) return -1; else return child_tid; #else return _pure_syscall(__NR_fork); #endif } pid_t vfork(void){ /*The BSD man page states: "This system call will be eliminated when * proper system sharing mechanisms are implemented. Users should not * depend on the memory sharing semantics of vfork() as it will, in that * case, be made synonymous to fork(2)." */ return fork(); } int stime(const time_t *t){ struct timeval tivu = { *t,0}; return _pure_syscall(__NR_settimeofday,&tivu,NULL); } long int ptrace (enum __ptrace_request request, ...){ va_list ap; pid_t pid; void *addr; void *data; long int res, ret; va_start(ap, request); pid=va_arg(ap, pid_t); addr=va_arg(ap, void *); data=va_arg(ap, void *); va_end(ap); if (request > 0 && request < 4) data = &ret; res = _pure_syscall(__NR_ptrace,request,pid,addr,data); if (res >= 0 && request > 0 && request < 4) { errno = 0; return ret; } else return res; } int nice(int inc){ #if defined(__x86_64__) || defined(__ia64__) || \ defined(__alpha__) || defined(__s390x__) || \ (defined(__mips__) && defined(__LP64__)) || \ defined(__aarch64__) || \ (defined(__riscv) && __riscv_xlen==64) int nice = _pure_syscall(__NR_getpriority,PRIO_PROCESS,0); return _pure_syscall(__NR_setpriority,PRIO_PROCESS,0,nice + inc); #else return _pure_syscall(__NR_nice,inc); #endif } void sync(void){ _pure_syscall(__NR_sync); } clock_t times(struct tms *buf){ return _pure_syscall(__NR_times,buf); } struct ustat; int ustat(dev_t dev, struct ustat *ubuf){ #ifdef __NR_ustat return _pure_syscall(__NR_ustat,dev,ubuf); #else errno = ENOSYS; return -1; #endif } pid_t getsid(pid_t pid){ return _pure_syscall(__NR_getsid,pid); } pid_t setsid(void){ return _pure_syscall(__NR_setsid); } int sethostname(const char *name, size_t len){ return _pure_syscall(__NR_sethostname,name,len); } #ifdef __NR_prlimit64 int prlimit(pid_t pid, enum __rlimit_resource resource, const struct rlimit *new_limit, struct rlimit *old_limit) { return _pure_syscall(__NR_prlimit64, pid, resource, new_limit, old_limit); } int setrlimit(__rlimit_resource_t resource, const struct rlimit *rlim){ return prlimit(0,resource,rlim,NULL); } int getrlimit(__rlimit_resource_t resource, struct rlimit *rlim){ return prlimit(0,resource,NULL,rlim); } #else int setrlimit(__rlimit_resource_t resource, const struct rlimit *rlim){ return _pure_syscall(__NR_setrlimit,resource,rlim); } int getrlimit(__rlimit_resource_t resource, struct rlimit *rlim){ return _pure_syscall(__NR_getrlimit,resource,rlim); } #endif int getrusage(int who, struct rusage *usage){ return _pure_syscall(__NR_getrusage,usage); } #ifdef GETTIMEOFDAY_TZ int gettimeofday(struct timeval *tv, struct timezone *tz) #else int gettimeofday(struct timeval *tv, void *tz) #endif { return _pure_syscall(__NR_gettimeofday, tv, tz); } int settimeofday(const struct timeval *tv , const struct timezone *tz){ return _pure_syscall(__NR_settimeofday, tv, tz); } time_t time(time_t *t){ #ifdef __NR_time return _pure_syscall(__NR_time,t); #else struct timeval tv; if (gettimeofday(&tv, NULL) == 0) { if (t) *t = tv.tv_sec; return tv.tv_sec; } else return -1; #endif } int getgroups(int size, gid_t list[]){ return _pure_syscall(__NR_getgroups,size,list); } #ifdef __NR_faccessat static int _is_group_member(gid_t gid) { int len = getgroups(0, NULL); gid_t list[len]; int i; len = getgroups(len, list); for (i = 0; i < len; i++) { if (gid == list[i]) return 1; } return 0; } #endif int setgroups(size_t size, const gid_t *list){ return _pure_syscall(__NR_setgroups,size,list); } int pselect(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, const struct timespec *timeout, const sigset_t *sigmask) { return _pure_syscall(__NR_pselect6,nfds, readfds, writefds, exceptfds, timeout, sigmask); } int ppoll(struct pollfd *fds, nfds_t nfds, const struct timespec *tmo_p, const sigset_t *sigmask) { return _pure_syscall(__NR_ppoll,fds,nfds,tmo_p,sigmask); } #ifdef __NR_epoll_create1 int select(int n, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout){ #if defined(__x86_64__) || defined(__s390x__) || \ defined(__alpha__) || defined(__ia64__) return _pure_syscall(__NR_select,n,readfds,writefds,exceptfds,timeout); #elif defined(__aarch64__) || defined(__riscv) && __riscv_xlen==64 if (timeout == NULL) return pselect(n,readfds,writefds,exceptfds,NULL,NULL); else { struct timespec ts = {timeout->tv_sec, timeout->tv_usec * 1000}; return pselect(n,readfds,writefds,exceptfds,&ts,NULL); } #else return _pure_syscall(__NR__newselect,n,readfds,writefds,exceptfds,timeout); #endif } int poll(struct pollfd *ufds, nfds_t nfds, int timeout){ #if defined(__NR_poll) return _pure_syscall(__NR_poll,ufds,nfds,timeout); #else if (timeout < 0) return _pure_syscall(__NR_ppoll,ufds,nfds, NULL, NULL); else { struct timespec ts = {timeout, 0}; return _pure_syscall(__NR_ppoll,ufds,nfds, &ts, NULL); } #endif } int epoll_create1(int flags) { return _pure_syscall(__NR_epoll_create1, flags); } int epoll_create(int size) { if (size <= 0) { errno = EINVAL; return -1; } else return _pure_syscall(__NR_epoll_create1, 0); } int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event) { return _pure_syscall(__NR_epoll_ctl,epfd,op,fd,event); } int epoll_wait(int epfd, struct epoll_event *events, int maxevents, int timeout) { return _pure_syscall(__NR_epoll_pwait,epfd,events,maxevents,timeout,NULL); } int epoll_pwait(int epfd, struct epoll_event *events, int maxevents, int timeout, const sigset_t *sigmask) { return _pure_syscall(__NR_epoll_pwait,epfd,events,maxevents,timeout,sigmask); } #endif int truncate(const char *path, __off_t length){ return _pure_syscall(__NR_truncate,path,length); } int ftruncate(int fd, __off_t length){ return _pure_syscall(__NR_ftruncate,fd,length); } #ifdef __NR_truncate64 int truncate64(const char *path, __off64_t length){ return _pure_syscall(__NR_truncate64,path, #if defined(__powerpc__) 0, #endif __LONG_LONG_PAIR( (__off_t)(length>>32),(__off_t)(length&0xffffffff))); } #endif #ifdef __NR_ftruncate64 int ftruncate64(int fd, __off64_t length){ return _pure_syscall(__NR_ftruncate64,fd, #if defined(__powerpc__) 0, #endif __LONG_LONG_PAIR( (__off_t)(length>>32),(__off_t)(length&0xffffffff))); } #endif int getpriority(__priority_which_t which, id_t who){ return _pure_syscall(__NR_getpriority,which,who); } int setpriority(__priority_which_t which, id_t who, int prio){ return _pure_syscall(__NR_setpriority,which,who,prio); } int statfs(const char *path, struct statfs *buf){ return _pure_syscall(__NR_statfs,path,buf); } int fstatfs(int fd, struct statfs *buf){ return _pure_syscall(__NR_fstatfs,fd,buf); } #ifdef __NR_statfs64 /* LIBC add an extra arg: the buf size */ int statfs64(const char *path, struct statfs64 *buf){ return _pure_syscall(__NR_statfs64,path,sizeof(struct statfs64), buf); } #endif #ifdef __NR_fstatfs64 int fstatfs64(int fd, struct statfs64 *buf){ return _pure_syscall(__NR_fstatfs64,fd,sizeof(struct statfs64), buf); } #endif int getitimer(__itimer_which_t which, struct itimerval *value){ return _pure_syscall(__NR_getitimer,which,value); } int setitimer(__itimer_which_t which, const struct itimerval *value, struct itimerval *ovalue){ return _pure_syscall(__NR_setitimer,which,value,ovalue); } pid_t waitpid(pid_t pid, int *status, int options){ return _pure_syscall(__NR_wait4,pid,status,options,NULL); } #ifdef __NR_waitid int waitid(idtype_t idtype, id_t id, siginfo_t *infop, int options){ return _pure_syscall(__NR_waitid,idtype,id,infop,options); } #endif pid_t wait3(int *status, int options, struct rusage *rusage){ return _pure_syscall(__NR_wait4,-1,status,options,rusage); } pid_t wait4(pid_t pid, int *status, int options, struct rusage *rusage){ return _pure_syscall(__NR_wait4,pid,status,options,rusage); } int sysinfo(struct sysinfo *info){ return _pure_syscall(__NR_sysinfo,info); } #ifdef __NR_ipc int ipc(unsigned int call, int first, int second, int third, void *ptr, long fifth){ return _pure_syscall(__NR_ipc,first,second,third,ptr,fifth); } #endif int setdomainname(const char *name, size_t len){ return _pure_syscall(__NR_setdomainname,name,len); } int uname(struct utsname *buf){ return _pure_syscall(__NR_uname,buf); } int adjtimex(struct timex *buf){ return _pure_syscall(__NR_adjtimex,buf); } #ifdef __NR_sysfs int sysfs(int option,...){ switch (option) { case 1: { va_list ap; char *fsname; va_start(ap, option); fsname=va_arg(ap, char *); va_end(ap); return _pure_syscall(__NR_sysfs,option,fsname); } case 2: { va_list ap; unsigned int fs_index; char *buf; va_start(ap, option); fs_index=va_arg(ap, unsigned int); buf=va_arg(ap, char *); va_end(ap); return _pure_syscall(__NR_sysfs,option,fs_index,buf); } case 3: return _pure_syscall(__NR_sysfs,option); default: errno=EINVAL; return -1; } } #endif int setfsuid(uid_t fsuid){ return _pure_syscall(__NR_setfsuid,fsuid); } int setfsgid(uid_t fsgid){ return _pure_syscall(__NR_setfsgid,fsgid); } int flock(int fd, int operation){ return _pure_syscall(__NR_flock,fd,operation); } int fdatasync(int fd){ return _pure_syscall(__NR_fdatasync,fd); } char *getcwd(char *buf, size_t size){ int rsize; if (size == 0 && buf==NULL) { size=PATH_MAX; buf=malloc(size); if (buf==NULL) return NULL; else { rsize=_pure_syscall(__NR_getcwd,buf,size); if (rsize>=0) { buf=realloc(buf,rsize); return buf; } else { free(buf); return NULL; } } } else { rsize=_pure_syscall(__NR_getcwd,buf,size); if (rsize>=0) return buf; else return NULL; } } ssize_t sendfile(int out_fd, int in_fd, off_t *offset, size_t count){ return _pure_syscall(__NR_sendfile,out_fd,in_fd,offset,count); } /* pid_t gettid(void){ return _pure_syscall(__NR_gettid); }*/ int setxattr (const char *path, const char *name, const void *value, size_t size, int flags){ return _pure_syscall(__NR_setxattr,path,name,value,size,flags); } int lsetxattr (const char *path, const char *name, const void *value, size_t size, int flags){ return _pure_syscall(__NR_lsetxattr,path,name,value,size,flags); } int fsetxattr (int fd, const char *name, const void *value, size_t size, int flags){ return _pure_syscall(__NR_fsetxattr,fd,name,value,size,flags); } ssize_t getxattr (const char *path, const char *name, void *value, size_t size){ return _pure_syscall(__NR_getxattr,path,name,value,size); } ssize_t lgetxattr (const char *path, const char *name, void *value, size_t size){ return _pure_syscall(__NR_lgetxattr,path,name,value,size); } ssize_t fgetxattr (int fd, const char *name, void *value, size_t size) { return _pure_syscall(__NR_fgetxattr,fd,name,value,size); } ssize_t listxattr (const char *path, char *list, size_t size){ return _pure_syscall(__NR_listxattr,path,list,size); } ssize_t llistxattr (const char *path, char *list, size_t size){ return _pure_syscall(__NR_llistxattr,path,list,size); } ssize_t flistxattr (int fd, char *list, size_t size){ return _pure_syscall(__NR_flistxattr,fd,list,size); } int removexattr (const char *path, const char *name){ return _pure_syscall(__NR_removexattr,path,name); } int lremovexattr (const char *path, const char *name){ return _pure_syscall(__NR_lremovexattr,path,name); } int fremovexattr (int fd, const char *name){ return _pure_syscall(__NR_fremovexattr,fd,name); } int clock_getres(clockid_t clk_id, struct timespec *res){ return _pure_syscall(__NR_clock_getres,clk_id,res); } int clock_gettime(clockid_t clk_id, struct timespec *tp){ return _pure_syscall(__NR_clock_gettime,clk_id,tp); } int clock_settime(clockid_t clk_id, const struct timespec *tp){ return _pure_syscall(__NR_clock_settime,clk_id,tp); } static void statfs2vfs(struct statfs *sfs,struct statvfs *vsfs) { vsfs->f_bsize=sfs->f_bsize; vsfs->f_frsize=0; vsfs->f_blocks=sfs->f_blocks; vsfs->f_bfree=sfs->f_bfree; vsfs->f_bavail=sfs->f_bavail; vsfs->f_files=sfs->f_files; vsfs->f_ffree=sfs->f_ffree; vsfs->f_favail=sfs->f_ffree; /*vsfs->f_fsid=sfs->f_fsid;*/ vsfs->f_flag=0; vsfs->f_namemax=sfs->f_namelen; } int statvfs(const char *path, struct statvfs *buf){ struct statfs sfs; int rv=_pure_syscall(__NR_statfs,path,&sfs); if (rv >= 0) statfs2vfs(&sfs,buf); return rv; } int fstatvfs(int fd, struct statvfs *buf){ struct statfs sfs; int rv=_pure_syscall(__NR_fstatfs,fd,&sfs); if (rv >= 0) statfs2vfs(&sfs,buf); return rv; } void *mmap(void *start, size_t length, int prot, int flags, int fd, off_t offset) { #if defined(__NR_mmap2) return (void *) _pure_syscall(__NR_mmap2,start,length,prot,flags,fd,offset>> _pageshift()); #else return (void *) _pure_syscall(__NR_mmap,start,length,prot,flags,fd,offset); #endif } #if defined(__NR_mmap2) void *mmap2(void *start, size_t length, int prot, int flags, int fd, off_t pgoffset) { return (void *) _pure_syscall(__NR_mmap2,start,length,prot,flags,fd,pgoffset); } #endif int munmap(void *start, size_t length) { return _pure_syscall(__NR_munmap,start,length); } #if __GLIBC__ >= 2 && __GLIBC_MINOR__ >= 5 void *mremap(void *old_address, size_t old_size , size_t new_size, int flags, ...) { va_list ap; va_start (ap, flags); void *newaddr = (flags & MREMAP_FIXED) ? va_arg (ap, void *) : NULL; va_end (ap); return (void *) _pure_syscall(__NR_mremap,old_address,old_size,new_size,flags,newaddr); } #else void *mremap(void *old_address, size_t old_size , size_t new_size, int flags) { return (void *) _pure_syscall(__NR_mremap,old_address,old_size,new_size,flags); } #endif int ftime(struct timeb *tp){ struct timeval tv; struct timezone tz; int rv=gettimeofday(&tv,&tz); tp->time = tv.tv_sec; tp->millitm = tv.tv_usec/1000; tp->timezone = timezone; tp->dstflag = daylight; return rv; } /* *at syscalls */ #ifdef __NR_openat int openat(int dirfd,const char* pathname,int flags,...){ va_list arg_list; if( flags & O_CREAT ){ mode_t mode; va_start(arg_list,flags); mode = va_arg(arg_list,mode_t); va_end(arg_list); return _pure_syscall(__NR_openat,dirfd,pathname,flags,mode); } else return _pure_syscall(__NR_openat,dirfd,pathname,flags); } int openat64(int dirfd,const char* pathname,int flags,...){ va_list arg_list; if( flags & O_CREAT ){ mode_t mode; va_start(arg_list,flags); mode = va_arg(arg_list,mode_t); va_end(arg_list); return _pure_syscall(__NR_openat,dirfd,pathname,flags|O_LARGEFILE,mode); } else return _pure_syscall(__NR_openat,dirfd,pathname,flags|O_LARGEFILE); } int __openat_2(int dirfd, const char *pathname, int flags) { return _pure_syscall(__NR_openat,dirfd,pathname,flags); } int __openat64_2(int dirfd, const char *pathname, int flags) { return _pure_syscall(__NR_openat,dirfd,pathname,flags|O_LARGEFILE); } #endif #ifdef __NR_mkdirat int mkdirat(int dirfd,const char* pathname,mode_t mode){ return _pure_syscall(__NR_mkdirat,dirfd,pathname,mode); } #endif #ifdef __NR_mknodat int mknodat(int dirfd,const char *pathname, mode_t mode, dev_t dev) { return _pure_syscall(__NR_mknodat,dirfd,pathname,mode,dev); } #endif #ifdef __NR_fchownat int fchownat(int dirfd, const char *pathname, uid_t owner, gid_t group, int flags) { return _pure_syscall(__NR_fchownat,dirfd,pathname,owner,group,flags); } #endif #ifdef __NR_futimesat int futimesat(int dirfd, const char *pathname, const struct timeval times[2]) { return _pure_syscall(__NR_futimesat,dirfd,pathname,times); } #endif #ifdef __NR_unlinkat int unlinkat(int dirfd, const char *pathname, int flags){ return _pure_syscall(__NR_unlinkat,dirfd,pathname,flags); } #endif #ifdef __NR_renameat int renameat(int olddirfd, const char *oldpath,int newdirfd, const char *newpath){ return _pure_syscall(__NR_renameat,olddirfd,oldpath,newdirfd,newpath); } #endif #ifdef __NR_renameat2 int renameat2(int olddirfd, const char *oldpath,int newdirfd, const char *newpath, unsigned int flags){ return _pure_syscall(__NR_renameat2,olddirfd,oldpath,newdirfd,newpath,flags); } #endif #ifdef __NR_linkat int linkat(int olddirfd, const char *oldpath,int newdirfd, const char *newpath, int flags){ return _pure_syscall(__NR_linkat,olddirfd,oldpath,newdirfd,newpath,flags); } #endif #ifdef __NR_symlinkat int symlinkat(const char *oldpath, int newdirfd, const char *newpath){ return _pure_syscall(__NR_symlinkat,oldpath,newdirfd,newpath); } #endif #ifdef __NR_readlinkat ssize_t readlinkat(int dirfd, const char *pathname,char *buf, size_t bufsiz){ return _pure_syscall(__NR_readlinkat,dirfd,pathname,buf,bufsiz); } #endif #ifdef __NR_fchmodat int fchmodat(int dirfd, const char *pathname, mode_t mode, int flags){ return _pure_syscall(__NR_fchmodat,dirfd,pathname,mode,flags); } #endif #ifdef __NR_faccessat //The raw faccessat() system call takes only the first three arguments // this function has been inspired by glibc: sysdeps/unix/sysv/linux/faccessat.c int faccessat(int dirfd, const char *pathname, int mode, int flags){ if (flags & ~(AT_EACCESS | AT_SYMLINK_NOFOLLOW)) { errno = EINVAL; return -1; } if (flags == 0) return _pure_syscall(__NR_faccessat,dirfd,pathname,mode); else { struct stat stats; if (fstatat(dirfd, pathname, &stats, flags & AT_SYMLINK_NOFOLLOW) < 0) return -1; mode &= (R_OK | W_OK | X_OK); if (mode == F_OK) return 0; uid_t uid = (flags & AT_EACCESS) ? geteuid() : getuid(); if (uid == 0) { // it is root if ((mode & X_OK) == 0) // RW are always allowed return 0; // X OK is X is okay for someone if (stats.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH)) return 0; } int granted; if (uid == stats.st_uid) // user permissions granted = (int) ((stats.st_mode >> 6) & mode); else { gid_t gid = (flags & AT_EACCESS) ? getegid() : getgid(); if (stats.st_gid == gid || _is_group_member(stats.st_gid)) // group permissions granted = (int) ((stats.st_mode >> 3) & mode); else // other permissions granted = stats.st_mode & mode; } if (granted == mode) return 0; errno = EACCES; return -1; } } int euidaccess(const char *pathname, int mode){ return faccessat(AT_FDCWD,pathname,mode,AT_EACCESS); } int eaccess(const char *pathname, int mode){ return euidaccess(pathname,mode); } int __euidaccess(const char *pathname, int mode){ return euidaccess(pathname,mode); } #endif #ifdef __NR_utimensat int utimensat(int dirfd, const char *pathname, const struct timespec times[2], int flags){ return _pure_syscall(__NR_utimensat,dirfd,pathname,times,flags); } #endif int raise(int sig) { return kill(getpid(), sig); } static void init(void); long int syscall(long int n,...) { long int arg0,arg1,arg2,arg3,arg4,arg5; va_list ap; va_start(ap, n); arg0=va_arg(ap, long int); arg1=va_arg(ap, long int); arg2=va_arg(ap, long int); arg3=va_arg(ap, long int); arg4=va_arg(ap, long int); arg5=va_arg(ap, long int); va_end(ap); /* in case of pre-init call: emergency initialization */ if (__builtin_expect(_pure_native_syscall == NULL,0)) init(); if (__builtin_expect(_pure_syscall == syscall,0)) return _pure_native_syscall(n,arg0,arg1,arg2,arg3,arg4,arg5); else return _pure_syscall(n,arg0,arg1,arg2,arg3,arg4,arg5); } sfun _pure_start(sfun pure_syscall, int flags) { int fdtmp; if (__builtin_expect(_pure_native_syscall == syscall,0)) init(); if (flags & PUREFLAG_STDIN) { fdtmp=dup(fileno(stdin)); dup2(fdtmp,STDIN_FILENO); stdin=fdopen(STDIN_FILENO,"r"); if (isatty(STDIN_FILENO)) setlinebuf(stdin); close(fdtmp); } if (flags & PUREFLAG_STDOUT) { fdtmp=dup(fileno(stdout)); dup2(fdtmp,STDOUT_FILENO); stdout=fdopen(STDOUT_FILENO,"w"); if (isatty(STDOUT_FILENO)) setlinebuf(stdout); close(fdtmp); } if (flags & PUREFLAG_STDERR) { fdtmp=dup(fileno(stderr)); dup2(fdtmp,STDERR_FILENO); stderr=fdopen(STDERR_FILENO,"a"); if (isatty(STDERR_FILENO)) setlinebuf(stderr); close(fdtmp); } _pure_syscall=pure_syscall; return _pure_native_syscall; } /* this is convenient since casting the return value of dlsym() to * a function pointer erroneously procudes a warning */ #pragma GCC diagnostic ignored "-Wpedantic" __attribute__ ((constructor)) static void init (void) { _pure_native_syscall = _pure_syscall = dlsym(RTLD_NEXT,"syscall"); }